c++: Fix up constexpr CLEANUP_POINT_EXPR and TRY_FINALLY_EXPR handling [PR97790]
As the testcase shows, CLEANUP_POINT_EXPR (and I think TRY_FINALLY_EXPR too) suffer from the same problem that I was trying to fix in r10-3597-g1006c9d4395a939820df76f37c7b085a4a1a003f for CLEANUP_STMT, namely that if in the middle of the body expression of those stmts is e.g. return stmt, goto, break or continue (something that changes *jump_target and makes it start skipping stmts), we then skip the cleanups too, which is not appropriate - the cleanups were either queued up during the non-skipping execution of the body (for CLEANUP_POINT_EXPR), or for TRY_FINALLY_EXPR are relevant already after entering the body block. > Would it make sense to always use a NULL jump_target when evaluating > cleanups? I was afraid of that, especially for TRY_FINALLY_EXPR, but it seems that during constexpr evaluation the cleanups will most often be just very simple destructor calls (or calls to cleanup attribute functions). Furthermore, for neither of these 3 tree codes we'll reach that code if jump_target && *jump_target initially (there is a return NULL_TREE much earlier for those except for trees that could embed labels etc. in it and clearly these 3 don't count in that). 2020-11-12 Jakub Jelinek <jakub@redhat.com> PR c++/97790 * constexpr.c (cxx_eval_constant_expression) <case CLEANUP_POINT_EXPR, case TRY_FINALLY_EXPR, case CLEANUP_STMT>: Don't pass jump_target to cxx_eval_constant_expression when evaluating the cleanups. * g++.dg/cpp2a/constexpr-dtor9.C: New test.
This commit is contained in:
parent
5d9ade39b8
commit
fc531c2ed3
|
@ -6018,8 +6018,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
|||
/* Evaluate the cleanups. */
|
||||
FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup)
|
||||
cxx_eval_constant_expression (ctx, cleanup, false,
|
||||
non_constant_p, overflow_p,
|
||||
jump_target);
|
||||
non_constant_p, overflow_p);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -6030,29 +6029,20 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|
|||
if (!*non_constant_p)
|
||||
/* Also evaluate the cleanup. */
|
||||
cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), true,
|
||||
non_constant_p, overflow_p,
|
||||
jump_target);
|
||||
non_constant_p, overflow_p);
|
||||
break;
|
||||
|
||||
case CLEANUP_STMT:
|
||||
{
|
||||
tree initial_jump_target = jump_target ? *jump_target : NULL_TREE;
|
||||
r = cxx_eval_constant_expression (ctx, CLEANUP_BODY (t), lval,
|
||||
non_constant_p, overflow_p,
|
||||
jump_target);
|
||||
if (!CLEANUP_EH_ONLY (t) && !*non_constant_p)
|
||||
{
|
||||
iloc_sentinel ils (loc);
|
||||
/* Also evaluate the cleanup. If we weren't skipping at the
|
||||
start of the CLEANUP_BODY, change jump_target temporarily
|
||||
to &initial_jump_target, so that even a return or break or
|
||||
continue in the body doesn't skip the cleanup. */
|
||||
cxx_eval_constant_expression (ctx, CLEANUP_EXPR (t), true,
|
||||
non_constant_p, overflow_p,
|
||||
jump_target ? &initial_jump_target
|
||||
: NULL);
|
||||
}
|
||||
}
|
||||
r = cxx_eval_constant_expression (ctx, CLEANUP_BODY (t), lval,
|
||||
non_constant_p, overflow_p,
|
||||
jump_target);
|
||||
if (!CLEANUP_EH_ONLY (t) && !*non_constant_p)
|
||||
{
|
||||
iloc_sentinel ils (loc);
|
||||
/* Also evaluate the cleanup. */
|
||||
cxx_eval_constant_expression (ctx, CLEANUP_EXPR (t), true,
|
||||
non_constant_p, overflow_p);
|
||||
}
|
||||
break;
|
||||
|
||||
/* These differ from cxx_eval_unary_expression in that this doesn't
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
// PR c++/97790
|
||||
// { dg-do compile { target c++20 } }
|
||||
|
||||
struct S
|
||||
{
|
||||
int *d;
|
||||
int n;
|
||||
constexpr S () : d(new int[1]{}), n(1) {}
|
||||
constexpr ~S () { delete [] d; }
|
||||
};
|
||||
|
||||
constexpr S
|
||||
foo ()
|
||||
{
|
||||
return S ();
|
||||
}
|
||||
|
||||
constexpr int
|
||||
bar ()
|
||||
{
|
||||
return foo ().n;
|
||||
}
|
||||
|
||||
constexpr int
|
||||
baz ()
|
||||
{
|
||||
return S ().n;
|
||||
}
|
||||
|
||||
constexpr int a = baz ();
|
||||
constexpr int b = bar ();
|
Loading…
Reference in New Issue