From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id B5ECD3856974; Thu, 12 Oct 2023 21:18:10 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B5ECD3856974 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1697145490; bh=mg5wP9aVrBiDId9dQYlZJZ39V9RpLmbecdgP/ryGk1Y=; h=From:To:Subject:Date:In-Reply-To:References:From; b=XGZylxVCEdMKyR07XjmsHNIIDqLM5VsxhInbA1G987SW8HWl7N5qr9vDTyyqqAo/D MIzAaFxEk7lpPtDM8nfPySOjE6/FKET2zR0ayK1/lps4X0N4eYy8yHe+VtCng6hKpW CstWJCAz/Au2cwXFnW4mhHZqyKWDnGL4CQaAqPDw= From: "lukas.graetz@tu-darmstadt.de" To: gcc-bugs@gcc.gnu.org Subject: [Bug c/111786] No tail recursion for simple program Date: Thu, 12 Oct 2023 21:18:10 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c X-Bugzilla-Version: 13.2.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: lukas.graetz@tu-darmstadt.de X-Bugzilla-Status: RESOLVED X-Bugzilla-Resolution: DUPLICATE X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 List-Id: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D111786 --- Comment #3 from Lukas Gr=C3=A4tz --- (In reply to Jakub Jelinek from comment #1) > We completely intentionally don't emit tail calls to noreturn functions, = so > that e.g. in case of abort one doesn't need to virtually reconstruct > backtrace. > In your case, the interprocedural optimizations determine expr_main_origi= nal > is noreturn and so calls it normally (and optimizes away anything after t= hat > call). Thank you very much indeed! (Ah yes, this also explains why there is not "ret".) And sorry for not realizing that this is duplicate. So the "call" is intentionally emitted by gcc for a better debugging experience. I agree, th= is makes perfectly sense in many cases. However, the price of better debugging seems to be the danger of a stack overflow. After I understood your "complete" intention, it took me about 20= min to construct an example with bears a stack overflow following that intentio= n. --- void foo(int n) { if (n =3D=3D 0) exit(0); int x[200]; for (int i =3D 0; i < 200; i++) extern_function(x[i], x[200-i]); return foo(n-1); } --- After adding __attribute__((noreturn)), compiling with -O3 and passing 1000= 0 to foo(), I get a segmentation fault. There is still a warning "function decla= red =E2=80=98noreturn=E2=80=99 has a =E2=80=98return=E2=80=99 statement". But i= n our case, the noreturn attribute is not wrong, because none of the recursive calls actually do return. This might be something that interprocedure optimizations detect in the future. = So even without attribute noreturn, gcc could decide to produce no tail recurs= ion (because it is a noreturn function, regardless of the noreturn attribute). Last remark, then I remain silent. I just learned that clang actually has t= he attribute musttail which would help for my reported C file as well as in the foo() example above to prevent the stack overflow. But I guess it is not planned to add musttail to gcc?=