tccgen: scope levels for local symbols

... for fast redeclaration checks

Also, check function parameters too:
    void foo(int a) { int a; ... }

Also, try to fix struct/union/enum's on different scopes:
    { struct xxx { int x; };
         { struct xxx { int y; }; ... }}
and some (probably not all) combination with incomplete
declarations "struct xxx;"

Replaces 2bfedb1867
and 07d896c8e5

Fixes cf95ac399c
master
grischka 2016-05-05 10:39:09 +02:00
parent 0fbc77cac6
commit caebbc3ee1
3 changed files with 30 additions and 26 deletions

View File

@ -1764,7 +1764,6 @@ static const FlagDef flag_defs[] = {
{ offsetof(TCCState, old_struct_init_code), 0, "old-struct-init-code" }, { offsetof(TCCState, old_struct_init_code), 0, "old-struct-init-code" },
{ offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" }, { offsetof(TCCState, dollars_in_identifiers), 0, "dollars-in-identifiers" },
{ offsetof(TCCState, normalize_inc_dirs), 0, "normalize-inc-dirs" }, { offsetof(TCCState, normalize_inc_dirs), 0, "normalize-inc-dirs" },
{ offsetof(TCCState, no_type_redef_check), FD_INVERT, "type-redefinition-check" },
}; };
/* set/reset a flag */ /* set/reset a flag */

6
tcc.h
View File

