tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Tinycc-devel] Unify C and asm symbols


From: grischka
Subject: Re: [Tinycc-devel] Unify C and asm symbols
Date: Mon, 04 Dec 2017 18:07:22 +0100
User-agent: Thunderbird 2.0.0.23 (Windows/20090812)

Michael Matz wrote:
Here 'x5' should have the g[lobal] binding from C.

... I have fixed this in mob with a one-liner instead :)

Well, however this one line
+       if (esym && s->type.t == VT_VOID) {

gives an interesting hint too because if after all we "post-process"
only asm symbols then this means (IMO) that logically equivalently
the same changes can be made to the symbol in place as well.

Anyway, while at it (and making more tests), I tried that and it
seems to work quite well.

I've attached it as "no-asm-stack.patch".  It also includes a fix
in 'unary()' for "error: function pointer expected" with
       __asm__("call f1")
         f1();

It clearly still has unwanted behavior with compiling multiple files
if symbols with same name are defined as global in one file and
then as static in another file.

The other "patch-type.patch" somewhat unifies type redefinition
and instance redefinition checking,  also between asm and C, such
as with
       __asm__("f1: ...")
        int f1() { }
or
        int f1 = 1;

Anyway. you might use these patches as just ideas or to run some tests
to see if we can include them as is for the release.

Apropos release, I don't have problems if the released version has
"limitations" say with some corner cases, as long as unlikely an
even simpler approach exist with equal or even less limitations.

IOW if we're possibly somewhere close to such possibly simpler and
better approach then I think it's worth to still wait, 1, 2, 3 ...
weeks doesn't matter ;)

--- grischka



Ciao,
Michael.


commit 21f943378bbbec0a499412e411ddecd51e505b89
Author: grischka <grischka>
Date:   Thu Nov 30 15:15:22 2017 +0100

    tccasm: use global(_symbol)_stack
    
    * removed asm_label stack
    * removed asm_free_labels() post-processing
    * using "impossible C type" for asm labels (VT_ASM)
    * tccgen.c:update_storage(): use it to refresh symbol attributes
    * tccelf.c:find_elf_sym(): ignore STB_LOCAL symbols
    * tccgen.c:unary(): asm symbols are supposed to be undeclared in C

diff --git a/tcc.h b/tcc.h
index 6241f42..07b9286 100644
--- a/tcc.h
+++ b/tcc.h
@@ -440,8 +440,7 @@ struct SymAttr {
     visibility  : 2,
     dllexport   : 1,
     dllimport   : 1,
-    asmexport   : 1,
-    unused      : 4;
+    unused      : 5;
 };
 
 /* function attributes or temporary attributes for parsing */
@@ -796,8 +795,8 @@ struct TCCState {
     /* extra attributes (eg. GOT/PLT value) for symtab symbols */
     struct sym_attr *sym_attrs;
     int nb_sym_attrs;
+
     /* tiny assembler state */
-    Sym *asm_labels;
     ElfSym esym_dot;
 
 #ifdef TCC_TARGET_PE
@@ -911,6 +910,11 @@ struct filespec {
 #define VT_STORAGE (VT_EXTERN | VT_STATIC | VT_TYPEDEF | VT_INLINE)
 #define VT_TYPE (~(VT_STORAGE|VT_STRUCT_MASK))
 
+/* symbol was created by tccasm.c first */
+#define VT_ASM (VT_VOID | VT_UNSIGNED)
+#define VT_ASM_GLOBAL VT_DEFSIGN
+#define IS_ASM_SYM(sym) (((sym)->type.t & (VT_BTYPE | VT_ASM)) == VT_ASM)
+
 /* token values */
 
 /* warning: the following compare tokens depend on i386 asm code */
@@ -1147,7 +1151,7 @@ ST_FUNC Sym *sym_push(int v, CType *type, int r, int c);
 ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep);
 ST_INLN Sym *struct_find(int v);
 ST_INLN Sym *sym_find(int v);
-ST_FUNC Sym *global_identifier_push_1(Sym **, int v, int t, int c);
+ST_FUNC Sym *global_identifier_push(int v, int t, int c);
 
 ST_FUNC void tcc_open_bf(TCCState *s1, const char *filename, int initlen);
 ST_FUNC int tcc_open(TCCState *s1, const char *filename);
@@ -1317,6 +1321,7 @@ ST_FUNC int ieee_finite(double d);
 ST_FUNC void test_lvalue(void);
 ST_FUNC void vpushi(int v);
 ST_FUNC ElfSym *elfsym(Sym *);
+ST_FUNC void update_storage(Sym *sym);
 ST_FUNC Sym *external_global_sym(int v, CType *type, int r);
 ST_FUNC void vset(CType *type, int r, int v);
 ST_FUNC void vswap(void);
@@ -1588,7 +1593,6 @@ ST_FUNC Sym* get_asm_sym(int name, Sym *csym);
 ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe);
 ST_FUNC int asm_int_expr(TCCState *s1);
 ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess);
