[gcc r17-2664] c++: Diagnose return from [[noreturn]] function during constant evaluation [PR126354]

Jakub Jelinek via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
https://gcc.gnu.org/g:571aae1dc596ec58bca11534800a857109dce498

commit r17-2664-g571aae1dc596ec58bca11534800a857109dce498
Author: Jakub Jelinek <[email protected]>
Date:   Thu Jul 23 15:42:10 2026 +0200

    c++: Diagnose return from [[noreturn]] function during constant evaluation [PR126354]
    
    This PR complains about g++ not diagnosing return from [[noreturn]]
    function (which is UB) during constant evaluation.
    
    This patch diagnoses that.
    I haven't included the [[noreturn]] function name in the diagnostics
    as it is printed in the context:
    /home/jakub/src/gcc/gcc/testsuite/g++.dg/cpp1y/pr126354.C:18:24:   in 'constexpr' expansion of 'bar()'
    /home/jakub/src/gcc/gcc/testsuite/g++.dg/cpp1y/pr126354.C:15:7:   in 'constexpr' expansion of 'foo(false)'
    /home/jakub/src/gcc/gcc/testsuite/g++.dg/cpp1y/pr126354.C:15:7: error: '[[noreturn]]' call returns
    But if you think it is better to emit
    error ("%<[[noreturn]]%> %qD call returns", fun);
    instead, I can certainly do that.
    
    2026-07-23  Jakub Jelinek  <[email protected]>
    
            PR c++/126354
            * constexpr.cc (cxx_eval_call_expression): Diagnose return from
            [[noreturn]] function.
    
            * g++.dg/cpp1y/pr126354.C: New test.
            * g++.dg/cpp26/pr126354.C: New test.
    
    Reviewed-by: Jason Merrill <[email protected]>

Diff:
---
 gcc/cp/constexpr.cc                   |  7 +++++++
 gcc/testsuite/g++.dg/cpp1y/pr126354.C | 18 ++++++++++++++++++
 gcc/testsuite/g++.dg/cpp26/pr126354.C | 28 ++++++++++++++++++++++++++++
 3 files changed, 53 insertions(+)

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index fe2c417bed7a..b4db9fd2bae4 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -4572,6 +4572,13 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
 	      cacheable = false;
 	      *jump_target = jmp_target;
 	    }
+	  else if (!*non_constant_p && TREE_THIS_VOLATILE (fun))
+	    {
+	      /* Return from a [[noreturn]] function.  */
+	      if (!ctx->quiet)
+		error ("%<[[noreturn]]%> call returns");
+	      *non_constant_p = true;
+	    }
 	  else if (DECL_CONSTRUCTOR_P (fun))
 	    /* This can be null for a subobject constructor call, in
 	       which case what we care about is the initialization
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr126354.C b/gcc/testsuite/g++.dg/cpp1y/pr126354.C
new file mode 100644
index 000000000000..9ea9fb837663
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr126354.C
@@ -0,0 +1,18 @@
+// PR c++/126354
+// { dg-do compile { target c++14 } }
+
+[[noreturn]] constexpr void
+foo (bool x)
+{
+  if (x)
+    for (;;)
+      ;
+}
+
+constexpr bool
+bar ()
+{
+  foo (false);		// { dg-error "'\\\[\\\[noreturn\\\]\\\]' call returns" }
+}
+
+constexpr bool a = bar ();
diff --git a/gcc/testsuite/g++.dg/cpp26/pr126354.C b/gcc/testsuite/g++.dg/cpp26/pr126354.C
new file mode 100644
index 000000000000..3261df675628
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp26/pr126354.C
@@ -0,0 +1,28 @@
+// PR c++/126354
+// { dg-do compile { target c++26 } }
+
+[[noreturn]] constexpr void
+foo (bool x)
+{
+  if (x)
+    throw 42;
+}
+
+consteval {
+  try
+    {
+      foo (true);
+      throw nullptr;
+    }
+  catch (int x)
+    {
+      if (x != 42)
+	throw nullptr;
+      return;
+    }
+  throw nullptr;
+}
+
+consteval {
+  foo (false);		// { dg-error "'\\\[\\\[noreturn\\\]\\\]' call returns" }
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.