diff options
author | Timur Iskhodzhanov <timurrrr@google.com> | 2014-11-14 14:10:15 +0000 |
---|---|---|
committer | Timur Iskhodzhanov <timurrrr@google.com> | 2014-11-14 14:10:15 +0000 |
commit | 46a18efa5af730b72721f9f24d94f6251f927855 (patch) | |
tree | 17f3970ad74cd4d44462839be8f9524b89e2b232 /clang/lib/AST/VTableBuilder.cpp | |
parent | 9dec07439902f89c0c40a81ecc12da5acd64394a (diff) | |
download | bcm5719-llvm-46a18efa5af730b72721f9f24d94f6251f927855.tar.gz bcm5719-llvm-46a18efa5af730b72721f9f24d94f6251f927855.zip |
Add one illustrative class hierarchy as an example in a comment to the VFTableBuilder code
llvm-svn: 221996
Diffstat (limited to 'clang/lib/AST/VTableBuilder.cpp')
-rw-r--r-- | clang/lib/AST/VTableBuilder.cpp | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp index 43a0fb7d755..14a174ede6e 100644 --- a/clang/lib/AST/VTableBuilder.cpp +++ b/clang/lib/AST/VTableBuilder.cpp @@ -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; |