On 12/8/20 5:57 PM, Jakub Jelinek wrote:
On Tue, Dec 08, 2020 at 05:34:13PM -0500, Jason Merrill wrote:
On 12/8/20 4:23 AM, Jakub Jelinek wrote:
The earlier cases in build_new_1 already use | tf_no_cleanup, these are
cases where the type isn't type_build_ctor_call nor explicit_value_init_p.
It is true that often one can't delete these (unless e.g. the dtor would be
private or protected and deletion done in some method), but diagnosing that
belongs to delete, not new.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for
trunk?
It wasn't clear to me why adding tf_no_cleanup in those places made a
difference; after some investigation I tried moving the tf_no_cleanup closer
to where we build a TARGET_EXPR and then soon put it in an INIT_EXPR.
I'm afraid I don't know the FE enough to know.
I see cp_build_modify_expr can be called with INIT_EXPR from
perform_member_init, this build_new_1 case and get_temp_regvar.
Whether it is ok for all of them not to build destructors is something I
have no idea about, for build_new_1 case I was confident it shouldn't be
built.
It is OK; those other places are also using it to initialize something,
so there's never a temporary.
Applied, thanks.
commit 3421b3cc35317815a60ee224b9593549d617d0ac
Author: Jason Merrill <ja...@redhat.com>
Date: Tue Dec 8 22:05:45 2020 -0500
c++: Don't require accessible dtors for some forms of new [PR59238]
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 <ja...@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.
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 0b98f338feb..3c3e05d9b21 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 4d499af5ccb..afbb8ef02e6 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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
index 00000000000..728ef4ee7ce
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/new4.C
@@ -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{}};