This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
[Bug c++/11973] New: GCC 3.3 optimizer creates wrong code (i386/Linux)
- From: "yuri at tsoft dot com" <gcc-bugzilla at gcc dot gnu dot org>
- To: gcc-bugs at gcc dot gnu dot org
- Date: 18 Aug 2003 21:14:49 -0000
- Subject: [Bug c++/11973] New: GCC 3.3 optimizer creates wrong code (i386/Linux)
- Reply-to: gcc-bugzilla at gcc dot gnu dot org
PLEASE REPLY TO gcc-bugzilla@gcc.gnu.org ONLY, *NOT* gcc-bugs@gcc.gnu.org.
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=11973
Summary: GCC 3.3 optimizer creates wrong code (i386/Linux)
Product: gcc
Version: 3.3
Status: UNCONFIRMED
Severity: critical
Priority: P3
Component: c++
AssignedTo: unassigned at gcc dot gnu dot org
ReportedBy: yuri at tsoft dot com
CC: gcc-bugs at gcc dot gnu dot org,yuri at tsoft dot com
Symptom: Code (see below) crashes when compiled with -O3 and works
when compiled non-optimized
Expected: both optimized and nonoptimized should exit "main" OK.
Immediate reason in ASM: in inlined function alc() in E::X_alc()
freed = freed->next and first operation of constructor of C class
(vtbl initialization) are swapped by optimizer.
So it fills VTBL pointer into freed->next before it's value is being
placed into freed by alc(). So after the first call to alc()
freed is already wrong (has VTBL in it). And it should have "next"
value from the previous "freed" instance.
Please contact me yuri@tsoft.com if explanation isn't clear.
This bug prevents us from switching to 3.3.
Thanx,
Yuri
----Version from "gcc -v"------------------------
Reading specs from /usr/gcc-3.3/bin/../lib/gcc-lib/i686-pc-linux-gnu/3.3/specs
Configured with: ./configure --prefix=/gjt/home/yuri/gcc
--exec-prefix=/gjt/home/yuri/gcc
Thread model: posix
gcc version 3.3
---end Version------------------------------------
---code-------------------------------------------
#include <stdio.h>
struct SList {
SList *next;
int i;
};
SList sl1, sl2;
SList *freed;
inline void *alc() {
void *r = freed;
// !!! HERE IS WHERE BUG IS IMPLANTED
freed = freed->next;
return (r);
}
class P {
public:
virtual int fn1() { return (1); }
virtual int fn2() { return (2); }
};
class C : public P {
public:
virtual int fn1() { return (3); }
virtual int fn2() { return (4); }
int i;
inline void * operator new(size_t sz) { return alc(); }
inline void operator delete(void *) { }
};
class D {
public:
virtual C* X_alc() { return (NULL); }
};
class E {
public:
virtual C* X_alc() { return (new C()); };
};
int
main(int argc[], const char *argv[]) {
C *c1, *c2;
E *a = new E;
// initialize
sl1.next = &sl2;
sl2.next = NULL;
freed = &sl1;
printf(" ** freed=%p **\n", freed);
printf(" ** alloc: %p **\n", (c1 = a->X_alc()));
printf(" ** freed=%p **\n", freed);
printf(" ** alloc: %p **\n", (c2 = a->X_alc()));
printf(" ** freed=%p **\n", freed);
delete c1;
delete c2;
return (0);
}
---end code---------------------------------------
---asm------(E::X_alc where alc() is inlined)-----
080485e0 <_ZN1E5X_alcEv>:
80485e0: 55 push %ebp
80485e1: a1 d8 98 04 08 mov 0x80498d8,%eax
80485e6: 89 e5 mov %esp,%ebp
80485e8: c7 00 c8 86 04 08 movl $0x80486c8,(%eax)
80485ee: 8b 08 mov (%eax),%ecx
80485f0: 5d pop %ebp
80485f1: 89 0d d8 98 04 08 mov %ecx,0x80498d8
80485f7: c3 ret
80485f8: 90 nop
80485f9: 8d b4 26 00 00 00 00 lea 0x0(%esi,1),%esi
---end asm----------------------------------------