Hi! 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.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 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>: For evaluation of cleanups use initially recorded jump_target pointee rather than whatever ends up in it after evaluation of the body operand. * 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 @@ -6008,6 +6008,7 @@ cxx_eval_constant_expression (const cons auto_vec<tree, 2> cleanups; vec<tree> *prev_cleanups = ctx->global->cleanups; ctx->global->cleanups = &cleanups; + tree initial_jump_target = jump_target ? *jump_target : NULL_TREE; r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, non_constant_p, overflow_p, @@ -6019,19 +6020,24 @@ cxx_eval_constant_expression (const cons FOR_EACH_VEC_ELT_REVERSE (cleanups, i, cleanup) cxx_eval_constant_expression (ctx, cleanup, false, non_constant_p, overflow_p, - jump_target); + jump_target ? &initial_jump_target + : NULL); } break; case TRY_FINALLY_EXPR: - r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, + { + tree initial_jump_target = jump_target ? *jump_target : NULL_TREE; + r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval, + non_constant_p, overflow_p, + jump_target); + 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); - 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); + jump_target ? &initial_jump_target + : NULL); + } break; case CLEANUP_STMT: --- 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