This is the mail archive of the mailing list for the GCC project.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

c++/6830: Virtual table layout: wrong vcall/vbase order for primary base class

>Number:         6830
>Category:       c++
>Synopsis:       Virtual table layout: wrong vcall/vbase order for primary base class
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    unassigned
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon May 27 03:26:01 PDT 2002
>Originator:     Grigory Zagorodnev
>Release:        3.1
host: i686-pc-linux-gnu
build: i686-pc-linux-gnu
target: i686-pc-linux-gnu
configured with: ./configure
The C++ ABI syas that...

2.5 Virtual Table Layout 
2.5.2 Virtual Table Components and Order 
"However, in classes sharing a virtual table with a primary base class, the 
vcall and vbase offsets added by the derived class all come before the vcall 
and vbase offsets required by the base class, so that the latter may be laid 
out as required by the base class without regard to additions from the derived 
class(es). "

In the attached testcase, P is the primary base for S. So we are following 
quoted rule for vcall/vbase offsets order in it. Expected S's virtual table 
layout is the following (vptr is the virtual table entry point):
	vptr[-4] S's vbase offset
	vptr[-3] P's vcall offset
	vptr[-2] offset to top
	vptr[-1] typeinfo ptr

g++ compiler violates described rule by changing order of P's vcall and S's 
vbase offsets. It gives the following:
	vptr[-4] P's vcall offset
	vptr[-3] S's vbase offset

This happens both on ia-32 and ia-64.

PS: Hope there is enough information, use attached testcase to check the problem.
1. compile testcase 
    g++3 -c fail.cpp

2. Run to see the output

Actual Results:  
bad P's vcall offset
bad S's vbase offset

Expected Results:  

Content-Type: text/plain; name="fail.cpp"
Content-Disposition: inline; filename="fail.cpp"

#include <stdio.h>

struct P {
  virtual int g (void) = 0;

struct R {
  long long l;

struct S : virtual public R, public P {
  virtual int g (void) { return 1; }
  int i;

struct V : virtual public S {
  int f(void){ return 1; };
  int g (void) { return 1; }

V v;

#ifdef __ia64
#   define PAD_INT_TO_VOID 4
#   define PAD_INT_TO_VOID 0

int main (void)
    bool anyfail = false;
    // Get S's virtual table entry point
    size_t *vptr = *((size_t **)dynamic_cast<S*>(&v));

    // Expected S's virtual table layout is the following:
    // vptr[-1] typeinfo ptr
    // vptr[-2] offset to top
    // vptr[-3] P's vcall offset (note that P is the primary base for S)
    // vptr[-4] S's vbase offset
    if( vptr[-3] != -sizeof(void *) ) {
	anyfail = true;
	puts("bad P's vcall offset");

    if( vptr[-4] != sizeof(void *) + sizeof(int) + PAD_INT_TO_VOID){
	anyfail = true;
	puts("bad S's vbase offset");

    if( !anyfail )
    return anyfail;

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]