From: David Majnemer Date: Fri, 8 Aug 2014 00:10:39 +0000 (+0000) Subject: MS ABI: Don't force bases to have an inheritance model X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4f071e89894b0eef44a22d5cdc68b161fd01de22;p=clang 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? git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@215174 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index eb7924f473..49d1fdfb3f 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/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/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index b6b024c89a..029d2c2806 100644 --- a/lib/Sema/SemaType.cpp +++ b/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/test/CodeGenCXX/microsoft-abi-member-pointers.cpp b/test/CodeGenCXX/microsoft-abi-member-pointers.cpp index 18e8c827ee..80d92de3ec 100644 --- a/test/CodeGenCXX/microsoft-abi-member-pointers.cpp +++ b/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 struct S {