tccgen.c: local extern decls: copy s->ref for VT_PTR too

This fixes the issue

    int main() { extern char *x; }
    void main1() { extern char *x; }
    t2.c:5: error: incompatible types for redefinition of 'x'

(reported by Giovanni Mascellani 2019/07/16)
This commit is contained in:
grischka 2019-07-16 17:30:04 +02:00
parent 9298555eb6
commit 7b8799e5ff
4 changed files with 41 additions and 13 deletions

View file

@ -98,7 +98,7 @@ TCC_X += riscv64
# cross libtcc1.a targets to build # cross libtcc1.a targets to build
LIBTCC1_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince LIBTCC1_X = i386 x86_64 i386-win32 x86_64-win32 x86_64-osx arm arm64 arm-wince
LIBTCC1_X = riscv64 LIBTCC1_X += riscv64
PROGS_CROSS = $(foreach X,$(TCC_X),$X-tcc$(EXESUF)) PROGS_CROSS = $(foreach X,$(TCC_X),$X-tcc$(EXESUF))
LIBTCC1_CROSS = $(foreach X,$(LIBTCC1_X),$X-libtcc1.a) LIBTCC1_CROSS = $(foreach X,$(LIBTCC1_X),$X-libtcc1.a)

View file

@ -1096,18 +1096,24 @@ static Sym *sym_copy(Sym *s0, Sym **ps)
return s; return s;
} }
/* copy a list of syms */ /* copy s->type.ref to stack 'ps' for VT_FUNC and VT_PTR */
static void sym_copy_ref(Sym *s0, Sym **ps) static void sym_copy_ref(Sym *s, Sym **ps)
{ {
Sym *s, **sp = &s0->type.ref; int bt = s->type.t & VT_BTYPE;
for (s = *sp, *sp = NULL; s; s = s->next) if (bt == VT_FUNC || bt == VT_PTR) {
sp = &(*sp = sym_copy(s, ps))->next; Sym **sp = &s->type.ref;
for (s = *sp, *sp = NULL; s; s = s->next) {
Sym *s2 = sym_copy(s, ps);
sp = &(*sp = s2)->next;
sym_copy_ref(s2, ps);
}
}
} }
/* define a new external reference to a symbol 'v' */ /* define a new external reference to a symbol 'v' */
static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad) static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad)
{ {
Sym *s; int bt; Sym *s;
/* look for global symbol */ /* look for global symbol */
s = sym_find(v); s = sym_find(v);
@ -1121,16 +1127,14 @@ static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad)
s->a = ad->a; s->a = ad->a;
s->asm_label = ad->asm_label; s->asm_label = ad->asm_label;
s->type.ref = type->ref; s->type.ref = type->ref;
bt = s->type.t & (VT_BTYPE|VT_ARRAY); /* copy type to the global stack */
/* copy type to the global stack also */ if (local_stack)
if (local_scope && (bt == VT_FUNC || (bt & VT_ARRAY)))
sym_copy_ref(s, &global_stack); sym_copy_ref(s, &global_stack);
} else { } else {
patch_storage(s, ad, type); patch_storage(s, ad, type);
bt = s->type.t & VT_BTYPE;
} }
/* push variables to local scope if any */ /* push variables on local_stack if any */
if (local_stack && bt != VT_FUNC) if (local_stack && (s->type.t & VT_BTYPE) != VT_FUNC)
s = sym_copy(s, &local_stack); s = sym_copy(s, &local_stack);
return s; return s;
} }

View file

@ -273,5 +273,27 @@ int main ()
int xxx[1] = {1}; int xxx[1] = {1};
int bar() { P(3, xxx[0]); return 0; } int bar() { P(3, xxx[0]); return 0; }
#elif defined test_var_4
struct yyy { int y; };
struct zzz;
void f1() {
extern char *x;
extern char **xx;
extern struct yyy y;
extern struct yyy *yy;
extern struct zzz z;
extern struct zzz *zz;
}
void f2() {
extern char *x;
extern char **xx;
extern struct yyy y;
extern struct yyy *yy;
extern struct zzz z;
extern struct zzz *zz;
}
struct yyy y, *yy;
struct zzz { int z; } z, *zz;
/******************************************************************/ /******************************************************************/
#endif #endif

View file

@ -132,3 +132,5 @@ bar : 3 ; 3
[test_var_3] [test_var_3]
60_errors_and_warnings.c:273: error: incompatible types for redefinition of 'xxx' 60_errors_and_warnings.c:273: error: incompatible types for redefinition of 'xxx'
[test_var_4]