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