[MS ABI] Make member pointers return true for isIncompleteType
authorDavid Majnemer <david.majnemer@gmail.com>
Thu, 10 Sep 2015 21:52:00 +0000 (21:52 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Thu, 10 Sep 2015 21:52:00 +0000 (21:52 +0000)
The type of a member pointer is incomplete if it has no inheritance
model.  This lets us reuse more general logic already embedded in clang.

llvm-svn: 247346

clang/lib/AST/Type.cpp
clang/lib/CodeGen/CGCXXABI.h
clang/lib/CodeGen/CGCall.cpp
clang/lib/CodeGen/CGDebugInfo.cpp
clang/lib/CodeGen/CodeGenFunction.cpp
clang/lib/CodeGen/MicrosoftCXXABI.cpp
clang/lib/Sema/SemaExprCXX.cpp
clang/lib/Sema/SemaOverload.cpp
clang/lib/Sema/SemaType.cpp

index e0e6708..dfa14aa 100644 (file)
@@ -22,6 +22,7 @@
 #include "clang/AST/Type.h"
 #include "clang/AST/TypeVisitor.h"
 #include "clang/Basic/Specifiers.h"
+#include "clang/Basic/TargetInfo.h"
 #include "llvm/ADT/APSInt.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/raw_ostream.h"
@@ -1899,6 +1900,28 @@ bool Type::isIncompleteType(NamedDecl **Def) const {
   case IncompleteArray:
     // An array of unknown size is an incomplete type (C99 6.2.5p22).
     return true;
+  case MemberPointer: {
+    // Member pointers in the MS ABI have special behavior in
+    // RequireCompleteType: they attach a MSInheritanceAttr to the CXXRecordDecl
+    // to indicate which inheritance model to use.
+    auto *MPTy = cast<MemberPointerType>(CanonicalType);
+    const Type *ClassTy = MPTy->getClass();
+    // Member pointers with dependent class types don't get special treatment.
+    if (ClassTy->isDependentType())
+      return false;
+    const CXXRecordDecl *RD = ClassTy->getAsCXXRecordDecl();
+    ASTContext &Context = RD->getASTContext();
+    // Member pointers not in the MS ABI don't get special treatment.
+    if (!Context.getTargetInfo().getCXXABI().isMicrosoft())
+      return false;
+    // The inheritance attribute might only be present on the most recent
+    // CXXRecordDecl, use that one.
+    RD = RD->getMostRecentDecl();
+    // Nothing interesting to do if the inheritance attribute is already set.
+    if (RD->hasAttr<MSInheritanceAttr>())
+      return false;
+    return true;
+  }
   case ObjCObject:
     return cast<ObjCObjectType>(CanonicalType)->getBaseType()
              ->isIncompleteType(Def);
index 828c9ec..93e2db0 100644 (file)
@@ -174,10 +174,6 @@ public:
     return true;
   }
 
-  virtual bool isTypeInfoCalculable(QualType Ty) const {
-    return !Ty->isIncompleteType();
-  }
-
   /// Create a null member pointer of the given type.
   virtual llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT);
 
