this change fixes building of invalid types. The inner scope struct P is return type of the forward decl foobar. The outer scope foobar() call implicitely declares that function again, with int return type; overall this leads to access within the sym free list, effectively building up a type directly referring to itself, leading to endless recursion later. The testcase is: void n(void) { { struct P { int __val; }; struct P foobar(); // 1 } foobar(); // 2 } I've not included it in tests2 for now, because tcc accepts this. Ideally we would like to reject it (as 'int foobar();' is incompatible with the earlier decl). clang also accepts it, but only because it's not handling (1) above as an implicit decl of foobar (it warns, and with -pedantic also warns about the type incompatiblity). GCC rejects this. Implementing that in tcc requires some surgery, as we need to differ between these cases: { struct P foo(int); // 1 foo(); // no implicit decl, call to foo from 1 } and { { struct P foo(int); // 2 } foo(); // implicit decl, _incompatible_ with 2 }
Unified · Split
| @@ -1817,7 +1817,7 @@ static Sym *sym_copy(Sym *s0, Sym **ps) · 1816 unmodified lines | |||
| 1817 | static void sym_copy_ref(Sym *s, Sym **ps) | 1817 | static void sym_copy_ref(Sym *s, Sym **ps) |
| 1818 | { | 1818 | { |
| 1819 | int bt = s->type.t & VT_BTYPE; | 1819 | int bt = s->type.t & VT_BTYPE; |
| 1820 | if (bt == VT_FUNC || bt == VT_PTR) { | 1820 | if (bt == VT_FUNC || bt == VT_PTR || (bt == VT_STRUCT && s->sym_scope)) { |
| 1821 | Sym **sp = &s->type.ref; | 1821 | Sym **sp = &s->type.ref; |
| 1822 | for (s = *sp, *sp = NULL; s; s = s->next) { | 1822 | for (s = *sp, *sp = NULL; s; s = s->next) { |
| 1823 | Sym *s2 = sym_copy(s, ps); | 1823 | Sym *s2 = sym_copy(s, ps); |