summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2018-03-28 18:23:35 +0000
committerReid Kleckner <rnk@google.com>2018-03-28 18:23:35 +0000
commiteed882022f6e997942d3e4f0bc07d4dadc3cbd57 (patch)
tree1582ab1f2103fd72ce245afff260470f62d137bc
parent10f50a44c1fa25463b0cb819f424abfbca336c9e (diff)
downloadbcm5719-llvm-eed882022f6e997942d3e4f0bc07d4dadc3cbd57.tar.gz
bcm5719-llvm-eed882022f6e997942d3e4f0bc07d4dadc3cbd57.zip
[MS] Fix bug in method vfptr location code
We were assuming that vbtable indices were assigned in layout order in our comparison, which is not the case. When a virtual method, such as the destructor, appears in multiple vftables, the vftable that appears first in object layout order is the one that points to the main implementation of that method. The later vftables use thunks. In this layout, we adjusted "this" in the main implementation by the amount that is appropriate for 'B' instead of 'A', even though the main implementation is found in D's vftable for A: struct A { virtual ~A() {} }; struct B { virtual ~B() {} }; struct C : virtual B {}; struct D : virtual A, C {}; D's layout looks like: 0 D subobject (empty) 0 C base suboject 8 A base subobject 16 B base subobject With this fix, we correctly adjust by -8 in D's deleting destructor instead of -16. Fixes PR36921. llvm-svn: 328723
-rw-r--r--clang/lib/AST/VTableBuilder.cpp26
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-virtual-inheritance.cpp17
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"*
+}
OpenPOWER on IntegriCloud