diff options
| author | Timur Iskhodzhanov <timurrrr@google.com> | 2014-04-17 22:01:48 +0000 |
|---|---|---|
| committer | Timur Iskhodzhanov <timurrrr@google.com> | 2014-04-17 22:01:48 +0000 |
| commit | ed11ae3d212db6875b889ad3d49d6866e685e730 (patch) | |
| tree | d5fd79cbf23fb788195e55bf62cc17199bd30e77 /clang/lib/AST | |
| parent | e80bfcd048068a5b4637927389846eca892540c3 (diff) | |
| download | bcm5719-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.cpp | 42 |
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. |

