]> granicus.if.org Git - clang/commitdiff
MS ABI: Handle member function pointers returning a member data pointer
authorDavid Majnemer <david.majnemer@gmail.com>
Thu, 7 Aug 2014 22:56:13 +0000 (22:56 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Thu, 7 Aug 2014 22:56:13 +0000 (22:56 +0000)
MSVC doesn't decide what the inheritance model for a returned member
pointer *until* a call expression returns it.

This fixes PR20017.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@215164 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGCXXABI.h
lib/CodeGen/CodeGenTypes.cpp
lib/CodeGen/MicrosoftCXXABI.cpp
lib/Sema/SemaOverload.cpp
test/SemaCXX/member-pointer-ms.cpp

index 91e49707bae683b1b0ee2b09b2b44e083b3cdf32..40418b60c1b90a9910e5288da43aa1659daae50f 100644 (file)
@@ -156,6 +156,11 @@ public:
   /// (in the C++ sense) with an LLVM zeroinitializer.
   virtual bool isZeroInitializable(const MemberPointerType *MPT);
 
+  /// Return whether or not a member pointers type is convertible to an IR type.
+  virtual bool isMemberPointerConvertible(const MemberPointerType *MPT) const {
+    return true;
+  }
+
   /// Create a null member pointer of the given type.
   virtual llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
 
index d4e22623e0293aa29dfc6d724400754cf71dcb92..6b0e4ad8b3137c8ea2961a85bf87d225adcd0246 100644 (file)
@@ -187,6 +187,11 @@ static bool isSafeToConvert(const RecordDecl *RD, CodeGenTypes &CGT) {
 /// we've temporarily deferred expanding the type because we're in a recursive
 /// context.
 bool CodeGenTypes::isFuncParamTypeConvertible(QualType Ty) {
+  // Some ABIs cannot have their member pointers represented in IR unless
+  // certain circumstances have been reached.
+  if (const auto *MPT = Ty->getAs<MemberPointerType>())
+    return getCXXABI().isMemberPointerConvertible(MPT);
+
   // If this isn't a tagged type, we can convert it!
   const TagType *TT = Ty->getAs<TagType>();
   if (!TT) return true;
@@ -194,7 +199,7 @@ bool CodeGenTypes::isFuncParamTypeConvertible(QualType Ty) {
   // Incomplete types cannot be converted.
   if (TT->isIncompleteType())
     return false;
-  
+
   // If this is an enum, then it is always safe to convert.
   const RecordType *RT = dyn_cast<RecordType>(TT);
   if (!RT) return true;
index 23f9768d4a8c45f8a1d0f3cdc4b90074c1de0dda..d01fb7bf34fb77aa8adcbf57887a5f5188421512 100644 (file)
@@ -482,6 +482,11 @@ public:
 
   bool isZeroInitializable(const MemberPointerType *MPT) override;
 
+  bool isMemberPointerConvertible(const MemberPointerType *MPT) const override {
+    const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
+    return RD->getAttr<MSInheritanceAttr>() != nullptr;
+  }
+
   llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT) override;
 
   llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
index e13fd14fd8c6e420dfac48d0b5b35ef3c598f869..d719b84c96c8e8cd2cc3b8354574a5927c61540c 100644 (file)
@@ -11353,6 +11353,10 @@ Sema::BuildCallToMemberFunction(Scope *S, Expr *MemExprE,
         << (qualsString.find(' ') == std::string::npos ? 1 : 2);
     }
 
+    if (resultType->isMemberPointerType())
+      if (Context.getTargetInfo().getCXXABI().isMicrosoft())
+        RequireCompleteType(LParenLoc, resultType, 0);
+
     CXXMemberCallExpr *call
       = new (Context) CXXMemberCallExpr(Context, MemExprE, Args,
                                         resultType, valueKind, RParenLoc);
index e7c4ae9409e04f9e451024d01cdcb060d03e1b5c..39cf601dc9561def4913c98c7cdec8c720c03936 100644 (file)
@@ -249,6 +249,25 @@ struct __virtual_inheritance D;
 struct D : virtual B {};
 }
 #ifdef VMB
+
+namespace PR20017 {
+template <typename T>
+struct A {
+  int T::*f();
+};
+
+struct B;
+
+auto a = &A<B>::f;
+
+struct B {};
+
+void q() {
+  A<B> b;
+  (b.*a)();
+}
+}
+
 #pragma pointers_to_members(full_generality, multiple_inheritance)
 struct TrulySingleInheritance;
 static_assert(sizeof(int TrulySingleInheritance::*) == kMultipleDataSize, "");