On 11/11/20 3:04 PM, Jakub Jelinek wrote:
On Wed, Nov 11, 2020 at 02:11:14PM -0500, Jason Merrill via Gcc-patches wrote:
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).
This adjusted patch doesn't have any check-c++-all regressions, would that
be ok for trunk if it passes whole bootstrap/regtest?
OK.
2020-11-11 Jakub Jelinek <ja...@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.
--- gcc/cp/constexpr.c.jj 2020-11-04 09:35:10.025029335 +0100
+++ gcc/cp/constexpr.c 2020-11-11 13:52:37.538466295 +0100
@@ -6018,8 +6018,7 @@ cxx_eval_constant_expression (const cons
/* 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 cons
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
--- gcc/testsuite/g++.dg/cpp2a/constexpr-dtor9.C.jj 2020-11-11
13:57:16.572334917 +0100
+++ gcc/testsuite/g++.dg/cpp2a/constexpr-dtor9.C 2020-11-11
13:57:45.510010165 +0100
@@ -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 ();
Jakub