From 7b8799e5ff02184d60df34a034396dc98ac59ed0 Mon Sep 17 00:00:00 2001 From: grischka Date: Tue, 16 Jul 2019 17:30:04 +0200 Subject: [PATCH] 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) --- Makefile | 2 +- tccgen.c | 28 ++++++++++++---------- tests/tests2/60_errors_and_warnings.c | 22 +++++++++++++++++ tests/tests2/60_errors_and_warnings.expect | 2 ++ 4 files changed, 41 insertions(+), 13 deletions(-) diff --git a/Makefile b/Makefile index 1c05e8a0..6c87f010 100644 --- a/Makefile +++ b/Makefile @@ -98,7 +98,7 @@ TCC_X += riscv64 # 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 = riscv64 +LIBTCC1_X += riscv64 PROGS_CROSS = $(foreach X,$(TCC_X),$X-tcc$(EXESUF)) LIBTCC1_CROSS = $(foreach X,$(LIBTCC1_X),$X-libtcc1.a) diff --git a/tccgen.c b/tccgen.c index bb7438bd..237869c8 100644 --- a/tccgen.c +++ b/tccgen.c @@ -1096,18 +1096,24 @@ static Sym *sym_copy(Sym *s0, Sym **ps) return s; } -/* copy a list of syms */ -static void sym_copy_ref(Sym *s0, Sym **ps) +/* copy s->type.ref to stack 'ps' for VT_FUNC and VT_PTR */ +static void sym_copy_ref(Sym *s, Sym **ps) { - Sym *s, **sp = &s0->type.ref; - for (s = *sp, *sp = NULL; s; s = s->next) - sp = &(*sp = sym_copy(s, ps))->next; + int bt = s->type.t & VT_BTYPE; + if (bt == VT_FUNC || bt == VT_PTR) { + 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' */ static Sym *external_sym(int v, CType *type, int r, AttributeDef *ad) { - Sym *s; int bt; + Sym *s; /* look for global symbol */ 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->asm_label = ad->asm_label; s->type.ref = type->ref; - bt = s->type.t & (VT_BTYPE|VT_ARRAY); - /* copy type to the global stack also */ - if (local_scope && (bt == VT_FUNC || (bt & VT_ARRAY))) + /* copy type to the global stack */ + if (local_stack) sym_copy_ref(s, &global_stack); } else { patch_storage(s, ad, type); - bt = s->type.t & VT_BTYPE; } - /* push variables to local scope if any */ - if (local_stack && bt != VT_FUNC) + /* push variables on local_stack if any */ + if (local_stack && (s->type.t & VT_BTYPE) != VT_FUNC) s = sym_copy(s, &local_stack); return s; } diff --git a/tests/tests2/60_errors_and_warnings.c b/tests/tests2/60_errors_and_warnings.c index b84eec2c..14ff527b 100644 --- a/tests/tests2/60_errors_and_warnings.c +++ b/tests/tests2/60_errors_and_warnings.c @@ -273,5 +273,27 @@ int main () int xxx[1] = {1}; 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 diff --git a/tests/tests2/60_errors_and_warnings.expect b/tests/tests2/60_errors_and_warnings.expect index f252355d..93986d80 100644 --- a/tests/tests2/60_errors_and_warnings.expect +++ b/tests/tests2/60_errors_and_warnings.expect @@ -132,3 +132,5 @@ bar : 3 ; 3 [test_var_3] 60_errors_and_warnings.c:273: error: incompatible types for redefinition of 'xxx' + +[test_var_4]