]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
calls: Allow musttail calls to noreturn [PR121159]
authorJakub Jelinek <jakub@redhat.com>
Tue, 29 Jul 2025 07:49:55 +0000 (09:49 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 29 Jul 2025 08:15:15 +0000 (10:15 +0200)
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.

2025-07-29  Jakub Jelinek  <jakub@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.

(cherry picked from commit f4abe216199930adfa110059c3c8e642c585388b)

gcc/calls.cc
gcc/testsuite/c-c++-common/pr121159.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/plugin/must-tail-call-2.c

index 076e046a8ef1989af3bfe5f9941fa64bfba93c45..099a353909e817f1786eb8ede12292963c35fc5c 100644 (file)
@@ -2580,7 +2580,8 @@ can_implement_as_sibling_call_p (tree exp,
       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;
diff --git a/gcc/testsuite/c-c++-common/pr121159.c b/gcc/testsuite/c-c++-common/pr121159.c
new file mode 100644 (file)
index 0000000..c8c5d67
--- /dev/null
@@ -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 ();
+}
index d51d15cc087978762d42058a2bd96dc5dcd94882..6f65f4ab96cbf8e50ff0f29a0ee5cc7afd44af9c 100644 (file)
@@ -55,5 +55,5 @@ volatile fn_ptr_t fn_ptr;
 void
 test_5 (void)
 {
-  fn_ptr (); /* { dg-error "cannot tail-call: " } */
+  fn_ptr ();
 }