-ST_FUNC void asm_free_labels(TCCState *st);
 /* ------------ i386-asm.c ------------ */
 ST_FUNC void gen_expr32(ExprValue *pe);
 #ifdef TCC_TARGET_X86_64
diff --git a/tccasm.c b/tccasm.c
index 15f1e43..4fe3f32 100644
--- a/tccasm.c
+++ b/tccasm.c
@@ -44,11 +44,11 @@ static Sym *asm_label_find(int v)
 
 static Sym *asm_label_push(int v, int t)
 {
-    Sym *sym = global_identifier_push_1(&tcc_state->asm_labels, v, t, 0);
+    Sym *sym = global_identifier_push(v, t, 0);
     /* We always add VT_EXTERN, for sym definition that's tentative
        (for .set, removed for real defs), for mere references it's correct
        as is.  */
-    sym->type.t |= VT_VOID | VT_EXTERN;
+    sym->type.t |= VT_ASM | VT_EXTERN;
     sym->r = VT_CONST | VT_SYM;
     return sym;
 }
@@ -149,7 +149,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe)
         pe->v = 0;
         pe->sym = &sym_dot;
        pe->pcrel = 0;
-        sym_dot.type.t = VT_VOID | VT_STATIC;
+        sym_dot.type.t = VT_ASM | VT_STATIC;
        sym_dot.c = -1;
         tcc_state->esym_dot.st_shndx = cur_text_section->sh_num;
         tcc_state->esym_dot.st_value = ind;
