c++: don't preevaluate new-initializer
authorJason Merrill <jason@redhat.com>
Tue, 4 Jan 2022 19:39:52 +0000 (14:39 -0500)
committerJason Merrill <jason@redhat.com>
Fri, 7 Jan 2022 00:22:47 +0000 (19:22 -0500)
The preevaluation code was causing trouble with my fix for PR94041, and now
I see that it's actually wrong since P0145 was adopted for C++17, mandating
order of evaluation for many expressions that were previously unspecified.
I don't see a need to preserve the preevaluation code for older standard
modes.

gcc/cp/ChangeLog:

* init.c (build_new_1): Remove preevaluation code.

gcc/testsuite/ChangeLog:

* g++.old-deja/g++.martin/new1.C: Don't expect preeval.
* g++.dg/tree-ssa/stabilize1.C: Removed.

gcc/cp/init.c
gcc/testsuite/g++.dg/tree-ssa/stabilize1.C [deleted file]
gcc/testsuite/g++.old-deja/g++.martin/new1.C

index 9d616f3..2cab4b4 100644 (file)
@@ -3047,7 +3047,6 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
      address of the first array element.  This node is a VAR_DECL, and
      is therefore reusable.  */
   tree data_addr;
-  tree init_preeval_expr = NULL_TREE;
   tree orig_type = type;
 
   if (nelts)
@@ -3561,7 +3560,6 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
      placement delete.  */
   if (is_initialized)
     {
-      bool stable;
       bool explicit_value_init_p = false;
 
       if (*init != NULL && (*init)->is_empty ())
@@ -3587,7 +3585,6 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
                                                   init, elt_type,
                                                   LOOKUP_NORMAL,
                                                   complain);
-         stable = stabilize_init (init_expr, &init_preeval_expr);
        }
       else if (array_p)
        {
@@ -3633,11 +3630,6 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
                              explicit_value_init_p,
                              /*from_array=*/0,
                               complain);
-
-         /* An array initialization is stable because the initialization
-            of each element is a full-expression, so the temporaries don't
-            leak out.  */
-         stable = true;
        }
       else
        {
@@ -3694,8 +3686,6 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
              = replace_placeholders (TREE_OPERAND (init_expr, 1),
                                      TREE_OPERAND (init_expr, 0),
                                      &had_placeholder);
-         stable = (!had_placeholder
-                   && stabilize_init (init_expr, &init_preeval_expr));
        }
 
       if (init_expr == error_mark_node)
@@ -3726,20 +3716,7 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
                      alloc_fn,
                      complain));
 
-         if (!cleanup)
-           /* We're done.  */;
-         else if (stable)
-           /* This is much simpler if we were able to preevaluate all of
-              the arguments to the constructor call.  */
-           {
-             /* CLEANUP is compiler-generated, so no diagnostics.  */
-             suppress_warning (cleanup);
-             init_expr = build2 (TRY_CATCH_EXPR, void_type_node,
-                                 init_expr, cleanup);
-             /* Likewise, this try-catch is compiler-generated.  */
-             suppress_warning (init_expr);
-           }
-         else
+         if (cleanup && !processing_template_decl)
            /* Ack!  First we allocate the memory.  Then we set our sentry
               variable to true, and expand a cleanup that deletes the
               memory if sentry is true.  Then we run the constructor, and
@@ -3747,9 +3724,13 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
 
               We need to do this because we allocate the space first, so
               if there are any temporaries with cleanups in the
-              constructor args and we weren't able to preevaluate them, we
-              need this EH region to extend until end of full-expression
-              to preserve nesting.  */
+              constructor args, we need this EH region to extend until
+              end of full-expression to preserve nesting.
+
+              We used to try to evaluate the args first to avoid this, but
+              since C++17 [expr.new] says that "The invocation of the
+              allocation function is sequenced before the evaluations of
+              expressions in the new-initializer."  */
            {
              tree end, sentry, begin;
 
@@ -3810,9 +3791,6 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
       rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), alloc_expr, rval);
     }
 
-  if (init_preeval_expr)
-    rval = build2 (COMPOUND_EXPR, TREE_TYPE (rval), init_preeval_expr, rval);
-
   /* A new-expression is never an lvalue.  */
   gcc_assert (!obvalue_p (rval));
 
diff --git a/gcc/testsuite/g++.dg/tree-ssa/stabilize1.C b/gcc/testsuite/g++.dg/tree-ssa/stabilize1.C
deleted file mode 100644 (file)
index 5eb0bf8..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-// PR c++/53356
-// { dg-options "-fdump-tree-gimple" }
-// { dg-final { scan-tree-dump-not "= 0" "gimple" } }
-
-class A {};
-
-struct B {
-    operator const A &() const;
-};
-
-A* cause_ICE() {
-    return new A(B());
-}
index 502c4f4..18eb88d 100644 (file)
@@ -1,5 +1,5 @@
 // { dg-do run  }
-//Lifetime of temporaries: 
+//Lifetime of temporaries:
 //egcs 2.92 performs cleanup for temporaries inside new expressions
 //after the new is complete, not at the end of the full expression.
 
@@ -71,8 +71,8 @@ void test1()
     func(new B(A(10).addr()));
   }catch(int){
   }
-  CHECK(ctor_done==1);
-  CHECK(new_done==2);
+  CHECK(new_done==1);
+  CHECK(ctor_done==2);
   CHECK(func_done==3);
   CHECK(dtor_done==4);
   CHECK(delete_done==0);
@@ -86,10 +86,10 @@ void test2()
     func(new B(A(10).addr()));
   }catch(int){
   }
-  CHECK(ctor_done==1);
-  CHECK(new_done==2);
+  CHECK(new_done==1);
+  CHECK(ctor_done==0);
   CHECK(func_done==0);
-  CHECK(dtor_done==3);
+  CHECK(dtor_done==0);
   CHECK(delete_done==0);
 }
 
@@ -101,11 +101,11 @@ void test3()
     func(new B(A(10).addr()));
   }catch(int){
   }
-  CHECK(new_done==0);
-  CHECK(ctor_done==1);
+  CHECK(new_done==1);
+  CHECK(ctor_done==2);
   CHECK(func_done==0);
   CHECK(dtor_done==0);
-  CHECK(delete_done==0);
+  CHECK(delete_done==3);
 }
 
 int main()