From 605538f46d277fe0931f72f032a24a675417ee2a Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Wed, 22 Feb 2023 17:59:31 +0100 Subject: [PATCH] Fix sym_scope of typedefs Sym.sym_scope and Sym.f (FuncAttr) share space, so blindly setting one clobbers the other. Right now this only leads to missing errors on incompatible typedefs (see testcase), which this commit fixes. But it points to a larger problem: Generally we can only manipulate Sym.f for anonymous and field symbols, not for anything that has a top-level name (basically any proper decl), because the latter use sym_scope. Luckily the functions type always contains an anonymous symbol (in sym->type.ref), so we can use that. But some of the functions attributes actually _do_ apply to the decl, not the type (e.g. always_inline), so we still have a problem possibly, when we update an pre-existing type that may already be shared with another decl. Would need untangling and perhaps using accessor functions that check that Sym.f and Sym.sym_scope aren't used for the same symbol. --- tccgen.c | 5 +++-- tests/tests2/60_errors_and_warnings.c | 8 +++++++ tests/tests2/60_errors_and_warnings.expect | 25 ++++++++++++---------- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/tccgen.c b/tccgen.c index 6a870096..53a25bf3 100644 --- a/tccgen.c +++ b/tccgen.c @@ -8482,7 +8482,8 @@ static int decl(int l) sym = sym_push(v, &type, 0, 0); } sym->a = ad.a; - sym->f = ad.f; + if ((type.t & VT_BTYPE) == VT_FUNC) + merge_funcattr(&sym->type.ref->f, &ad.f); if (debug_modes) tcc_debug_typedef (tcc_state, sym); } else if ((type.t & VT_BTYPE) == VT_VOID @@ -8493,7 +8494,7 @@ static int decl(int l) if ((type.t & VT_BTYPE) == VT_FUNC) { /* external function definition */ /* specific case for func_call attribute */ - type.ref->f = ad.f; + merge_funcattr(&type.ref->f, &ad.f); } else if (!(type.t & VT_ARRAY)) { /* not lvalue if array */ r |= VT_LVAL; diff --git a/tests/tests2/60_errors_and_warnings.c b/tests/tests2/60_errors_and_warnings.c index 570cd7f9..960c64f5 100644 --- a/tests/tests2/60_errors_and_warnings.c +++ b/tests/tests2/60_errors_and_warnings.c @@ -398,6 +398,14 @@ struct S2 { extern int array[2]; int array[] = { 1, 2, 3 }; +#elif defined test_incompatible_local_redef +void foo (void) +{ + typedef int localfunctype (int); + extern localfunctype func2; + typedef void localfunctype (int, int); +} + #elif defined test_cast_from_void void v() {} int f() { return v(); } diff --git a/tests/tests2/60_errors_and_warnings.expect b/tests/tests2/60_errors_and_warnings.expect index 06ec7feb..9a95e93e 100644 --- a/tests/tests2/60_errors_and_warnings.expect +++ b/tests/tests2/60_errors_and_warnings.expect @@ -190,28 +190,31 @@ bar : 3 ; 3 [test_conflicting_array_definition] 60_errors_and_warnings.c:399: error: incompatible types for redefinition of 'array' +[test_incompatible_local_redef] +60_errors_and_warnings.c:406: error: incompatible redefinition of 'localfunctype' + [test_cast_from_void] -60_errors_and_warnings.c:403: error: cannot convert 'void' to 'int' +60_errors_and_warnings.c:411: error: cannot convert 'void' to 'int' [test_switch_W1] -60_errors_and_warnings.c:419: warning: implicit declaration of function 'fink' +60_errors_and_warnings.c:427: warning: implicit declaration of function 'fink' [test_switch_W2] -60_errors_and_warnings.c:410: warning: unsupported option '-Wstuff' -60_errors_and_warnings.c:421: warning: 'stuff' attribute ignored +60_errors_and_warnings.c:418: warning: unsupported option '-Wstuff' +60_errors_and_warnings.c:429: warning: 'stuff' attribute ignored [test_switch_W3] -60_errors_and_warnings.c:418: error: assignment discards qualifiers from pointer target type +60_errors_and_warnings.c:426: error: assignment discards qualifiers from pointer target type [test_switch_W4] -60_errors_and_warnings.c:419: warning: implicit declaration of function 'fink' -60_errors_and_warnings.c:421: error: 'stuff' attribute ignored +60_errors_and_warnings.c:427: warning: implicit declaration of function 'fink' +60_errors_and_warnings.c:429: error: 'stuff' attribute ignored [test_invalid_funcparam_1] -60_errors_and_warnings.c:424: error: redeclaration of 'a' +60_errors_and_warnings.c:432: error: redeclaration of 'a' [test_invalid_funcparam_2] -60_errors_and_warnings.c:427: error: identifier expected +60_errors_and_warnings.c:435: error: identifier expected [test_array_funcparam] arg[0] = "X" @@ -221,7 +224,7 @@ arg[1] = "Y" [returns 78] [test_illegal_unicode] -60_errors_and_warnings.c:451: error: 0xffffffff is not a valid universal character +60_errors_and_warnings.c:459: error: 0xffffffff is not a valid universal character [test_error_string] -60_errors_and_warnings.c:456: error: #error \123\456 +60_errors_and_warnings.c:464: error: #error \123\456