@@ -371,7 +371,7 @@ static Sym* asm_new_label1(TCCState *s1, int label, int 
is_local,
           definitions won't have VT_EXTERN set.  */
         if (esym && esym->st_shndx != SHN_UNDEF && !(sym->type.t & VT_EXTERN)) 
{
             /* the label is already defined */
-            if (!is_local) {
+            if (is_local != 1) {
                 tcc_error("assembler label '%s' already defined", 
                       get_tok_str(label, NULL));
             } else {
@@ -381,13 +381,22 @@ static Sym* asm_new_label1(TCCState *s1, int label, int 
is_local,
         }
     } else {
     new_label:
-        sym = asm_label_push(label, is_local ? VT_STATIC : 0);
+        sym = asm_label_push(label, is_local == 1 ? VT_STATIC : 0);
     }
     if (!sym->c)
       put_extern_sym2(sym, NULL, 0, 0, 0);
     esym = elfsym(sym);
     esym->st_shndx = sh_num;
     esym->st_value = value;
+
+    if (is_local != 2)
+        sym->type.t &= ~VT_EXTERN;
+
+    if (IS_ASM_SYM(sym) && !(sym->type.t & VT_ASM_GLOBAL)) {
+        sym->type.t |= VT_STATIC;
+        update_storage(sym);
+    }
+
     return sym;
 }
 
@@ -410,39 +419,11 @@ static Sym* set_symbol(TCCState *s1, int label)
     esym = elfsym(e.sym);
     if (esym)
        n += esym->st_value;
-    sym = asm_new_label1(s1, label, 0, esym ? esym->st_shndx : SHN_ABS, n);
+    sym = asm_new_label1(s1, label, 2, esym ? esym->st_shndx : SHN_ABS, n);
     elfsym(sym)->st_other |= ST_ASM_SET;
     return sym;
 }
 
-ST_FUNC void asm_free_labels(TCCState *st)
-{
-    Sym *s, *s1;
-
-    for(s = st->asm_labels; s != NULL; s = s1) {
-       ElfSym *esym = elfsym(s);
-        s1 = s->prev;
-        /* Possibly update binding and visibility from asm directives
-          if the symbol has no C decl (type is VT_VOID).*/
-       s->type.t &= ~VT_EXTERN;
-       if (esym && s->type.t == VT_VOID) {
-           if (!s->a.asmexport && esym->st_shndx != SHN_UNDEF)
-               s->type.t |= VT_STATIC;
-           if (s->a.visibility)
-               esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
-                                | s->a.visibility;
-           esym->st_info = ELFW(ST_INFO)(s->a.weak ? STB_WEAK
-                                         : (s->type.t & VT_STATIC) ? STB_LOCAL
-                                         : STB_GLOBAL,
-                                         ELFW(ST_TYPE)(esym->st_info));
-       }
-        /* remove label */
-        table_ident[s->v - TOK_IDENT]->sym_identifier = s->prev_tok;
-        sym_free(s);
-    }
-    st->asm_labels = NULL;
-}
-
 static void use_section1(TCCState *s1, Section *sec)
 {
     cur_text_section->data_offset = ind;
@@ -696,15 +677,18 @@ static void asm_parse_directive(TCCState *s1, int global)
        tok1 = tok;
        do { 
             Sym *sym;
-
             next();
             sym = get_asm_sym(tok, NULL);
-           if (tok1 != TOK_ASMDIR_hidden)
-                sym->type.t &= ~VT_STATIC, sym->a.asmexport = 1;
+           if (tok1 != TOK_ASMDIR_hidden) {
+                sym->type.t &= ~VT_STATIC;
+                if (IS_ASM_SYM(sym))
+                    sym->type.t |= VT_ASM_GLOBAL;
+            }
             if (tok1 == TOK_ASMDIR_weak)
                 sym->a.weak = 1;
            else if (tok1 == TOK_ASMDIR_hidden)
                sym->a.visibility = STV_HIDDEN;
+            update_storage(sym);
             next();
        } while (tok == ',');
        break;
@@ -947,7 +931,6 @@ static int tcc_assemble_internal(TCCState *s1, int 
do_preprocess, int global)
         } else if (tok >= TOK_ASMDIR_FIRST && tok <= TOK_ASMDIR_LAST) {
             asm_parse_directive(s1, global);
         } else if (tok == TOK_PPNUM) {
-           Sym *sym;
             const char *p;
             int n;
             p = tokc.str.data;
@@ -955,9 +938,7 @@ static int tcc_assemble_internal(TCCState *s1, int 
do_preprocess, int global)
             if (*p != '\0')
                 expect("':'");
             /* new local label */
-            sym = asm_new_label(s1, asm_get_local_label_name(s1, n), 1);
-           /* Remove the marker for tentative definitions.  */
-           sym->type.t &= ~VT_EXTERN;
+            asm_new_label(s1, asm_get_local_label_name(s1, n), 1);
             next();
             skip(':');
             goto redo;
@@ -967,8 +948,7 @@ static int tcc_assemble_internal(TCCState *s1, int 
do_preprocess, int global)
             next();
             if (tok == ':') {
                 /* new label */
-                Sym *sym = asm_new_label(s1, opcode, 0);
-               sym->type.t &= ~VT_EXTERN;
+                asm_new_label(s1, opcode, 0);
                 next();
                 goto redo;
             } else if (tok == '=') {
@@ -998,7 +978,6 @@ ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess)
     ind = cur_text_section->data_offset;
     nocode_wanted = 0;
     ret = tcc_assemble_internal(s1, do_preprocess, 1);
-    asm_free_labels(s1);
     cur_text_section->data_offset = ind;
     tcc_debug_end(s1);
     return ret;
diff --git a/tccelf.c b/tccelf.c
index 422dfd6..657aa61 100644
--- a/tccelf.c
+++ b/tccelf.c
@@ -310,8 +310,7 @@ static void rebuild_hash(Section *s, unsigned int 
nb_buckets)
 
     sym = (ElfW(Sym) *)s->data + 1;
     for(sym_index = 1; sym_index < nb_syms; sym_index++) {
-        if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL
-           || sym->st_shndx == SHN_UNDEF) {
+        if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
             h = elf_hash(strtab + sym->st_name) % nb_buckets;
             *ptr = hash[h];
             hash[h] = sym_index;
@@ -350,9 +349,8 @@ ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned 
long size,
         int *ptr, *base;
         ptr = section_ptr_add(hs, sizeof(int));
         base = (int *)hs->data;
-        /* only add global, weak or undef symbols.  The latter might
-          become global late (from asm references).  */
-        if (ELFW(ST_BIND)(info) != STB_LOCAL || shndx == SHN_UNDEF) {
+        /* only add global or weak symbols. */
+        if (ELFW(ST_BIND)(info) != STB_LOCAL) {
             /* add another hashing entry */
             nbuckets = base[0];
             h = elf_hash((unsigned char *) name) % nbuckets;
@@ -390,7 +388,7 @@ ST_FUNC int find_elf_sym(Section *s, const char *name)
     while (sym_index != 0) {
         sym = &((ElfW(Sym) *)s->data)[sym_index];
         name1 = (char *) s->link->data + sym->st_name;
-        if (!strcmp(name, name1))
+        if (!strcmp(name, name1) && ELFW(ST_BIND)(sym->st_info) != STB_LOCAL)
             return sym_index;
         sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
     }
diff --git a/tccgen.c b/tccgen.c
index 2d3f2d0..7ddde72 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -275,11 +275,6 @@ ST_FUNC int tccgen_compile(TCCState *s1)
     decl(VT_CONST);
     gen_inline_functions(s1);
     check_vstack();
-
-#ifdef CONFIG_TCC_ASM
-    asm_free_labels(s1);
-#endif
-
     /* end of translation unit info */
     tcc_debug_end(s1);
     return 0;
@@ -297,28 +292,42 @@ ST_FUNC ElfSym *elfsym(Sym *s)
 }
 
 /* apply storage attributes to Elf symbol */
-
-static void update_storage(Sym *sym)
+ST_FUNC void update_storage(Sym *sym)
 {
-    ElfSym *esym = elfsym(sym);
+    ElfSym *esym;
+    int sym_bind, old_sym_bind;
+
+    esym = elfsym(sym);
     if (!esym)
         return;
+
     if (sym->a.visibility)
         esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
             | sym->a.visibility;
-    if (sym->a.weak)
-        esym->st_info = ELFW(ST_INFO)(STB_WEAK, ELFW(ST_TYPE)(esym->st_info));
+
+    if (sym->type.t & VT_STATIC)
+        sym_bind = STB_LOCAL;
+    else if (sym->a.weak)
+        sym_bind = STB_WEAK;
+    else
+        sym_bind = STB_GLOBAL;
+    old_sym_bind = ELFW(ST_BIND)(esym->st_info);
+    if (sym_bind != old_sym_bind) {
+        esym->st_info = ELFW(ST_INFO)(sym_bind, ELFW(ST_TYPE)(esym->st_info));
+    }
+
 #ifdef TCC_TARGET_PE
     if (sym->a.dllimport)
         esym->st_other |= ST_PE_IMPORT;
     if (sym->a.dllexport)
         esym->st_other |= ST_PE_EXPORT;
 #endif
+
 #if 0
-    printf("storage %s: vis=%d weak=%d exp=%d imp=%d\n",
+    printf("storage %s: bind=%c vis=%d exp=%d imp=%d\n",
         get_tok_str(sym->v, NULL),
+        sym_bind == STB_WEAK ? 'w' : sym_bind == STB_LOCAL ? 'l' : 'g',
         sym->a.visibility,
-        sym->a.weak,
         sym->a.dllexport,
         sym->a.dllimport
         );
@@ -578,10 +587,10 @@ ST_FUNC Sym *sym_push(int v, CType *type, int r, int c)
 }
 
 /* push a global identifier */
-ST_FUNC Sym *global_identifier_push_1(Sym **ptop, int v, int t, int c)
+ST_FUNC Sym *global_identifier_push(int v, int t, int c)
 {
     Sym *s, **ps;
-    s = sym_push2(ptop, v, t, c);
+    s = sym_push2(&global_stack, v, t, c);
     /* don't record anonymous symbol */
     if (v < SYM_FIRST_ANOM) {
         ps = &table_ident[v - TOK_IDENT]->sym_identifier;
@@ -595,11 +604,6 @@ ST_FUNC Sym *global_identifier_push_1(Sym **ptop, int v, 
int t, int c)
     return s;
 }
 
-static Sym *global_identifier_push(int v, int t, int c)
-{
-    return global_identifier_push_1(&global_stack, v, t, c);
-}
-
 /* pop symbols until top reaches 'b'.  If KEEP is non-zero don't really
    pop them yet from the list, but do remove them from the token array.  */
 ST_FUNC void sym_pop(Sym **ptop, Sym *b, int keep)
@@ -841,6 +845,9 @@ ST_FUNC Sym *external_global_sym(int v, CType *type, int r)
         s = global_identifier_push(v, type->t | VT_EXTERN, 0);
         s->type.ref = type->ref;
         s->r = r | VT_CONST | VT_SYM;
+    } else if (IS_ASM_SYM(s)) {
+        s->type.t = type->t | (s->type.t & VT_EXTERN);
+        s->type.ref = type->ref;
     }
     return s;
 }
@@ -849,7 +856,7 @@ ST_FUNC Sym *external_global_sym(int v, CType *type, int r)
 static void patch_storage(Sym *sym, AttributeDef *ad, CType *type)
 {
     if (type) {
-       if ((sym->type.t & VT_BTYPE) == VT_VOID) /* from asm */
+       if (IS_ASM_SYM(sym))
            sym->type = *type;
        else if (!is_compatible_types(&sym->type, type))
            tcc_error("incompatible types for redefinition of '%s'",
@@ -5026,7 +5033,7 @@ ST_FUNC void unary(void)
         if (t < TOK_UIDENT)
             expect("identifier");
         s = sym_find(t);
-        if (!s) {
+        if (!s || IS_ASM_SYM(s)) {
             const char *name = get_tok_str(t, NULL);
             if (tok != '(')
                 tcc_error("'%s' undeclared", name);
@@ -7223,12 +7230,8 @@ static int decl0(int l, int is_for_loop_init, Sym 
*func_sym)
                     type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
                 
                 sym = sym_find(v);
-                if (sym) {
+                if (sym && !IS_ASM_SYM(sym)) {
                     Sym *ref;
-                   /* If type is VT_VOID the symbol was created by tccasm
-                      first, and we see the first reference from C now. */
-                   if ((sym->type.t & VT_BTYPE) == VT_VOID)
-                       sym->type = type;
 
                     if ((sym->type.t & VT_BTYPE) != VT_FUNC)
                         goto func_error1;
@@ -7261,15 +7264,14 @@ static int decl0(int l, int is_for_loop_init, Sym 
*func_sym)
                         tcc_error("redefinition of '%s'", get_tok_str(v, 
NULL));
                     /* if symbol is already defined, then put complete type */
                     sym->type = type;
+                    sym->r = VT_SYM | VT_CONST;
 
                 } else {
                     /* put function symbol */
-                    sym = global_identifier_push(v, type.t, 0);
-                    sym->type.ref = type.ref;
+                    sym = external_global_sym(v, &type, 0);
                 }
 
                 sym->type.ref->f.func_body = 1;
-                sym->r = VT_SYM | VT_CONST;
                 patch_storage(sym, &ad, NULL);
 
                 /* static inline functions are just recorded as a kind

commit 7cf7ab12de04d1f9f2683b2cb805437fc6379a23
Author: grischka <grischka>
Date:   Sun Dec 3 20:43:48 2017 +0100

    tccgen: unify type redefinition checks
    
    tccgen.c:
    - improved function patch_storage() and added new function
      patch_type() for more consistent type redefinition and
      instance redefinition checks.

diff --git a/tcc.h b/tcc.h
index 07b9286..38bbda8 100644
--- a/tcc.h
+++ b/tcc.h
@@ -448,7 +448,6 @@ struct FuncAttr {
     unsigned
     func_call   : 3, /* calling convention (0..5), see below */
     func_type   : 2, /* FUNC_OLD/NEW/ELLIPSIS */
-    func_body   : 1, /* body was defined */
     func_args   : 8; /* PE __stdcall args */
 };
 
diff --git a/tccgen.c b/tccgen.c
index 7ddde72..97ea94c 100644
--- a/tccgen.c
+++ b/tccgen.c
@@ -852,22 +852,63 @@ ST_FUNC Sym *external_global_sym(int v, CType *type, int 
r)
     return s;
 }
 
+/* Merge some type attributes.  */
+static void patch_type(Sym *sym, CType *type)
+{
+    if (!(type->t & VT_EXTERN)) {
+        if (!(sym->type.t & VT_EXTERN))
+            tcc_error("redefinition of '%s'", get_tok_str(sym->v, NULL));
+        sym->type.t &= ~VT_EXTERN;
+    }
+
+    if (IS_ASM_SYM(sym)) {
+        sym->type = *type;
+
+    } else if (!is_compatible_types(&sym->type, type)) {
+        tcc_error("incompatible types for redefinition of '%s'",
+                  get_tok_str(sym->v, NULL));
+
+    } else if ((sym->type.t & VT_BTYPE) == VT_FUNC) {
+        int static_proto = sym->type.t & VT_STATIC;
+        /* warn if static follows non-static function declaration */
+        if ((type->t & VT_STATIC) && !static_proto && !(type->t & VT_INLINE))
+            tcc_warning("static storage ignored for redefinition of '%s'",
+                get_tok_str(sym->v, NULL));
+
+        if (0 == (type->t & VT_EXTERN)) {
+            /* put complete type */
+            sym->type = *type;
+            /* use static from prototype */
+            sym->type.t |= static_proto;
+        }
+
+    } else {
+        if ((sym->type.t & VT_ARRAY) && type->ref->c >= 0) {
+            /* set array size if it was omitted in extern declaration */
+            if (sym->type.ref->c < 0)
+                sym->type.ref->c = type->ref->c;
+            else if (sym->type.ref->c != type->ref->c)
+                tcc_error("conflicting type for '%s'", get_tok_str(sym->v, 
NULL));
+        }
+        if ((type->t ^ sym->type.t) & VT_STATIC)
+            tcc_warning("storage mismatch for redefinition of '%s'",
+                get_tok_str(sym->v, NULL));
+    }
+}
+
+
 /* Merge some storage attributes.  */
 static void patch_storage(Sym *sym, AttributeDef *ad, CType *type)
 {
-    if (type) {
-       if (IS_ASM_SYM(sym))
-           sym->type = *type;
-       else if (!is_compatible_types(&sym->type, type))
-           tcc_error("incompatible types for redefinition of '%s'",
-                      get_tok_str(sym->v, NULL));
-    }
+    if (type)
+        patch_type(sym, type);
+
 #ifdef TCC_TARGET_PE
     if (sym->a.dllimport != ad->a.dllimport)
         tcc_error("incompatible dll linkage for redefinition of '%s'",
             get_tok_str(sym->v, NULL));
-#endif
     sym->a.dllexport |= ad->a.dllexport;
+#endif
     sym->a.weak |= ad->a.weak;
     if (ad->a.visibility) {
         int vis = sym->a.visibility;
@@ -6904,26 +6945,9 @@ static void decl_initializer_alloc(CType *type, 
AttributeDef *ad, int r,
             sym = sym_find(v);
             if (sym) {
                 patch_storage(sym, ad, type);
-                if (sym->type.t & VT_EXTERN) {
-                    /* if the variable is extern, it was not allocated */
-                    sym->type.t &= ~VT_EXTERN;
-                    /* set array size if it was omitted in extern
-                       declaration */
-                    if ((sym->type.t & VT_ARRAY) && 
-                        sym->type.ref->c < 0 &&
-                        type->ref->c >= 0)
-                        sym->type.ref->c = type->ref->c;
-                } else if (!has_init) {
-                    /* we accept several definitions of the same
-                       global variable. this is tricky, because we
-                       must play with the SHN_COMMON type of the symbol */
-                    /* no init data, we won't add more to the symbol */
+                /* we accept several definitions of the same global variable. 
*/
+                if (!has_init && sym->c && elfsym(sym)->st_shndx != SHN_UNDEF)
                     goto no_alloc;
-                } else if (sym->c) {
-                    ElfSym *esym = elfsym(sym);
-                    if (esym->st_shndx == data_section->sh_num)
-                        tcc_error("redefinition of '%s'", get_tok_str(v, 
NULL));
-                }
             }
         }
 
@@ -7228,51 +7252,11 @@ static int decl0(int l, int is_for_loop_init, Sym 
*func_sym)
                 /* XXX: cannot do better now: convert extern line to static 
inline */
                 if ((type.t & (VT_EXTERN | VT_INLINE)) == (VT_EXTERN | 
VT_INLINE))
                     type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
-                
-                sym = sym_find(v);
-                if (sym && !IS_ASM_SYM(sym)) {
-                    Sym *ref;
-
-                    if ((sym->type.t & VT_BTYPE) != VT_FUNC)
-                        goto func_error1;
-
-                    ref = sym->type.ref;
-
-                    /* use func_call from prototype if not defined */
-                    if (ref->f.func_call != FUNC_CDECL
-                     && type.ref->f.func_call == FUNC_CDECL)
-                        type.ref->f.func_call = ref->f.func_call;
-
-                    /* use static from prototype */
-                    if (sym->type.t & VT_STATIC)
-                        type.t = (type.t & ~VT_EXTERN) | VT_STATIC;
-
-                   /* If the definition has no visibility use the
-                      one from prototype.  */
-                   if (!type.ref->a.visibility)
-                        type.ref->a.visibility = ref->a.visibility;
-                    /* apply other storage attributes from prototype */
-                    type.ref->a.dllexport |= ref->a.dllexport;
-                    type.ref->a.weak |= ref->a.weak;
-
-                    if (!is_compatible_types(&sym->type, &type)) {
-                    func_error1:
-                        tcc_error("incompatible types for redefinition of 
'%s'", 
-                              get_tok_str(v, NULL));
-                    }
-                    if (ref->f.func_body)
-                        tcc_error("redefinition of '%s'", get_tok_str(v, 
NULL));
-                    /* if symbol is already defined, then put complete type */
-                    sym->type = type;
-                    sym->r = VT_SYM | VT_CONST;
 
-                } else {
-                    /* put function symbol */
-                    sym = external_global_sym(v, &type, 0);
-                }
-
-                sym->type.ref->f.func_body = 1;
-                patch_storage(sym, &ad, NULL);
+                /* put function symbol */
+                sym = external_global_sym(v, &type, 0);
+                type.t &= ~VT_EXTERN;
+                patch_storage(sym, &ad, &type);
 
                 /* static inline functions are just recorded as a kind
                    of macro. Their code will be emitted at the end of
@@ -7350,6 +7334,7 @@ found:
                         /* NOTE: as GCC, uninitialized global static
                            arrays of null size are considered as
                            extern */
+                        type.t |= VT_EXTERN;
                         sym = external_sym(v, &type, r, &ad);
                         if (ad.alias_target) {
                             Section tsec;
@@ -7372,6 +7357,9 @@ found:
                             r |= l;
                         if (has_init)
                             next();
+                        else if (l == VT_CONST)
+                            /* uninitialized global variables may be 
overridden */
+                            type.t |= VT_EXTERN;
                         decl_initializer_alloc(&type, &ad, r, has_init, v, l);
                     }
                 }


reply via email to

[Prev in Thread] Current Thread [Next in Thread]