Patchwork C++ PATCH for c++/34949 (destructor clobbers object)

login
register
mail settings
Submitter Jason Merrill
Date April 2, 2013, 9:09 p.m.
Message ID <515B48F9.5080805@redhat.com>
Download mbox | patch
Permalink /patch/233144/
State New
Headers show

Comments

Jason Merrill - April 2, 2013, 9:09 p.m.
Now that Jakub has checked in support for MEM_REF clobbers, we can use 
that to let the front end tell the back end that nothing in an object is 
interesting after the destructor is complete.  This should allow us to 
optimize away assignments to vtable pointers if the destructor doesn't 
use them, and so on.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

commit dcad5dc2a92840dee3bf153448ed2ccb4ace3b46
Author: Jason Merrill <jason@redhat.com>
Date:   Tue Apr 2 17:05:34 2013 -0400

    	PR c++/34949
    	* decl.c (begin_destructor_body): Clobber the object in a cleanup.

diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 40200b0..70137f4 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -13555,6 +13555,14 @@  begin_destructor_body (void)
       initialize_vtbl_ptrs (current_class_ptr);
       finish_compound_stmt (compound_stmt);
 
+      /* Insert a cleanup to let the back end know that the object is dead
+	 when we exit the destructor, either normally or via exception.  */
+      tree clobber = build_constructor (current_class_type, NULL);
+      TREE_THIS_VOLATILE (clobber) = true;
+      tree exprstmt = build2 (MODIFY_EXPR, current_class_type,
+			      current_class_ref, clobber);
+      finish_decl_cleanup (NULL_TREE, exprstmt);
+
       /* And insert cleanups for our bases and members so that they
 	 will be properly destroyed if we throw.  */
       push_base_cleanups ();
diff --git a/gcc/testsuite/g++.dg/opt/vt2.C b/gcc/testsuite/g++.dg/opt/vt2.C
new file mode 100644
index 0000000..a77db38
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/vt2.C
@@ -0,0 +1,24 @@ 
+// PR c++/34949
+// { dg-options "-O3" }
+// { dg-final { scan-assembler-not "mov\[^\n\]*_ZTV" { target i?86-*-* x86_64-*-* } } }
+
+class Foo
+{
+public:
+  virtual ~Foo();
+};
+
+Foo::~Foo()
+{
+}
+
+
+class Bar : public Foo
+{
+public:
+  virtual ~Bar();
+};
+
+Bar::~Bar()
+{
+}