Patchwork C++ PATCH for c++/48873 (unnecessary dtor calls in new-expressions)

login
register
mail settings
Submitter Jason Merrill
Date May 5, 2011, 2:53 p.m.
Message ID <4DC2B9E1.2020200@redhat.com>
Download mbox | patch
Permalink /patch/94280/
State New
Headers show

Comments

Jason Merrill - May 5, 2011, 2:53 p.m.
Here the issue was that build_new_1 wants to stabilize any constructor 
arguments so that the EH region for deleting the allocated memory can be 
as small as possible.  But stabilize_expr was being over-eager, making a 
copy of a class with trivial constructors, but a non-trivial (and indeed 
non-callable) destructor.  And even if it didn't have a problematic 
destructor, there's no reason to introduce extra copies of trivially 
copyable classes.  So this patch changes stabilize_expr to only make 
copies of scalar types and class prvalues.

Tested x86_64-pc-linux-gnu, applying to trunk.
commit 21a411247eb5e59895aa54ff9a85e3cf8795a81a
Author: Jason Merrill <jason@redhat.com>
Date:   Wed May 4 11:15:30 2011 -0400

    	PR c++/48873
    	* tree.c (stabilize_expr): Don't make gratuitous copies of classes.

Patch

diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 0f2f86c..9a6e26d 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -3119,7 +3119,10 @@  stabilize_expr (tree exp, tree* initp)
 
   if (!TREE_SIDE_EFFECTS (exp))
     init_expr = NULL_TREE;
-  else if (!TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (exp))
+  /* There are no expressions with REFERENCE_TYPE, but there can be call
+     arguments with such a type; just treat it as a pointer.  */
+  else if (TREE_CODE (TREE_TYPE (exp)) == REFERENCE_TYPE
+	   || SCALAR_TYPE_P (exp)
 	   || !lvalue_or_rvalue_with_address_p (exp))
     {
       init_expr = get_target_expr (exp);
diff --git a/gcc/testsuite/g++.dg/init/new32.C b/gcc/testsuite/g++.dg/init/new32.C
new file mode 100644
index 0000000..f827857
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/new32.C
@@ -0,0 +1,16 @@ 
+// PR c++/48873
+
+#include <new>
+
+struct D {
+private:
+  ~D();
+};
+
+template<class T>
+T& create();
+
+void f()
+{
+  D* dp = new (((void*) 0)) D(create<D>()); // #
+}