aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/decl.c8
-rw-r--r--gcc/testsuite/g++.dg/opt/vt2.C24
3 files changed, 37 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7b73e03..1b847a9 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,8 @@
+2013-04-02 Jason Merrill <jason@redhat.com>
+
+ PR c++/34949
+ * decl.c (begin_destructor_body): Clobber the object in a cleanup.
+
2013-04-02 Paolo Carlini <paolo.carlini@oracle.com>
* friend.c (do_friend): Use COMPLETE_OR_OPEN_TYPE_P.
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()
+{
+}