The following simple testcase struct Foo { ~Foo() {} int i; }; struct NonPod { Foo foo[2]; }; void foo(void) { NonPod x; }
produces(!) at -O2 _Z3foov: .LFB5: pushl %ebp .LCFI0: movl %esp, %ebp .LCFI1: subl $16, %esp .LCFI2: leal -2(%ebp), %edx movl %ebp, %eax .p2align 4,,15 .L4: decl %eax cmpl %edx, %eax jne .L4 leave ret yay! Looking at the optimized tree-dump, it contains a funny loop: void foo() () { struct Foo * const this; register struct Foo * D.1621; struct Foo[2] * D.1620; struct NonPod x; <bb 0>: if (&x.foo[2] == &x.foo) goto <L6>; else goto <L14>; <L14>:; this = &x.foo[2]; <L2>:; this = this - 1; if (this == &x.foo) goto <L6>; else goto <L2>; <L6>:; return; } which is roughly what is generated initially by the C++ frontend for the dtor: ;; Function NonPod::~NonPod() (_ZN6NonPodD1Ev *INTERNAL* ) ;; enabled by -tree-original { <<< Unknown tree: if_stmt 1 >>> ; try { } finally { { register struct Foo * D.1599; (if (&((struct NonPod *) this)->foo != 0B) { (void) (D.1599 = &((struct NonPod *) this)->foo + 2); while (1) { if (&((struct NonPod *) this)->foo == D.1599) break; (void) (D.1599 = D.1599 - 1);; __comp_dtor (NON_LVALUE_EXPR <D.1599>);; }; } else { 0 }); } } } <D1598>:; Note the same happens for empty struct Foo, but even avoiding the ambiguous(?) &this->foo[2] - &this->foo[1] doesn't help. The RTL unroller, if enabled, gets rid of the most ugly stuff from above, but appearantly the tree loop optimizer does not know how to handle this loop. _Z3foov: .LFB5: pushl %ebp .LCFI0: movl %esp, %ebp .LCFI1: subl $16, %esp .LCFI2: movl %ebp, %esp popl %ebp ret -- Summary: Funny (horrible) code for empty destructor Product: gcc Version: 4.0.0 Status: UNCONFIRMED Severity: normal Priority: P2 Component: tree-optimization AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: rguenth at tat dot physik dot uni-tuebingen dot de CC: gcc-bugs at gcc dot gnu dot org http://gcc.gnu.org/bugzilla/show_bug.cgi?id=19639