summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2015-04-27 17:19:49 +0000
committerReid Kleckner <reid@kleckner.net>2015-04-27 17:19:49 +0000
commit4cb2dbde5b08fa5b9a5868699f8d64c9b456f6c2 (patch)
tree6d7543563aef75af48abcacaafd1ded837d2fc3f
parentc205570127c9f35607e55e96c4a2fac4c2553e99 (diff)
downloadbcm5719-llvm-4cb2dbde5b08fa5b9a5868699f8d64c9b456f6c2.tar.gz
bcm5719-llvm-4cb2dbde5b08fa5b9a5868699f8d64c9b456f6c2.zip
[MS ABI] Use 'continue' instead of 'return false' where intended
This was a bug in r218285 that prevented us from seeing subsequent virtual bases in the class hierarchy, leading to crashes later. Also add some comments to this function, now that we better understand what it's trying to do. Fixes PR21062 and PR21064. llvm-svn: 235899
-rw-r--r--clang/lib/AST/VTableBuilder.cpp17
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp38
2 files changed, 51 insertions, 4 deletions
diff --git a/clang/lib/AST/VTableBuilder.cpp b/clang/lib/AST/VTableBuilder.cpp
index 9a768a9fd22..089520debff 100644
--- a/clang/lib/AST/VTableBuilder.cpp
+++ b/clang/lib/AST/VTableBuilder.cpp
@@ -3442,6 +3442,15 @@ MicrosoftVTableContext::~MicrosoftVTableContext() {
llvm::DeleteContainerSeconds(VBaseInfo);
}
+/// Find the full path of bases from the most derived class to the base class
+/// containing the vptr described by Info. Use depth-first search for this, but
+/// search non-virtual bases before virtual bases. This is important in cases
+/// like this where we need to find the path to a vbase that goes through an
+/// nvbase:
+/// struct A { virtual void f(); }
+/// struct B : virtual A { virtual void f(); };
+/// struct C : virtual A, B { virtual void f(); };
+/// The path to A's vftable in C should be 'C, B, A', not 'C, A'.
static bool
findPathForVPtr(ASTContext &Context, const ASTRecordLayout &MostDerivedLayout,
const CXXRecordDecl *RD, CharUnits Offset,
@@ -3454,9 +3463,9 @@ findPathForVPtr(ASTContext &Context, const ASTRecordLayout &MostDerivedLayout,
const ASTRecordLayout &Layout = Context.getASTRecordLayout(RD);
- // Recurse with non-virtual bases first.
- // FIXME: Does this need to be in layout order? Virtual bases will be in base
- // specifier order, which isn't necessarily layout order.
+ // Sort direct bases into non-virtual bases followed by virtual bases. This
+ // approximates layout order with the exception of classes that do not contain
+ // vptrs, and those don't affect our results.
SmallVector<CXXBaseSpecifier, 4> Bases(RD->bases_begin(), RD->bases_end());
std::stable_partition(Bases.begin(), Bases.end(),
[](CXXBaseSpecifier bs) { return !bs.isVirtual(); });
@@ -3468,7 +3477,7 @@ findPathForVPtr(ASTContext &Context, const ASTRecordLayout &MostDerivedLayout,
NewOffset = Offset + Layout.getBaseClassOffset(Base);
else {
if (!VBasesSeen.insert(Base).second)
- return false;
+ continue;
NewOffset = MostDerivedLayout.getVBaseClassOffset(Base);
}
FullPath.push_back(Base);
diff --git a/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp b/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
index 65d6a9d90e6..83f8114bae9 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-vtables-virtual-inheritance.cpp
@@ -807,3 +807,41 @@ C::C() {}
// MANGLING-DAG: @"\01??_7C@pr21031_2@@6BA@1@@" = {{.*}} constant [1 x i8*]
// MANGLING-DAG: @"\01??_7C@pr21031_2@@6BB@1@@" = {{.*}} constant [1 x i8*]
}
+
+namespace pr21062_1 {
+struct A { virtual void f(); };
+struct B {};
+struct C : virtual B {};
+struct D : virtual C, virtual B, virtual A { D();};
+D::D() {}
+
+// CHECK-LABEL: VFTable for 'pr21062_1::A' in 'pr21062_1::D' (1 entry)
+// CHECK-NEXT: 0 | void pr21062_1::A::f()
+
+// MANGLING-DAG: @"\01??_7D@pr21062_1@@6B@" = {{.*}} constant [1 x i8*]
+}
+
+namespace pr21062_2 {
+struct A { virtual void f(); };
+struct B {};
+struct C : virtual B {};
+struct D : C, virtual B, virtual A { D(); };
+D::D() {}
+
+// CHECK-LABEL: VFTable for 'pr21062_2::A' in 'pr21062_2::D' (1 entry)
+// CHECK-NEXT: 0 | void pr21062_2::A::f()
+
+// MANGLING-DAG: @"\01??_7D@pr21062_2@@6B@" = {{.*}} constant [1 x i8*]
+}
+
+namespace pr21064 {
+struct A {};
+struct B { virtual void f(); };
+struct C : virtual A, virtual B {};
+struct D : virtual A, virtual C { D(); };
+D::D() {}
+// CHECK-LABEL: VFTable for 'pr21064::B' in 'pr21064::C' in 'pr21064::D' (1 entry)
+// CHECK-NEXT: 0 | void pr21064::B::f()
+
+// MANGLING-DAG: @"\01??_7D@pr21064@@6B@" = {{.*}} constant [1 x i8*]
+}
OpenPOWER on IntegriCloud