c++: Don't require accessible dtors for some forms of new [PR59238]
authorJason Merrill <jason@redhat.com>
Wed, 9 Dec 2020 03:05:45 +0000 (22:05 -0500)
committerJason Merrill <jason@redhat.com>
Wed, 9 Dec 2020 05:36:07 +0000 (00:36 -0500)
Jakub noticed that in build_new_1 we needed to add tf_no_cleanup to avoid
building a cleanup for a TARGET_EXPR that we already know is going to be
used to initialize something, so the cleanup will never be run.  The best
place to add it is close to where we build the INIT_EXPR; in
cp_build_modify_expr fixes the single-object new, in expand_default_init
fixes array new.

Co-authored-by: Jakub Jelinek <jakub@redhat.com>
gcc/cp/ChangeLog:

PR c++/59238
* init.c (expand_default_init): Pass tf_no_cleanup when building
a TARGET_EXPR to go on the RHS of an INIT_EXPR.
* typeck.c (cp_build_modify_expr): Likewise.

gcc/testsuite/ChangeLog:

PR c++/59238
* g++.dg/cpp0x/new4.C: New test.

gcc/cp/init.c
gcc/cp/typeck.c
gcc/testsuite/g++.dg/cpp0x/new4.C [new file with mode: 0644]

index 0b98f338feb53c309a3ac9914666ae64bb37b134..3c3e05d9b212112667ecef1ef21757e30449bd54 100644 (file)
@@ -1922,7 +1922,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
           in an exception region.  */;
       else
        init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP,
-                           flags, complain);
+                           flags, complain | tf_no_cleanup);
 
       if (TREE_CODE (init) == MUST_NOT_THROW_EXPR)
        /* We need to protect the initialization of a catch parm with a
index 4d499af5ccb91cae326207d946125830f654b020..afbb8ef02e6e894fbdce72bd395dd533a59d88e0 100644 (file)
@@ -8860,7 +8860,7 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
        LOOKUP_ONLYCONVERTING.  */
     newrhs = convert_for_initialization (lhs, olhstype, newrhs, LOOKUP_NORMAL,
                                         ICR_INIT, NULL_TREE, 0,
-                                         complain);
+                                        complain | tf_no_cleanup);
   else
     newrhs = convert_for_assignment (olhstype, newrhs, ICR_ASSIGN,
                                     NULL_TREE, 0, complain, LOOKUP_IMPLICIT);
diff --git a/gcc/testsuite/g++.dg/cpp0x/new4.C b/gcc/testsuite/g++.dg/cpp0x/new4.C
new file mode 100644 (file)
index 0000000..728ef4e
--- /dev/null
@@ -0,0 +1,36 @@
+// PR c++/59238
+// { dg-do compile { target c++11 } }
+
+struct A { ~A () = delete; };
+A *pa{new A{}};
+A *pa2{new A[2]{}};
+
+class B { ~B () = default; };
+B *pb{new B{}};
+
+struct E {
+  ~E () = delete;
+private:
+  int x;
+};
+E *pe{new E{}};
+
+class C { ~C (); };
+C *pc{new C{}};
+
+class D { ~D () {} };
+D *pd{new D{}};
+
+struct F {
+  F () = default;
+  ~F () = delete;
+};
+F *pf{new F{}};
+
+struct G {
+  G () = default;
+  ~G () = delete;
+private:
+  int x;
+};
+G *pg{new G{}};