Add one illustrative class hierarchy as an example in a comment to the VFTableBuilder code

llvm-svn: 221996
This commit is contained in:
Timur Iskhodzhanov 2014-11-14 14:10:15 +00:00
parent 9dec074399
commit 46a18efa5a
1 changed files with 58 additions and 0 deletions

View File

@ -2390,6 +2390,7 @@ namespace {
// first vfptr whose table provides a compatible overridden method. In many
// cases, this permits the original vf-table entry to directly call
// the method instead of passing through a thunk.
// See example before VFTableBuilder::ComputeThisOffset below.
//
// A compatible overridden method is one which does not have a non-trivial
// covariant-return adjustment.
@ -2412,6 +2413,9 @@ namespace {
// a) a user-defined ctor/dtor
// and
// b) a method overriding a method in a virtual base.
//
// To get a better understanding of this code,
// you might want to see examples in test/CodeGenCXX/microsoft-abi-vtables-*.cpp
class VFTableBuilder {
public:
@ -2642,6 +2646,60 @@ static bool BaseInSet(const CXXBaseSpecifier *Specifier,
return Bases->count(Specifier->getType()->getAsCXXRecordDecl());
}
// Let's study one class hierarchy as an example:
// struct A {
// virtual void f();
// int x;
// };
//
// struct B : virtual A {
// virtual void f();
// };
//
// Record layouts:
// struct A:
//   0 |   (A vftable pointer)
// 4 | int x
//
// struct B:
//   0 |   (B vbtable pointer)
//  4 |   struct A (virtual base)
//  4 |     (A vftable pointer)
// 8 | int x
//
// Let's assume we have a pointer to the A part of an object of dynamic type B:
// B b;
// A *a = (A*)&b;
// a->f();
//
// In this hierarchy, f() belongs to the vftable of A, so B::f() expects
// "this" parameter to point at the A subobject, which is B+4.
// In the B::f() prologue, it adjusts "this" back to B by subtracting 4,
// peformed as a *static* adjustment.
//
// Interesting thing happens when we alter the relative placement of A and B
// subobjects in a class:
// struct C : virtual B { };
//
// C c;
// A *a = (A*)&c;
// a->f();
//
// Respective record layout is:
// 0 | (C vbtable pointer)
// 4 | struct A (virtual base)
// 4 | (A vftable pointer)
// 8 | int x
// 12 | struct B (virtual base)
// 12 | (B vbtable pointer)
//
// The final overrider of f() in class C is still B::f(), so B+4 should be
// passed as "this" to that code. However, "a" points at B-8, so the respective
// vftable entry should hold a thunk that adds 12 to the "this" argument before
// performing a tail call to B::f().
//
// With this example in mind, we can now calculate the 'this' argument offset
// for the given method, relative to the beginning of the MostDerivedClass.
CharUnits
VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
InitialOverriddenDefinitionCollector Collector;