oops, slight mistake, sorry. Here is replacement patch.
----------
I was going to send this as a high-tech Mercurial bundle, but then I realized
I'd transplanted the parent, so it was a bit difficult. Here's a low-tech
patch file instead.
Check for duplicate definitions of variables
Added global "Sym *local_compound" which is a pointer into the local
symbol stack to mark the start of the current compound statement.
The following are valid:
int a, a; /* in a global context */
int a; { int a; } /* in a function */
The following now throw errors:
int a, a; /* in a function */
void foo(int a, int a);
enum { a, a };
union { int a; int a; };
struct { int a; struct { int a; }; };
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);
_______________________________________________
Tinycc-devel mailing list
[email protected]
http://lists.nongnu.org/mailman/listinfo/tinycc-devel