Hi!

The following testcase is miscompiled, we throw exception only during
the first bar () call and not during the second and in that case reach
the inline asm.
The problem is that the TARGET_EXPR handling calls
            ctx->global->put_value (new_ctx.object, new_ctx.ctor);
first for aggregate/vectors, then
        if (is_complex)
          /* In case no initialization actually happens, clear out any
             void_node from a previous evaluation.  */
          ctx->global->put_value (slot, NULL_TREE);
and then recurses on TARGET_EXPR_INITIAL.
If that throws, we keep it as is and return.  If (!is_complex), we
can in that case keep a value cached for the TARGET_EXPR_SLOT.  For
*non_constant_p I think that is a non-issue, but for *jump_target
it can still be a constant expression.

The following patch fixes it by calling put_value in that case for
the !is_complex case.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

Or should it be called ragardless of !is_complex?

2026-03-04  Jakub Jelinek  <[email protected]>

        PR c++/124145
        * constexpr.cc (cxx_eval_constant_expression) <case TARGET_EXPR>: If
        *jump_target && !is_complex, call put_value with NULL_TREE value on
        slot.  Use TARGET_EXPR_INITIAL instead of TREE_OPERAND.

        * g++.dg/cpp26/constexpr-eh18.C: New test.

--- gcc/cp/constexpr.cc.jj      2026-03-02 07:43:12.342788130 +0100
+++ gcc/cp/constexpr.cc 2026-03-03 13:41:31.435442193 +0100
@@ -9486,13 +9486,17 @@ cxx_eval_constant_expression (const cons
 
        /* Pass vc_prvalue because this indicates
           initialization of a temporary.  */
-       r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), vc_prvalue,
-                                         non_constant_p, overflow_p,
-                                         jump_target);
+       r = cxx_eval_constant_expression (ctx, TARGET_EXPR_INITIAL (t),
+                                         vc_prvalue, non_constant_p,
+                                         overflow_p, jump_target);
        if (*non_constant_p)
          break;
        if (*jump_target)
-         return NULL_TREE;
+         {
+           if (!is_complex)
+             ctx->global->put_value (slot, NULL_TREE);
+           return NULL_TREE;
+         }
        if (!is_complex)
          {
            r = unshare_constructor (r);
--- gcc/testsuite/g++.dg/cpp26/constexpr-eh18.C.jj      2026-03-03 
13:44:19.501639167 +0100
+++ gcc/testsuite/g++.dg/cpp26/constexpr-eh18.C 2026-03-03 13:43:51.868100042 
+0100
@@ -0,0 +1,42 @@
+// PR c++/124145
+// { dg-do compile { target c++26 } }
+
+struct S {};
+
+constexpr S
+foo (S x)
+{
+  throw 123;
+  return x;
+}
+
+constexpr void
+bar ()
+{
+  foo (S {});
+}
+
+constexpr bool
+baz ()
+{
+  try
+    {
+      bar ();
+      asm  ("");
+    }
+  catch (int)
+    {
+    }
+
+  try
+    {
+      bar ();
+      asm ("");
+    }
+  catch (int)
+    {
+    }
+  return true;
+}
+
+static_assert (baz ());

        Jakub

Reply via email to