From d7f2775af8d67d2c3b08823a69fae35d516dfea2 Mon Sep 17 00:00:00 2001 From: Michael Matz Date: Sat, 13 Feb 2021 03:20:44 +0100 Subject: [PATCH] Fix endless recursion due to type scoping 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 } --- tccgen.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tccgen.c b/tccgen.c index 0e62a0ec..aa15831a 100644 --- a/tccgen.c +++ b/tccgen.c @@ -1817,7 +1817,7 @@ static Sym *sym_copy(Sym *s0, Sym **ps) static void sym_copy_ref(Sym *s, Sym **ps) { int bt = s->type.t & VT_BTYPE; - if (bt == VT_FUNC || bt == VT_PTR) { + if (bt == VT_FUNC || bt == VT_PTR || (bt == VT_STRUCT && s->sym_scope)) { Sym **sp = &s->type.ref; for (s = *sp, *sp = NULL; s; s = s->next) { Sym *s2 = sym_copy(s, ps);