Incorrect example in abi-examples

michaelw at ca.ibm.com michaelw at ca.ibm.com
Tue Aug 27 04:26:14 UTC 2002


The CXXABI example section
http://www.codesourcery.com/cxx-abi/abi-examples.html
contain an incorrect sample. On page 3:
/*
Test case for sharing virtual bases.
In Most_Derived, share the vptr with
Interface2 but not Interface3, since
Interface3 is indirectly inherited.

Should get:
(long)(Interface1 *)dd - (long)dd = 0
(long)(Interface2 *)dd - (long)dd = 0
(long)(Interface3 *)dd - (long)dd = 8
(long)(Concrete1 *)dd - (long)dd = 8
*/

struct Interface1 {
    virtual void foo();
};
struct Interface2 : virtual Interface1 {
        virtual void bar();
};
struct Interface3 : virtual Interface2 {
        virtual void baz();
};

struct Concrete1 : virtual Interface3 {
        virtual void foo();
        int i; // important.
};

struct Most_Derived : virtual Interface1,
                      virtual Interface2,
                      virtual Concrete1 {
        virtual void bar();
};

void Interface1::foo() { }
void Interface2::bar() { }
void Interface3::baz() { }
void Concrete1::foo() { }
void Most_Derived::bar() { }


extern "C" int printf(const char *,...);
#define EVAL(EXPR) printf( #EXPR " = %d\n", (EXPR) );
main()
{
  Most_Derived *dd = new Most_Derived;
  EVAL((long)(Interface1 *)dd - (long)dd);
  EVAL((long)(Interface2 *)dd - (long)dd);
  EVAL((long)(Interface3 *)dd - (long)dd);
  EVAL((long)(Concrete1 *)dd - (long)dd);
}

G++ 3.0.3 reveals the order is as follows:
Class Most_Derived
   size=12 align=4
Most_Derived (0x300a0200) 0 nearly-empty
    vptridx=0 vptr=((&Most_Derived::_ZTV12Most_Derived) + 28)
  Interface1 (0x300a0240) 0 nearly-empty virtual canonical
      primary-for Most_Derived (0x300a0200)
      vptridx=4 vbaseoffset=-16
  Interface2 (0x300a0280) 4 nearly-empty virtual non-canonical
      lost-primary
    Interface1 (0x300a02c0) 0 nearly-empty virtual non-canonical
  Concrete1 (0x300a0300) 4 virtual canonical
      subvttidx=28 vptridx=12 vbaseoffset=-24 vptr=((&Most_Derived::
_ZTV12Most_D
erived) + 68)
    Interface3 (0x300a0340) 4 nearly-empty virtual canonical
        primary-for Concrete1 (0x300a0300)
        subvttidx=44 vptridx=16 vbaseoffset=-28
      Interface2 (0x300a0380) 4 nearly-empty virtual canonical
          primary-for Interface3 (0x300a0340) lost-primary
          subvttidx=20 vptridx=8 vbaseoffset=-20
        Interface1 (0x300a03c0) 0 nearly-empty virtual non-canonical

G++ seems correct based on the following rule.

For a stand-alone class:
Primary(Interface2)=Interface1 by virtual nearly empty
Primary(Interface 3)=Interface2 by virtual nearly empty
Primary (Concrete1)=Interface3 by virtual nearly empty

Primary(Most_Derived)=Interface1 since it is the first virtual nearly empty
primary. Most_Derived cannot take Concrete1 since it is virtually inherited
and is not nearly empty.
So Interface2 loses its primary


Michael Wong
VisualAge C++ Compiler kernel Development
IBM Canada Ltd., C2/KD2/8200/MKM
8200 Warden Avenue
Markham, Ontario  L6G 1C7
W:905-413-3283 F:905-413-4839




More information about the cxx-abi-dev mailing list