diff -r 9e68675fe174 -r 2e2a944a8e1a tcc.c --- a/tcc.c Thu Sep 20 02:52:04 2007 -0500 +++ b/tcc.c Thu Nov 01 16:07:35 2007 +0000 @@ -91,7 +91,7 @@ static TokenSym *hash_ident[TOK_HASH_SIZ static TokenSym *hash_ident[TOK_HASH_SIZE]; static char token_buf[STRING_MAX_SIZE + 1]; static char *funcname; -static Sym *global_stack, *local_stack; +static Sym *global_stack, *local_stack, *local_compound; static Sym *define_stack; static Sym *global_label_stack, *local_label_stack; /* symbol allocator */ @@ -5711,12 +5711,25 @@ static void parse_attribute(AttributeDef } } +/* check for a duplicate parameter/member */ +static int check_field(Sym *first, int v) +{ + Sym *s; + s = first; + while (s){ + if (s->v == v) + return -1; + s = s->next; + } + return 0; +} + /* enum/struct/union declaration. u is either VT_ENUM or VT_STRUCT */ static void struct_decl(CType *type, int u) { int a, v, size, align, maxalign, c, offset; int bit_size, bit_pos, bsize, bt, lbit_pos; - Sym *s, *ss, *ass, **ps; + Sym *s, *ss, *first, *ass, **ps; AttributeDef ad; CType type1, btype; @@ -5764,6 +5777,15 @@ static void struct_decl(CType *type, int c = expr_const(); } /* enum symbols have static storage */ + ss = sym_find(v); + if (ss){ + if (ss->type.t == (VT_INT | VT_STATIC) && ss->r == VT_CONST) + error("redeclaration of enumerator '%s'", + get_tok_str(v, NULL)); + else + error("enumerator '%s' redeclared as different kind of symbol", + get_tok_str(v, NULL)); + } ss = sym_push(v, &int_type, VT_CONST, c); ss->type.t |= VT_STATIC; if (tok != ',') @@ -5780,6 +5802,7 @@ static void struct_decl(CType *type, int ps = &s->next; bit_pos = 0; offset = 0; + first = NULL; while (tok != '}') { parse_btype(&btype, &ad); while (1) { @@ -5883,12 +5906,22 @@ static void struct_decl(CType *type, int if (v == 0 && (type1.t & VT_BTYPE) == VT_STRUCT) { ass = type1.ref; while ((ass = ass->next) != NULL) { + if (check_field(first, ass->v)) + error("duplicate member '%s' from anonymous struct", + get_tok_str(ass->v & ~SYM_FIELD, NULL)); ss = sym_push(ass->v, &ass->type, 0, offset + ass->c); + if (!first) + first = ss; *ps = ss; ps = &ss->next; } } else if (v) { + if (check_field(first, v | SYM_FIELD)) + error("duplicate member '%s'", + get_tok_str(v, NULL)); ss = sym_push(v | SYM_FIELD, &type1, 0, offset); + if (!first) + first = ss; *ps = ss; ps = &ss->next; } @@ -6135,6 +6168,9 @@ static void post_type(CType *type, Attri next(); } convert_parameter_type(&pt); + if(check_field(first, n | SYM_FIELD)) + error("redefinition of parameter '%s'", + get_tok_str(n, NULL)); s = sym_push(n | SYM_FIELD, &pt, 0, 0); *plast = s; plast = &s->next; @@ -7212,11 +7248,12 @@ static void block(int *bsym, int *csym, gsym(a); gsym_addr(b, d); } else if (tok == '{') { - Sym *llabel; + Sym *llabel, *old_comp; next(); /* record local declaration stack position */ - s = local_stack; + old_comp = local_compound; + local_compound = s = local_stack; llabel = local_label_stack; /* handle local labels declarations */ if (tok == TOK_LABEL) { @@ -7246,6 +7283,7 @@ static void block(int *bsym, int *csym, label_pop(&local_label_stack, llabel); /* pop locally defined symbols */ sym_pop(&local_stack, s); + local_compound = old_comp; next(); } else if (tok == TOK_RETURN) { next(); @@ -7930,6 +7968,29 @@ static void decl_initializer(CType *type } } +/* return true if 's' is in the current compound statement */ +static int is_in_compound(Sym *sym) +{ + Sym *s; + s = local_stack; + if (!s || !local_compound) + return 0; + while (s != local_compound){ + if (s == sym) + return 1; + s = s->prev; + } + return 0; +} + +static inline int is_global(Sym *s) +{ + if ((s->r & (VT_VALMASK | VT_LVAL)) == (VT_CONST | VT_LVAL)) + return 1; + else + return 0; +} + /* parse an initializer for type 't' if 'has_init' is non zero, and allocate space in local or global data space ('r' is either VT_LOCAL or VT_CONST). If 'v' is non zero, then an associated @@ -8025,6 +8086,12 @@ static void decl_initializer_alloc(CType } if (v) { /* local variable */ + Sym *sym; + sym = sym_find(v); + if (sym && !is_global(sym) && is_in_compound(sym)){ + error("redefinition of local variable '%s'", + get_tok_str(v, NULL)); + } sym_push(v, type, r, addr); } else { /* push local reference */ @@ -8218,6 +8285,7 @@ static void gen_function(Sym *sym) put_func_debug(sym); /* push a dummy symbol to enable local sym storage */ sym_push2(&local_stack, SYM_FIELD, 0, 0); + local_compound = local_stack; gfunc_prolog(&sym->type); rsym = 0; block(NULL, NULL, NULL, NULL, 0, 0);