Hi!

This is a follow-up to the PR70259 that got fixed yesterday.
As the testcase shows, clobbers for empty classes are harmful not just in
the ctors, but also in the dtors, where they can result in stores being
removed before the corresponding dtor has acted upon them.

The ehcleanup1.C part of the patch just reverts the PR34949 adjustment
of the testcase following to addition of clobbers in dtors - it doesn't
actually make the generated code any worse.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk
and 5.x after a while?

2016-03-17  Jakub Jelinek  <ja...@redhat.com>

        PR c++/70272
        * decl.c (begin_destructor_body): Don't insert clobber if
        is_empty_class (current_class_type).

        * g++.dg/opt/flifetime-dse5.C (main): Remove extra semicolon.
        * g++.dg/opt/flifetime-dse6.C: New test.
        * g++.dg/tree-ssa/ehcleanup-1.C: Adjust unreachable count.

--- gcc/cp/decl.c.jj    2016-03-17 00:12:07.000000000 +0100
+++ gcc/cp/decl.c       2016-03-17 11:11:04.816068299 +0100
@@ -14354,7 +14354,9 @@ begin_destructor_body (void)
       initialize_vtbl_ptrs (current_class_ptr);
       finish_compound_stmt (compound_stmt);
 
-      if (flag_lifetime_dse)
+      if (flag_lifetime_dse
+         /* Clobbering an empty base is harmful if it overlays real data.  */
+         && !is_empty_class (current_class_type))
        {
          /* Insert a cleanup to let the back end know that the object is dead
             when we exit the destructor, either normally or via exception.  */
--- gcc/testsuite/g++.dg/opt/flifetime-dse5.C.jj        2016-03-17 
00:12:06.000000000 +0100
+++ gcc/testsuite/g++.dg/opt/flifetime-dse5.C   2016-03-17 11:11:28.948734056 
+0100
@@ -10,4 +10,4 @@ int main() {
   C c;
   if ( c.a == false )
     __builtin_abort();
-};
+}
--- gcc/testsuite/g++.dg/opt/flifetime-dse6.C.jj        2016-03-17 
11:14:41.344069338 +0100
+++ gcc/testsuite/g++.dg/opt/flifetime-dse6.C   2016-03-17 11:14:32.000000000 
+0100
@@ -0,0 +1,11 @@
+// PR c++/70272
+// { dg-options -O2 }
+// { dg-do run }
+
+struct Empty { };
+struct A { A() : a(true) { } bool a; ~A() { if (!a) __builtin_abort(); } };
+struct B : Empty { B() : Empty() { } ~B() { } };
+struct C : A, B { C() : A(), B() { } ~C() { } };
+int main() {
+  C c;
+}
--- gcc/testsuite/g++.dg/tree-ssa/ehcleanup-1.C.jj      2015-05-29 
15:04:33.000000000 +0200
+++ gcc/testsuite/g++.dg/tree-ssa/ehcleanup-1.C 2016-03-17 15:01:01.267373561 
+0100
@@ -26,5 +26,5 @@ t (void)
 // { dg-final { scan-tree-dump-times "Empty EH handler" 2 "ehcleanup1" } }
 //
 // And as a result also contained control flow.
-// { dg-final { scan-tree-dump-times "Removing unreachable" 6 "ehcleanup1" } }
+// { dg-final { scan-tree-dump-times "Removing unreachable" 4 "ehcleanup1" } }
 //


        Jakub

Reply via email to