summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Majnemer <david.majnemer@gmail.com>2014-08-08 00:10:39 +0000
committerDavid Majnemer <david.majnemer@gmail.com>2014-08-08 00:10:39 +0000
commitd96b99740d1f2c47941e589d9719016388ee6453 (patch)
tree1948bfebd62c54547ae481c4ad1b81b622126bcc
parent7d498629f1e038d2642116b40a04f4acf6532a26 (diff)
downloadbcm5719-llvm-d96b99740d1f2c47941e589d9719016388ee6453.tar.gz
bcm5719-llvm-d96b99740d1f2c47941e589d9719016388ee6453.zip
MS ABI: Don't force bases to have an inheritance model
Previously, assigning an inheritance model to a derived class would trigger further assiginments to the various bases of the class. This was done to fix a bug where we couldn't handle an implicit base-to-derived conversion for pointers-to-members when the conversion was ambiguous at an earlier point. However, this is not how the MS scheme works. Instead, assign inheritance models to *just* the class which owns to declaration we ended up referencing. N.B. This result is surprising in many ways. It means that it is possible for a base to have a "larger" inheritance model than it's derived classes. It also means that bases in the conversion path do not get assigned a model. struct A { void f(); void f(int); }; struct B : A {}; struct C : B {}; void f() { void (C::*x)() = &A::f; } We can only begin to assign an inheritance model *after* we've seen the address-of but *before* we've done the implicit conversion the more derived pointer-to-member type. After that point, both 'A' and 'C' will have an inheritance model but 'B' will not. Surprising, right? llvm-svn: 215174
-rw-r--r--clang/lib/Sema/SemaExprCXX.cpp8
-rw-r--r--clang/lib/Sema/SemaType.cpp8
-rw-r--r--clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp28
3 files changed, 36 insertions, 8 deletions
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index eb7924f473a..49d1fdfb3f2 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -2898,6 +2898,14 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
return ExprError();
if (CheckExceptionSpecCompatibility(From, ToType))
return ExprError();
+
+ // We may not have been able to figure out what this member pointer resolved
+ // to up until this exact point. Attempt to lock-in it's inheritance model.
+ QualType FromType = From->getType();
+ if (FromType->isMemberPointerType())
+ if (Context.getTargetInfo().getCXXABI().isMicrosoft())
+ RequireCompleteType(From->getExprLoc(), FromType, 0);
+
From = ImpCastExprToType(From, ToType, Kind, VK_RValue, &BasePath, CCK)
.get();
break;
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index b6b024c89ab..029d2c2806c 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -5163,14 +5163,6 @@ static void assignInheritanceModel(Sema &S, CXXRecordDecl *RD) {
? 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
diff --git a/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
index 18e8c827eeb..80d92de3ec3 100644
--- a/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
+++ b/clang/test/CodeGenCXX/microsoft-abi-member-pointers.cpp
@@ -630,6 +630,34 @@ void test() { void (B::*a)() = &B::f; }
// CHECK: store i8* bitcast (void (%"struct.pr20007_kw::A"*)* @"\01?f@A@pr20007_kw@@QAEXXZ" to i8*)
}
+namespace pr20007_pragma {
+struct A {
+ void f();
+ void f(int);
+};
+struct B : public A {};
+void test() { (void)(void (B::*)()) &B::f; }
+#pragma pointers_to_members(full_generality, virtual_inheritance)
+static_assert(sizeof(int B::*) == 4, "");
+static_assert(sizeof(int A::*) == 4, "");
+#pragma pointers_to_members(best_case)
+// CHECK-LABEL: define void @"\01?test@pr20007_pragma@@YAXXZ"
+}
+
+namespace pr20007_pragma2 {
+struct A {
+};
+struct B : public A {
+ void f();
+};
+void test() { (void)&B::f; }
+#pragma pointers_to_members(full_generality, virtual_inheritance)
+static_assert(sizeof(int B::*) == 4, "");
+static_assert(sizeof(int A::*) == 12, "");
+#pragma pointers_to_members(best_case)
+// CHECK-LABEL: define void @"\01?test@pr20007_pragma2@@YAXXZ"
+}
+
namespace pr19987 {
template <typename T>
struct S {
OpenPOWER on IntegriCloud