[cfe-dev] Cannot access the offset of a virtual base class in a given case

Xiaolong Tang xiaolong.snake at gmail.com
Mon Aug 22 09:06:31 PDT 2011


Thanks David,

> >
> > Hi Everyone,
> >
> > I have a question about the layout of a C++ record.
> >
> > Given the following class hierarchy:
> >
> > // A virtual class
> > class Foo {
> > public:
> >  virtual void f() {};
> > };
> >
> > // A virtual class
> > class Bar {
> > public:
> >  virtual void g() {};
> > };
> >
> > // Two virtual bases
> > class Zoo : virtual public Foo, virtual public Bar {
> > public:
> >  int x;
> >  int y;
> >  virtual void g() { x = x + y; };
> >  virtual void f() { x = x - y; };
> > };
> >
> >
> > Following is the code I use to access the offset of the virtual bases of a
> > class:
> >
> >    // Suppose that "Record" denotes a RecordDecl
> >
> >    // The layout code generation for the backend, e.g., LLVM IR
> >    const CGRecordLayout &Layout = CGM.getTypes().getCGRecordLayout(Record);
> >    // In C++ mode
> >    const CXXRecordDecl *CXXRecord = cast<CXXRecordDecl>(Record);
> >
> >    // Virtual bases
> >    for (CXXRecordDecl::base_class_const_iterator I = CXXRecord->vbases_begin(),
> >         E = CXXRecord->vbases_end(); I != E; ++I) {
> >      // The type of a virtual base
> >      const RecordType *BaseTy = I->getType()->getAs<RecordType>();
> >      // The decl of the virtual base
> >      const CXXRecordDecl *BaseDecl = dyn_cast<CXXRecordDecl>(BaseTy->getDecl());
> >      // Accessing the index of the base
> >      unsigned fieldNo  = Layout.getVirtualBaseIndex(BaseDecl);
> >    }
> >
> > Fed with the given class hierarchy, the last statement of the above
> > code, i.e., "getVirtualBaseIndex(BaseDecl)", causes an assertion
> > failure.
> >
> >  Assertion failed: (CompleteObjectVirtualBases.count(base) && "Invalid virtual base!"), ...
> >
> > The failure means that the virtual base "Foo" is not in the
> > layout mapping from the virtual bases of the class "Zoo" to their
> > offsets. So, can someone point out any hints about this missing?
> >
> > P.S. When the class "Foo" contains one data member, the above
> > issue goes away.
> 
> My stab in the dark would be that this sounds rather like the Empty
> Base Class optimization at work (
> http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=319 ).
> If Foo has no members then there's no reason to ever access it so its
> offset doesn't need to be computable (because it doesn't actually
> exist).

In my case, "Foo" is a polymophic class, having a size greater than
zero. Moreover, "Foo" is a virtual base of "Zoo". Consider the
statements:
  Zoo zoo;
  Foo *foo = &zoo;
  foo->f();
I guess, to ensure the correctness of "foo->f()", the "Foo" subobject
in a "Zoo" object must be present. My guess seems to agree with the
LLVM IR type system for the given class hierarchy: 

%class.Foo = type { i32 (...)** }
%class.Bar = type { i32 (...)** }
%class.Zoo = type { [8 x i8], i32, i32, [8 x i8] }

There are two virtual tables, respectively, for the two virtual bases
of the class "Zoo". %class.Bar is identified as the primary base class
of Zoo in this case, and has the offset 0.  %class.Foo has a non-zero
offset.

I am, however, not sure if this is an empty-based optimization
issue. If it is, what predicates can I use to check the specialty of
such a base class "Foo"?

> No doubt someone with more actual clang knowledge can
confirm/provide
> more detail, but perhaps this'll help put you in the right direction
> until then.
> 

Xiaolong




More information about the cfe-dev mailing list