This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
c++ code that egcs kills ...
- To: egcs-bugs at cygnus dot com
- Subject: c++ code that egcs kills ...
- From: "Glenn W. Bach" <glenn at dodgson dot wonderland dot caltech dot edu>
- Date: Thu, 20 Aug 1998 10:44:11 -0700
The following code demonstrates a bug in how egcs handles c++.
Has this been seen before? Is there hope of fixing it in a future version?
We are stuck, because RedHat Linux uses egcs, so we can't get any of our
code to work.
-----------
The following code demonstrates a bug in egcs 1.0.3.
B
/ \
A D - E
\ /
C
In the above inheritance tree, B and C inherit virtually from A. When an
object of type E is constructed, D's constructor calls a function in A
which in turn calls a virtual function overridden by D. This requires a
downcast from type A to type D, and egcs incorrectly adjusts the object
pointer, forgetting the size of E's member data.
The correct output, produced by g++ 2.7.2, is:
starting test
A::foo 0xbffffb30
B::foo 0xbffffb18
C::foo 0xbffffb20
D::foo 0xbffffb18
E::foo 0xbffffb18
object constructed
E::foo 0xbffffb18
test finished
egcs 1.0.3 produces the incorrect output indicated below:
starting test
A::foo 0xbffffb40
B::foo 0xbffffb38
C::foo 0xbffffb38
D::foo 0xbffffb2c <------ incorrect
E::foo 0xbffffb28
object constructed
E::foo 0xbffffb28
test finished
The minimal source code required to reproduce the problem is listed below.
Changing the size of E's member data changes the difference between the
output of D::foo() and E::foo() by exactly the same amount.
Also note that B::foo() and C::foo() should probably not be printing the same result. (They don't with g++ 2.7.2.)
#include <iostream.h>
class A
{
public:
A() { bar(); };
virtual void foo() { cout << "A::foo " << this << endl; };
void bar() { foo(); };
private:
int a;
};
class B : virtual public A
{
public:
B() { bar(); };
virtual void foo() { cout << "B::foo " << this << endl; };
private:
int b;
};
class C : virtual public A
{
public:
C() { bar(); };
virtual void foo() { cout << "C::foo " << this << endl; };
private:
int c;
};
class D : public B, public C
{
public:
D() { bar(); };
virtual void foo() { cout << "D::foo " << this << endl; };
private:
int d;
};
class E : public D
{
public:
E() { bar(); };
virtual void foo() { cout << "E::foo " << this << endl; };
private:
int e;
};
int
main()
{
cout << "starting test" << endl;
E e;
cout << "object constructed" << endl;
e.bar();
cout << "test finished" << endl;
return 0;
}