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