mirror of
https://github.com/mirror/tinycc.git
synced 2025-03-26 12:04:59 +08:00
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;" Replaces2bfedb1867
and07d896c8e5
Fixescf95ac399c
This commit is contained in:
parent
0fbc77cac6
commit
caebbc3ee1
1
libtcc.c
1
libtcc.c
@ -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
6
tcc.h
@ -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;
|
||||||
|
49
tccgen.c
49
tccgen.c
@ -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 */
|
||||||
|
Loading…
Reference in New Issue
Block a user