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