summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST
diff options
context:
space:
mode:
authorTimur Iskhodzhanov <timurrrr@google.com>2014-04-17 22:01:48 +0000
committerTimur Iskhodzhanov <timurrrr@google.com>2014-04-17 22:01:48 +0000
commited11ae3d212db6875b889ad3d49d6866e685e730 (patch)
treed5fd79cbf23fb788195e55bf62cc17199bd30e77 /clang/lib/AST
parente80bfcd048068a5b4637927389846eca892540c3 (diff)
downloadbcm5719-llvm-ed11ae3d212db6875b889ad3d49d6866e685e730.tar.gz
bcm5719-llvm-ed11ae3d212db6875b889ad3d49d6866e685e730.zip
Follow-up to r206457 -- fix static adjustments for some subtle virtual inheritance cases
Reviewed at http://reviews.llvm.org/D3410 llvm-svn: 206504
Diffstat (limited to 'clang/lib/AST')
-rw-r--r--clang/lib/AST/VTableBuilder.cpp42
1 files changed, 15 insertions, 27 deletions
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp
index b2316e97b70..3e8dd470dfe 100644
--- a/clang/lib/AST/VTableBuilder.cpp
+++ b/clang/lib/AST/VTableBuilder.cpp
@@ -2649,6 +2649,8 @@ VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
CharUnits Ret;
bool First = true;
+ const ASTRecordLayout &OverriderRDLayout =
+ Context.getASTRecordLayout(Overrider.Method->getParent());
for (CXXBasePaths::paths_iterator I = Paths.begin(), E = Paths.end();
I != E; ++I) {
const CXXBasePath &Path = (*I);
@@ -2665,19 +2667,18 @@ VFTableBuilder::ComputeThisOffset(FinalOverriders::OverriderInfo Overrider) {
const ASTRecordLayout &Layout = Context.getASTRecordLayout(PrevRD);
if (Element.Base->isVirtual()) {
- LastVBaseOffset = MostDerivedClassLayout.getVBaseClassOffset(CurRD);
- if (Overrider.Method->getParent() == PrevRD) {
- // This one's interesting. If the final overrider is in a vbase B of the
- // most derived class and it overrides a method of the B's own vbase A,
- // it uses A* as "this". In its prologue, it can cast A* to B* with
- // a static offset. This offset is used regardless of the actual
- // offset of A from B in the most derived class, requiring an
- // this-adjusting thunk in the vftable if A and B are laid out
- // differently in the most derived class.
- ThisOffset += Layout.getVBaseClassOffset(CurRD);
- } else {
- ThisOffset = LastVBaseOffset;
- }
+ // The interesting things begin when you have virtual inheritance.
+ // The final overrider will use a static adjustment equal to the offset
+ // of the vbase in the final overrider class.
+ // For example, if the final overrider is in a vbase B of the most
+ // derived class and it overrides a method of the B's own vbase A,
+ // it uses A* as "this". In its prologue, it can cast A* to B* with
+ // a static offset. This offset is used regardless of the actual
+ // offset of A from B in the most derived class, requiring an
+ // this-adjusting thunk in the vftable if A and B are laid out
+ // differently in the most derived class.
+ LastVBaseOffset = ThisOffset =
+ Overrider.Offset + OverriderRDLayout.getVBaseClassOffset(CurRD);
} else {
ThisOffset += Layout.getBaseClassOffset(CurRD);
}
@@ -2739,21 +2740,8 @@ void VFTableBuilder::CalculateVtordispAdjustment(
// A simple vtordisp thunk will suffice if the final overrider is defined
// in either the most derived class or its non-virtual base.
- if (OverriderRD == MostDerivedClass)
- return;
-
- if (!OverriderVBase) {
- MethodVFTableLocation ML = VTables.getMethodVFTableLocation(Overrider.Method);
- assert(ML.VBase && "why would we need a vtordisp if we can call the method "
- "without a vfptr of a vbase?");
- // We need to offset the this parameter if the offset of the vbase is
- // different between the overrider class and the most derived class.
- const ASTRecordLayout &OverriderRDLayout =
- Context.getASTRecordLayout(OverriderRD);
- TA.NonVirtual += (OverriderRDLayout.getVBaseClassOffset(ML.VBase) +
- ML.VFPtrOffset - ThisOffset).getQuantity();
+ if (OverriderRD == MostDerivedClass || !OverriderVBase)
return;
- }
// Otherwise, we need to do use the dynamic offset of the final overrider
// in order to get "this" adjustment right.
OpenPOWER on IntegriCloud