summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2014-06-12 19:49:17 +0000
committerReid Kleckner <reid@kleckner.net>2014-06-12 19:49:17 +0000
commita766029b81937aafb0ee7e83a6252e51eb1f9c34 (patch)
tree157961163b84ddb472cd8e8e693d0c38071007a7
parentfbfbaf6a931918f7a648758b0a709d52b30ed71b (diff)
downloadbcm5719-llvm-a766029b81937aafb0ee7e83a6252e51eb1f9c34.tar.gz
bcm5719-llvm-a766029b81937aafb0ee7e83a6252e51eb1f9c34.zip
MS ABI: Fix forming pointers to members of a base class
Previously we would calculate the inheritance model of a class when requiring a pointer to member type of that class to be complete. The inheritance model is used to figure out how many fields are used by the member pointer. However, once we require a pointer to member of a derived class type to be complete, we can form pointers to members of bases without calculating the inheritance model for those bases. This was causing crashes on this simple test case: struct A { void f(); void f(int); }; struct B : public A {}; void g() { void (B::*a)() = &B::f; } Now we calculate the inheritance models of all base classes when completing a member pointer type. Fixes PR2007. llvm-svn: 210813
-rw-r--r--clang/lib/Sema/SemaType.cpp70
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp27
2 files changed, 65 insertions, 32 deletions
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index 57eae9a7fa1..f7042927e49 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -5147,6 +5147,45 @@ static bool hasVisibleDefinition(Sema &S, NamedDecl *D, NamedDecl **Suggested) {
return LookupResult::isVisible(S, D);
}
+/// Locks in the inheritance model for the given class and all of its bases.
+static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) {
+ RD = RD->getMostRecentDecl();
+ if (!RD->hasAttr<MSInheritanceAttr>()) {
+ MSInheritanceAttr::Spelling IM;
+
+ switch (S.MSPointerToMemberRepresentationMethod) {
+ case LangOptions::PPTMK_BestCase:
+ IM = RD->calculateInheritanceModel();
+ break;
+ case LangOptions::PPTMK_FullGeneralitySingleInheritance:
+ IM = MSInheritanceAttr::Keyword_single_inheritance;
+ break;
+ case LangOptions::PPTMK_FullGeneralityMultipleInheritance:
+ IM = MSInheritanceAttr::Keyword_multiple_inheritance;
+ break;
+ case LangOptions::PPTMK_FullGeneralityVirtualInheritance:
+ IM = MSInheritanceAttr::Keyword_unspecified_inheritance;
+ break;
+ }
+
+ RD->addAttr(MSInheritanceAttr::CreateImplicit(
+ S.getASTContext(), IM,
+ /*BestCase=*/S.MSPointerToMemberRepresentationMethod ==
+ LangOptions::PPTMK_BestCase,
+ S.ImplicitMSInheritanceAttrLoc.isValid()
+ ? S.ImplicitMSInheritanceAttrLoc
+ : RD->getSourceRange()));
+ }
+
+ if (RD->hasDefinition()) {
+ // Assign inheritance models to all of the base classes, because now we can
+ // form pointers to members of base classes without calling
+ // RequireCompleteType on the pointer to member of the base class type.
+ for (const CXXBaseSpecifier &BS : RD->bases())
+ assignInheritanceModel(S, BS.getType()->getAsCXXRecordDecl());
+ }
+}
+
/// \brief The implementation of RequireCompleteType
bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
TypeDiagnoser &Diagnoser) {
@@ -5185,36 +5224,7 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
if (!MPTy->getClass()->isDependentType()) {
RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), 0);
-
- CXXRecordDecl *RD = MPTy->getMostRecentCXXRecordDecl();
- if (!RD->hasAttr<MSInheritanceAttr>()) {
- MSInheritanceAttr::Spelling InheritanceModel;
-
- switch (MSPointerToMemberRepresentationMethod) {
- case LangOptions::PPTMK_BestCase:
- InheritanceModel = RD->calculateInheritanceModel();
- break;
- case LangOptions::PPTMK_FullGeneralitySingleInheritance:
- InheritanceModel = MSInheritanceAttr::Keyword_single_inheritance;
- break;
- case LangOptions::PPTMK_FullGeneralityMultipleInheritance:
- InheritanceModel =
- MSInheritanceAttr::Keyword_multiple_inheritance;
- break;
- case LangOptions::PPTMK_FullGeneralityVirtualInheritance:
- InheritanceModel =
- MSInheritanceAttr::Keyword_unspecified_inheritance;
- break;
- }
-
- RD->addAttr(MSInheritanceAttr::CreateImplicit(
- getASTContext(), InheritanceModel,
- /*BestCase=*/MSPointerToMemberRepresentationMethod ==
- LangOptions::PPTMK_BestCase,
- ImplicitMSInheritanceAttrLoc.isValid()
- ? ImplicitMSInheritanceAttrLoc
- : RD->getSourceRange()));
- }
+ assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl());
}
}
}
diff --git a/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
index 4ce8a02dcb0..2570754fba3 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 | FileCheck %s
-// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 | FileCheck %s -check-prefix=X64
+// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -fms-extensions | FileCheck %s
+// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=x86_64-pc-win32 -fms-extensions | FileCheck %s -check-prefix=X64
// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -fms-extensions -verify
// RUN: %clang_cc1 -fno-rtti -emit-llvm %s -o - -triple=i386-pc-win32 -DINCOMPLETE_VIRTUAL -DMEMFUN -fms-extensions -verify
// FIXME: Test x86_64 member pointers when codegen no longer asserts on records
@@ -607,6 +607,29 @@ void (C::*getmp())() {
}
+namespace pr2007 {
+struct A {
+ void f();
+ void f(int);
+};
+struct B : public A {};
+void test() { void (B::*a)() = &B::f; }
+// CHECK-LABEL: define void @"\01?test@pr2007@@YAXXZ"
+// CHECK: store i8* bitcast (void (%"struct.pr2007::A"*)* @"\01?f@A@pr2007@@QAEXXZ" to i8*)
+}
+
+namespace pr2007_kw {
+struct A {
+ void f();
+ void f(int);
+};
+struct __single_inheritance B;
+struct B : public A {};
+void test() { void (B::*a)() = &B::f; }
+// CHECK-LABEL: define void @"\01?test@pr2007_kw@@YAXXZ"
+// CHECK: store i8* bitcast (void (%"struct.pr2007_kw::A"*)* @"\01?f@A@pr2007_kw@@QAEXXZ" to i8*)
+}
+
#else
struct __virtual_inheritance A;
#ifdef MEMFUN
OpenPOWER on IntegriCloud