From: vaughan@CAD.MCC.COM (Paul Vaughan)
Subject: MI/virtual base class bug
Organization: GNUs Not Usenet
Distribution: gnu
Date: Tue, 7 Apr 1992 20:58:23 GMT

The following program produces incorrect output when compiled with

SUN4, g++ 2.1 latest patches
DecStation 3100 g++ 2.1 only one patch (by Tiemann)
SUN4 cfront 2.1 from ObjectCenter

but produces correct output when compiled with

SUN4 g++ 1.37.2

The symptom for g++ 2.1 is that when calling a function declared on a
virtual base class and redefined on the second base of a multiply
inherited class, the incorrect offset is applied, so that the this
object points into the wrong part of the object as the method
executes.

Cfront does the same thing, but only when the virtual function is
called using a pointer to the virtual base class.

----------------------------------------------------------------
#include <stream.h>

class Entity {
public: 
  Entity() { cout << (int) this << " Entity::Entity()\n"; };
  virtual ~Entity() { cout << (int) this << "~Entity::Entity()\n"; }
  virtual void Name() { cout << (int) this << " Entity::Name()\n"; };
};

class A : virtual public Entity {
public:
  A() { cout << (int) this << " A::A()\n"; };
  ~A() {cout << (int) this << "~A::A()\n";}
  void Name() { cout << (int) this << " A::Name()\n"; }
};

class At : public A {
public:
  At() { cout << (int) this << " At::At()\n"; }
  ~At() { cout << (int) this << "~At::At()\n"; }
};

class B : virtual public Entity {
public:
  B() { cout << (int) this << " B::B()\n"; }
  ~B() { cout << (int) this << "~B::B()\n"; }
};

class Bt : public B {
public:
  Bt() { cout << (int) this << " Bt::Bt()\n";  }
  ~Bt() { cout << (int) this << "~Bt::Bt()\n";}
};

class BtAt : public Bt, public At {
public:
  BtAt() { cout << (int) this << " BtAt::BtAt()\n"; }
  ~BtAt() {cout << (int) this << "~BtAt::BtAt()\n";}
};

class BtAtderived : public BtAt {
public:
  BtAtderived() { cout << (int) this << " BtAtderived::BtAtderived()\n"; }
  ~BtAtderived() {cout << (int) this << "~BtAtderived::BtAtderived()\n";}
};



main() {
  BtAtderived* btatderived = new BtAtderived;
  cout << "\n";
  cout << "btatderived->Name()\n";
  btatderived->Name();
  cout << "\n\n";
  cout << "((Entity*) btatderived)->Name()\n";
  ((Entity*) btatderived)->Name();
  cout << "\n\n";
  delete btatderived;
}

----------------------------------------------------------------

Here is the incorrect output generated when compiled with g++ 2.1,
both patched and unpatched. I've annotated the output with comments to
point out the pertinent lines.

[3.89]suntrek) atbug
36624 Entity::Entity()
36616 B::B()
36616 Bt::Bt()
36620 A::A()                               // address for A object
36620 At::At()
36616 BtAt::BtAt()
36616 BtAtderived::BtAtderived()

btatderived->Name()
36616 A::Name()                            // does not match address for A object WRONG


((Entity*) btatderived)->Name()
36616 A::Name()                            // does not match address for A object WRONG


36616~BtAtderived::BtAtderived()
36616~BtAt::BtAt()
36620~At::At()
36620~A::A()
36616~Bt::Bt()
36616~B::B()
36624~Entity::Entity()

Here is the incorrect output generated when compiled by cfront 2.1
(from ObjectCenter).


27812 Entity::Entity()
27792 B::B()
27792 Bt::Bt()
27800 A::A()
27800 At::At()
27792 BtAt::BtAt()
27792 BtAtderived::BtAtderived()

btatderived->Name()
27800 A::Name()                            // fine when called from a BtAtderived*


((Entity*) btatderived)->Name()
27792 A::Name()                            // fails when called from an Entity* WRONG


27792~BtAtderived::BtAtderived()
27792~BtAt::BtAt()
27800~At::At()
27800~A::A()
27792~Bt::Bt()
27792~B::B()
27812~Entity::Entity()



Here is the correct output generated by g++-1.37.2

[2.115]sunspot) !a
atbug
140048 Entity::Entity()
140040 B::B()
140040 Bt::Bt()
140044 A::A()
140044 At::At()
140040 BtAt::BtAt()
140040 BtAtderived::BtAtderived()

btatderived->Name()
140044 A::Name()                                // matches address for A object


((Entity*) btatderived)->Name()
140044 A::Name()                                // matches address for A object


140040~BtAtderived::BtAtderived()
140040~BtAt::BtAt()
140044~At::At()
140044~A::A()
140040~Bt::Bt()
140040~B::B()
140048~Entity::Entity()

Paul Vaughan

Newsgroups: gnu.g++.bug