Hi!

In the PR119483 r15-9003 change we've allowed musttail calls to noreturn
functions, after all the decision not to normally tail call noreturn
functions is not because it is not possible to tail call those, but because
it screws up backtraces.  As the following testcase shows, we've done that
only for functions not declared [[noreturn]]/_Noreturn but later on
discovered through IPA as noreturn.  Functions explicitly declared
[[noreturn]] have (for historical reasons) volatile FUNCTION_TYPE and
the FUNCTION_DECLs are volatile as well, so in order to support those
we shouldn't complain on ECF_NORETURN (we've stopped doing so for musttail
in PR119483) but also shouldn't complain about TYPE_VOLATILE on their
FUNCTION_TYPE (something that IPA doesn't change, I think it only sets
TREE_THIS_VOLATILE on the FUNCTION_DECL).  volatile on function type
really means noreturn as well, it has no other meaning.

Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux,
ok for trunk/15.2?

2025-07-29  Jakub Jelinek  <ja...@redhat.com>

        PR middle-end/121159
        * calls.cc (can_implement_as_sibling_call_p): Don't reject declared
        noreturn functions in musttail calls.

        * c-c++-common/pr121159.c: New test.
        * gcc.dg/plugin/must-tail-call-2.c (test_5): Don't expect an error.

--- gcc/calls.cc.jj     2025-06-04 17:21:01.000000000 +0200
+++ gcc/calls.cc        2025-07-28 11:58:35.205769000 +0200
@@ -2589,7 +2589,8 @@ can_implement_as_sibling_call_p (tree ex
       return false;
     }
 
-  if (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (addr))))
+  if (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (addr)))
+      && !CALL_EXPR_MUST_TAIL_CALL (exp))
     {
       maybe_complain_about_tail_call (exp, _("volatile function type"));
       return false;
--- gcc/testsuite/c-c++-common/pr121159.c.jj    2025-07-28 12:09:37.031226990 
+0200
+++ gcc/testsuite/c-c++-common/pr121159.c       2025-07-28 12:09:24.069394221 
+0200
@@ -0,0 +1,17 @@
+/* PR middle-end/121159 */
+/* { dg-do compile { target musttail } } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times "foo \\\(\[^\n\r]*\\\); \\\[tail call\\\] 
\\\[must tail call\\\]" 1 "optimized" } } */
+               
+[[noreturn, gnu::noipa]] void
+foo (void)
+{
+  for (;;)
+    ;
+}
+
+void
+bar (void)
+{
+  [[gnu::musttail]] return foo ();
+}
--- gcc/testsuite/gcc.dg/plugin/must-tail-call-2.c.jj   2023-03-08 
21:44:15.986550516 +0100
+++ gcc/testsuite/gcc.dg/plugin/must-tail-call-2.c      2025-07-29 
08:48:30.736998832 +0200
@@ -55,5 +55,5 @@ volatile fn_ptr_t fn_ptr;
 void
 test_5 (void)
 {
-  fn_ptr (); /* { dg-error "cannot tail-call: " } */
+  fn_ptr ();
 }

        Jakub

Reply via email to