@ -459,7 +459,10 @@ typedef struct AttributeDef {
/* symbol management */ /* symbol management */
typedef struct Sym { typedef struct Sym {
int v; /* symbol token */ int v; /* symbol token */
int asm_label; /* associated asm label */ union {
int asm_label; /* associated asm label */
int scope; /* scope level for locals */
};
union { union {
long r; /* associated register */ long r; /* associated register */
struct Attribute a; struct Attribute a;
@ -707,7 +710,6 @@ struct TCCState {
Liuux 2.4.26 can't find initrd when compiled with a new algorithm */ Liuux 2.4.26 can't find initrd when compiled with a new algorithm */
int dollars_in_identifiers; /* allows '$' char in indentifiers */ int dollars_in_identifiers; /* allows '$' char in indentifiers */
int normalize_inc_dirs; /* remove non-existent or duplicate directories from include paths */ int normalize_inc_dirs; /* remove non-existent or duplicate directories from include paths */
int no_type_redef_check; /* no local vars redefinition check */
/* warning switches */ /* warning switches */
int warn_write_strings; int warn_write_strings;

View File

@ -50,10 +50,10 @@ ST_DATA int nb_sym_pools;
ST_DATA Sym *global_stack; ST_DATA Sym *global_stack;
ST_DATA Sym *local_stack; ST_DATA Sym *local_stack;
ST_DATA Sym *scope_stack_bottom;
ST_DATA Sym *define_stack; ST_DATA Sym *define_stack;
ST_DATA Sym *global_label_stack; ST_DATA Sym *global_label_stack;
ST_DATA Sym *local_label_stack; ST_DATA Sym *local_label_stack;
static int local_scope;
ST_DATA int vlas_in_scope; /* number of VLAs that are currently in scope */ ST_DATA int vlas_in_scope; /* number of VLAs that are currently in scope */
ST_DATA int vla_sp_root_loc; /* vla_sp_loc for SP before any VLAs were pushed */ ST_DATA int vla_sp_root_loc; /* vla_sp_loc for SP before any VLAs were pushed */
@ -166,14 +166,7 @@ ST_INLN void sym_free(Sym *sym)
ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, long c) ST_FUNC Sym *sym_push2(Sym **ps, int v, int t, long c)
{ {
Sym *s; Sym *s;
if (!tcc_state->no_type_redef_check) {
if ((ps == &local_stack) && !(v & SYM_FIELD) && (v & ~SYM_STRUCT) < SYM_FIRST_ANOM) {
for (s = *ps; s != scope_stack_bottom; s = s->prev)
if (s->v == v)
tcc_error("incompatible types for redefinition of '%s'",
get_tok_str(v, NULL));
}
}
s = sym_malloc(); s = sym_malloc();
s->asm_label = 0; s->asm_label = 0;
s->v = v; s->v = v;
@ -246,6 +239,11 @@ ST_FUNC Sym *sym_push(int v, CType *type, int r, int c)
ps = &ts->sym_identifier; ps = &ts->sym_identifier;
s->prev_tok = *ps; s->prev_tok = *ps;
*ps = s; *ps = s;
if (local_scope) {
s->scope = local_scope;
if (s->prev_tok && s->prev_tok->scope == s->scope)
tcc_error("redeclaration of '%s'", get_tok_str(v & ~SYM_STRUCT, NULL));
}
} }
return s; return s;
} }
@ -2930,10 +2928,11 @@ static void struct_decl(CType *type, AttributeDef *ad, int u)
if (v < TOK_IDENT) if (v < TOK_IDENT)
expect("struct/union/enum name"); expect("struct/union/enum name");
s = struct_find(v); s = struct_find(v);
if (s) { if (s && s->type.t == a) {
if (s->type.t != a) if (tok != '{' && tok != ';')
tcc_error("invalid type"); goto do_decl; /* variable declaration: 'struct s x;' */
goto do_decl; if (s->scope == local_scope && (s->c == -1 || tok != '{'))
goto do_decl; /* at least one must be incomplete type */
} }
} else { } else {
v = anon_sym++; v = anon_sym++;
@ -3435,6 +3434,8 @@ static void post_type(CType *type, AttributeDef *ad)
plast = &first; plast = &first;
arg_size = 0; arg_size = 0;
if (tok != ')') { if (tok != ')') {
int ls = local_scope;
local_scope = 1; /* for struct decl inside function params */
for(;;) { for(;;) {
/* read param name and compute offset */ /* read param name and compute offset */
if (l != FUNC_OLD) { if (l != FUNC_OLD) {
@ -3474,6 +3475,7 @@ static void post_type(CType *type, AttributeDef *ad)
break; break;
} }
} }
local_scope = ls;
} }
/* if no parameters, then old type prototype */ /* if no parameters, then old type prototype */
if (l == 0) if (l == 0)
@ -4879,7 +4881,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
int case_reg, int is_expr) int case_reg, int is_expr)
{ {
int a, b, c, d; int a, b, c, d;
Sym *s, *frame_bottom; Sym *s;
/* generate line number info */ /* generate line number info */
if (tcc_state->do_debug && if (tcc_state->do_debug &&
@ -4933,10 +4935,8 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
next(); next();
/* record local declaration stack position */ /* record local declaration stack position */
s = local_stack; s = local_stack;
frame_bottom = sym_push2(&local_stack, SYM_FIELD, 0, 0);
frame_bottom->next = scope_stack_bottom;
scope_stack_bottom = frame_bottom;
llabel = local_label_stack; llabel = local_label_stack;
++local_scope;
/* handle local labels declarations */ /* handle local labels declarations */
if (tok == TOK_LABEL) { if (tok == TOK_LABEL) {
@ -4983,7 +4983,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
} }
} }
/* pop locally defined symbols */ /* pop locally defined symbols */
scope_stack_bottom = scope_stack_bottom->next; --local_scope;
sym_pop(&local_stack, s); sym_pop(&local_stack, s);
/* Pop VLA frames and restore stack pointer if required */ /* Pop VLA frames and restore stack pointer if required */
@ -5082,9 +5082,7 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
next(); next();
skip('('); skip('(');
s = local_stack; s = local_stack;
frame_bottom = sym_push2(&local_stack, SYM_FIELD, 0, 0); ++local_scope;
frame_bottom->next = scope_stack_bottom;
scope_stack_bottom = frame_bottom;
if (tok != ';') { if (tok != ';') {
/* c99 for-loop init decl? */ /* c99 for-loop init decl? */
if (!decl0(VT_LOCAL, 1)) { if (!decl0(VT_LOCAL, 1)) {
@ -5119,8 +5117,9 @@ static void block(int *bsym, int *csym, int *case_sym, int *def_sym,
gjmp_addr(c); gjmp_addr(c);
gsym(a); gsym(a);
gsym_addr(b, c); gsym_addr(b, c);
scope_stack_bottom = scope_stack_bottom->next; --local_scope;
sym_pop(&local_stack, s); sym_pop(&local_stack, s);
} else } else
if (tok == TOK_DO) { if (tok == TOK_DO) {
next(); next();
@ -6154,9 +6153,13 @@ static void gen_function(Sym *sym)
/* put debug symbol */ /* put debug symbol */
if (tcc_state->do_debug) if (tcc_state->do_debug)
put_func_debug(sym); put_func_debug(sym);
/* push a dummy symbol to enable local sym storage */ /* push a dummy symbol to enable local sym storage */
sym_push2(&local_stack, SYM_FIELD, 0, 0); sym_push2(&local_stack, SYM_FIELD, 0, 0);
local_scope = 1; /* for function parameters */
gfunc_prolog(&sym->type); gfunc_prolog(&sym->type);
local_scope = 0;
#ifdef CONFIG_TCC_BCHECK #ifdef CONFIG_TCC_BCHECK
if (tcc_state->do_bounds_check && !strcmp(funcname, "main")) { if (tcc_state->do_bounds_check && !strcmp(funcname, "main")) {
int i; int i;
@ -6177,7 +6180,7 @@ static void gen_function(Sym *sym)
cur_text_section->data_offset = ind; cur_text_section->data_offset = ind;
label_pop(&global_label_stack, NULL); label_pop(&global_label_stack, NULL);
/* reset local stack */ /* reset local stack */
scope_stack_bottom = NULL; local_scope = 0;
sym_pop(&local_stack, NULL); sym_pop(&local_stack, NULL);
/* end of function */ /* end of function */
/* patch symbol size */ /* patch symbol size */