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

Reply via email to