mirror of
https://github.com/gcc-mirror/gcc.git
synced 2026-05-06 14:59:39 +02:00
c++: Avoid caching TARGET_EXPR slot value if exception is thrown from TARGET_EXPR_INITIAL [PR124145]
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.
Even for is_complex it can actually store partially the result in the
slot before throwing.
When TARGET_EXPR_INITIAL doesn't throw, we do
if (ctx->save_expr)
ctx->save_expr->safe_push (slot);
and that arranges for the value in slot be invalidated at the end of
surrounding CLEANUP_POINT_EXPR.
But in case when it does throw this isn't done.
The following patch fixes it by moving that push to save_expr
before the if (*jump_target) return NULL_TREE; check.
2026-03-05 Jakub Jelinek <jakub@redhat.com>
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.
This commit is contained in:
committed by
Jakub Jelinek
parent
1b404c5744
commit
0970bb8565
@@ -9486,11 +9486,13 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
||||
|
||||
/* 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 constexpr_ctx *ctx, tree t,
|
||||
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)
|
||||
|
||||
42
gcc/testsuite/g++.dg/cpp26/constexpr-eh18.C
Normal file
42
gcc/testsuite/g++.dg/cpp26/constexpr-eh18.C
Normal file
@@ -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 ());
|
||||
Reference in New Issue
Block a user