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.
This commit is contained in:
Michael Matz 2023-02-22 17:59:31 +01:00
parent bdec3c5345
commit 605538f46d
3 changed files with 25 additions and 13 deletions

View File

@ -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;

View File

@ -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(); }

View File

@ -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