On 11/11/20 10:26 AM, Jakub Jelinek wrote:
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.

Would it make sense to always use a NULL jump_target when evaluating cleanups?

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


Reply via email to