diff options
-rw-r--r-- | clang/lib/AST/VTableBuilder.cpp | 26 | ||||
-rw-r--r-- | clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp | 17 |
2 files changed, 38 insertions, 5 deletions
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp index 3e7871e7bd7..a95791ce884 100644 --- a/clang/lib/AST/VTableBuilder.cpp +++ b/clang/lib/AST/VTableBuilder.cpp @@ -3544,6 +3544,19 @@ static void computeFullPathsForVFTables(ASTContext &Context, } } +static bool +vfptrIsEarlierInMDC(const ASTRecordLayout &Layout, + const MicrosoftVTableContext::MethodVFTableLocation &LHS, + const MicrosoftVTableContext::MethodVFTableLocation &RHS) { + CharUnits L = LHS.VFPtrOffset; + CharUnits R = RHS.VFPtrOffset; + if (LHS.VBase) + L += Layout.getVBaseClassOffset(LHS.VBase); + if (RHS.VBase) + R += Layout.getVBaseClassOffset(RHS.VBase); + return L < R; +} + void MicrosoftVTableContext::computeVTableRelatedInformation( const CXXRecordDecl *RD) { assert(RD->isDynamicClass()); @@ -3574,12 +3587,15 @@ void MicrosoftVTableContext::computeVTableRelatedInformation( EmptyAddressPointsMap); Thunks.insert(Builder.thunks_begin(), Builder.thunks_end()); + const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD); for (const auto &Loc : Builder.vtable_locations()) { - GlobalDecl GD = Loc.first; - MethodVFTableLocation NewLoc = Loc.second; - auto M = NewMethodLocations.find(GD); - if (M == NewMethodLocations.end() || NewLoc < M->second) - NewMethodLocations[GD] = NewLoc; + auto Insert = NewMethodLocations.insert(Loc); + if (!Insert.second) { + const MethodVFTableLocation &NewLoc = Loc.second; + MethodVFTableLocation &OldLoc = Insert.first->second; + if (vfptrIsEarlierInMDC(Layout, NewLoc, OldLoc)) + OldLoc = NewLoc; + } } } diff --git a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp index b34f20d3390..212c8dc84ae 100644 --- a/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp +++ b/clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp @@ -538,3 +538,20 @@ D::D() : C() {} // CHECK: %[[FIELD:.*]] = getelementptr inbounds i8, i8* %[[C_i8]], i32 8 // CHECK: call void @llvm.memset.p0i8.i32(i8* align 4 %[[FIELD]], i8 0, i32 4, i1 false) } + +namespace pr36921 { +struct A { + virtual ~A() {} +}; +struct B { + virtual ~B() {} +}; +struct C : virtual B {}; +struct D : virtual A, C {}; +D d; +// CHECK-LABEL: define linkonce_odr dso_local x86_thiscallcc i8* @"??_GD@pr36921@@UAEPAXI@Z"( +// CHECK: %[[THIS:.*]] = load %"struct.pr36921::D"*, %"struct.pr36921::D"** +// CHECK: %[[THIS_UNADJ_i8:.*]] = bitcast %"struct.pr36921::D"* %[[THIS_RELOAD]] to i8* +// CHECK: %[[THIS_ADJ_i8:.*]] = getelementptr inbounds i8, i8* %[[THIS_UNADJ_i8]], i32 -4 +// CHECK: %[[THIS:.*]] = bitcast i8* %[[THIS_ADJ_i8]] to %"struct.pr36921::D"* +} |