index d4e0793..e544ec5 100644 (file)
@@ -1586,7 +1586,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
 
   if (const auto *RefTy = RetTy->getAs<ReferenceType>()) {
     QualType PTy = RefTy->getPointeeType();
-    if (getCXXABI().isTypeInfoCalculable(PTy) && PTy->isConstantSizeType())
+    if (!PTy->isIncompleteType() && PTy->isConstantSizeType())
       RetAttrs.addDereferenceableAttr(getContext().getTypeSizeInChars(PTy)
                                         .getQuantity());
     else if (getContext().getTargetAddressSpace(PTy) == 0)
@@ -1698,7 +1698,7 @@ void CodeGenModule::ConstructAttributeList(const CGFunctionInfo &FI,
 
     if (const auto *RefTy = ParamType->getAs<ReferenceType>()) {
       QualType PTy = RefTy->getPointeeType();
-      if (getCXXABI().isTypeInfoCalculable(PTy) && PTy->isConstantSizeType())
+      if (!PTy->isIncompleteType() && PTy->isConstantSizeType())
         Attrs.addDereferenceableAttr(getContext().getTypeSizeInChars(PTy)
                                        .getQuantity());
       else if (getContext().getTargetAddressSpace(PTy) == 0)
index 61993f8..83b5e01 100644 (file)
@@ -1906,9 +1906,8 @@ llvm::DIType *CGDebugInfo::CreateType(const RValueReferenceType *Ty,
 
 llvm::DIType *CGDebugInfo::CreateType(const MemberPointerType *Ty,
                                       llvm::DIFile *U) {
-  uint64_t Size = CGM.getCXXABI().isTypeInfoCalculable(QualType(Ty, 0))
-                      ? CGM.getContext().getTypeSize(Ty)
-                      : 0;
+  uint64_t Size =
+      !Ty->isIncompleteType() ? CGM.getContext().getTypeSize(Ty) : 0;
   llvm::DIType *ClassType = getOrCreateType(QualType(Ty->getClass(), 0), U);
   if (Ty->isMemberDataPointerType())
     return DBuilder.createMemberPointerType(
index 39bd2bc..c948f8f 100644 (file)
@@ -117,7 +117,7 @@ CharUnits CodeGenFunction::getNaturalTypeAlignment(QualType T,
   if (Source) *Source = AlignmentSource::Type;
 
   CharUnits Alignment;
-  if (!CGM.getCXXABI().isTypeInfoCalculable(T)) {
+  if (T->isIncompleteType()) {
     Alignment = CharUnits::One(); // Shouldn't be used, but pessimistic is best.
   } else {
     // For C++ class pointees, we don't know whether we're pointing at a
index 5cefc72..a981dd6 100644 (file)
@@ -594,17 +594,6 @@ public:
     return RD->hasAttr<MSInheritanceAttr>();
   }
 
-  bool isTypeInfoCalculable(QualType Ty) const override {
-    if (!CGCXXABI::isTypeInfoCalculable(Ty))
-      return false;
-    if (const auto *MPT = Ty->getAs<MemberPointerType>()) {
-      const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl();
-      if (!RD->hasAttr<MSInheritanceAttr>())
-        return false;
-    }
-    return true;
-  }
-
   llvm::Constant *EmitNullMemberPointer(const MemberPointerType *MPT) override;
 
   llvm::Constant *EmitMemberDataPointer(const MemberPointerType *MPT,
index e52aca1..a48e634 100644 (file)
@@ -4507,8 +4507,6 @@ QualType Sema::CheckPointerToMemberOperands(ExprResult &LHS, ExprResult &RHS,
       << OpSpelling << RHSType << RHS.get()->getSourceRange();
     return QualType();
   }
-  //if (Context.getTargetInfo().getCXXABI().isMicrosoft())
-  //  RequireCompleteType(Loc, QualType(MemPtr, 0), 0);
 
   QualType Class(MemPtr->getClass(), 0);
 
index 2518735..34a03ab 100644 (file)
@@ -11588,10 +11588,6 @@ 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 63e69d3..012b65b 100644 (file)
@@ -6253,13 +6253,9 @@ bool Sema::RequireCompleteExprType(Expr *E, TypeDiagnoser &Diagnoser){
   QualType T = E->getType();
 
   // Fast path the case where the type is already complete.
-  if (!T->isIncompleteType()) {
-    if (T->isMemberPointerType() &&
-        Context.getTargetInfo().getCXXABI().isMicrosoft())
-      RequireCompleteType(E->getExprLoc(), T, 0);
+  if (!T->isIncompleteType())
     // FIXME: The definition might not be visible.
     return false;
-  }
 
   // Incomplete array types may be completed by the initializer attached to
   // their definitions. For static data members of class templates and for
@@ -6469,6 +6465,17 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
   //  assert(!T->isDependentType() &&
   //         "Can't ask whether a dependent type is complete");
 
+  // We lock in the inheritance model once somebody has asked us to ensure
+  // that a pointer-to-member type is complete.
+  if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
+    if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
+      if (!MPTy->getClass()->isDependentType()) {
+        RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), 0);
+        assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl());
+      }
+    }
+  }
+
   // If we have a complete type, we're done.
   NamedDecl *Def = nullptr;
   if (!T->isIncompleteType(&Def)) {
@@ -6478,17 +6485,6 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T,
         !hasVisibleDefinition(Def, &SuggestedDef, /*OnlyNeedComplete*/true))
       diagnoseMissingImport(Loc, SuggestedDef, /*NeedDefinition*/true);
 
-    // We lock in the inheritance model once somebody has asked us to ensure
-    // that a pointer-to-member type is complete.
-    if (Context.getTargetInfo().getCXXABI().isMicrosoft()) {
-      if (const MemberPointerType *MPTy = T->getAs<MemberPointerType>()) {
-        if (!MPTy->getClass()->isDependentType()) {
-          RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), 0);
-          assignInheritanceModel(*this, MPTy->getMostRecentCXXRecordDecl());
-        }
-      }
-    }
-
     return false;
   }