Create scopes for switches/whiles/do-whiles

The C standard has required this since at least C99.
A new scope should also be created for ifs, but that's currently
breaking tests2/122_vla_reuse.
This commit is contained in:
Petr Skocik 2023-03-05 22:31:40 +01:00
parent 29ae3ed4d5
commit ccc1651075
3 changed files with 53 additions and 1 deletions

View file

@ -6832,6 +6832,7 @@ again:
tcc_tcov_check_line (tcc_state, 0), tcc_tcov_block_begin (tcc_state); tcc_tcov_check_line (tcc_state, 0), tcc_tcov_block_begin (tcc_state);
if (t == TOK_IF) { if (t == TOK_IF) {
//new_scope(&o); //?? breaks tests2.122
skip('('); skip('(');
gexpr(); gexpr();
skip(')'); skip(')');
@ -6846,8 +6847,10 @@ again:
} else { } else {
gsym(a); gsym(a);
} }
//prev_scope(&o,0); //?? breaks tests2.122
} else if (t == TOK_WHILE) { } else if (t == TOK_WHILE) {
new_scope(&o);
d = gind(); d = gind();
skip('('); skip('(');
gexpr(); gexpr();
@ -6858,7 +6861,7 @@ again:
gjmp_addr(d); gjmp_addr(d);
gsym_addr(b, d); gsym_addr(b, d);
gsym(a); gsym(a);
prev_scope(&o,0);
} else if (t == '{') { } else if (t == '{') {
new_scope(&o); new_scope(&o);
@ -6970,6 +6973,7 @@ again:
prev_scope(&o, 0); prev_scope(&o, 0);
} else if (t == TOK_DO) { } else if (t == TOK_DO) {
new_scope(&o);
a = b = 0; a = b = 0;
d = gind(); d = gind();
lblock(&a, &b); lblock(&a, &b);
@ -6979,6 +6983,7 @@ again:
gexpr(); gexpr();
skip(')'); skip(')');
skip(';'); skip(';');
prev_scope(&o,0);
c = gvtst(0, 0); c = gvtst(0, 0);
gsym_addr(c, d); gsym_addr(c, d);
gsym(a); gsym(a);
@ -6986,6 +6991,7 @@ again:
} else if (t == TOK_SWITCH) { } else if (t == TOK_SWITCH) {
struct switch_t *sw; struct switch_t *sw;
new_scope(&o);
sw = tcc_mallocz(sizeof *sw); sw = tcc_mallocz(sizeof *sw);
sw->bsym = &a; sw->bsym = &a;
sw->scope = cur_scope; sw->scope = cur_scope;
@ -7031,6 +7037,7 @@ again:
dynarray_reset(&sw->p, &sw->n); dynarray_reset(&sw->p, &sw->n);
cur_switch = sw->prev; cur_switch = sw->prev;
tcc_free(sw); tcc_free(sw);
prev_scope(&o,0);
} else if (t == TOK_CASE) { } else if (t == TOK_CASE) {
struct case_t *cr = tcc_malloc(sizeof(struct case_t)); struct case_t *cr = tcc_malloc(sizeof(struct case_t));

45
tests/tests2/129_scopes.c Normal file
View file

@ -0,0 +1,45 @@
#include <stdio.h>
enum{ in = 0};
#define myassert(X) do{ if(!X) printf("%d: assertion failed\n", __LINE__); }while(0)
int main(){
#if 0
{
myassert(!in);
if(sizeof(enum{in=1})) myassert(in);
myassert(!in); //OOPS
}
#endif
{
myassert(!in);
switch(sizeof(enum{in=1})) { default: myassert(in); }
myassert(!in); //OOPS
}
{
myassert(!in);
while(sizeof(enum{in=1})) { myassert(in); break; }
myassert(!in); //OOPS
}
{
myassert(!in);
do{ myassert(!in);}while(0*sizeof(enum{in=1}));
myassert(!in); //OOPS
}
{
myassert(!in);
for(sizeof(enum{in=1});;){ myassert(in); break; }
myassert(!in); //OK
}
{
myassert(!in);
for(;;sizeof(enum{in=1})){ myassert(in); break; }
myassert(!in); //OK
}
{
myassert(!in);
for(;sizeof(enum{in=1});){ myassert(in); break; }
myassert(!in); //OK
}
}

View file