On 3/5/26 3:25 AM, Jakub Jelinek wrote:
On Wed, Mar 04, 2026 at 12:56:38PM -0500, Jason Merrill wrote:
I've been worrying also about something like:
struct S { int s; };

constexpr S
foo (int x)
{
    return S { x };
}

constexpr int
bar (int x)
{
    return foo (x).s;
}

constexpr bool
baz ()
{
    if (bar (42) != 42)
      throw 1;

    if (bar (43) != 43)
      throw 2;
    return true;
}

static_assert (baz ());
but that works fine - if TARGET_EXPR_INITIAL doesn't throw (and isn't
non-constant), and it is wrapped into a CLEANUP_POINT_EXPR, that
CLEANUP_POINT_EXPR sets ctx->save_expr and TARGET_EXPR handling will
if (ctx->save_expr)
    ctx->save_exprs->safe_push (slot);
and then CLEANUP_POINT_EXPR handling will
          /* Forget SAVE_EXPRs and TARGET_EXPRs created by this
             full-expression.  */
          for (tree save_expr : save_exprs)
            destroy_value_checked (ctx, save_expr, non_constant_p);
Anyway, that means another way to fix this would be to move
          if (ctx->save_exprs)
            ctx->save_exprs->safe_push (slot);
before
          if (*jump_target)
            return NULL_TREE;

...this sounds better.

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

OK.

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

        PR c++/124145
        * constexpr.cc (cxx_eval_constant_expression) <case TARGET_EXPR>: Move
        ctx->save_expr->safe_push (slot) call before if (*jump_target) test.
        Use TARGET_EXPR_INITIAL instead of TREE_OPERAND.

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

--- gcc/cp/constexpr.cc.jj      2026-03-03 15:43:28.514891948 +0100
+++ gcc/cp/constexpr.cc 2026-03-04 19:42:38.212514610 +0100
@@ -9486,11 +9486,13 @@ 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 (ctx->save_exprs)
+         ctx->save_exprs->safe_push (slot);
        if (*jump_target)
          return NULL_TREE;
        if (!is_complex)
@@ -9509,8 +9511,6 @@ cxx_eval_constant_expression (const cons
            if (CLEANUP_EH_ONLY (t))
              ctx->global->cleanups->safe_push (NULL_TREE);
          }
-       if (ctx->save_exprs)
-         ctx->save_exprs->safe_push (slot);
        if (lval)
          return slot;
        if (is_complex)
--- 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