From 2affb95d6d410f32f63c293e1ba9698373c363f8 Mon Sep 17 00:00:00 2001 From: David Majnemer <david.majnemer@gmail.com> Date: Thu, 10 Sep 2015 21:52:00 +0000 Subject: [PATCH] [MS ABI] Make member pointers return true for isIncompleteType 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@247346 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/Type.cpp | 23 +++++++++++++++++++++++ lib/CodeGen/CGCXXABI.h | 4 ---- lib/CodeGen/CGCall.cpp | 4 ++-- lib/CodeGen/CGDebugInfo.cpp | 5 ++--- lib/CodeGen/CodeGenFunction.cpp | 2 +- lib/CodeGen/MicrosoftCXXABI.cpp | 11 ----------- lib/Sema/SemaExprCXX.cpp | 2 -- lib/Sema/SemaOverload.cpp | 4 ---- lib/Sema/SemaType.cpp | 28 ++++++++++++---------------- 9 files changed, 40 insertions(+), 43 deletions(-) diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index e0e6708c42e..dfa14aa18b1 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -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); diff --git a/lib/CodeGen/CGCXXABI.h b/lib/CodeGen/CGCXXABI.h index 828c9ecfc6a..93e2db0d121 100644 --- a/lib/CodeGen/CGCXXABI.h +++ b/lib/CodeGen/CGCXXABI.h @@ -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); diff --git a/lib/CodeGen/CGCall.cpp b/lib/CodeGen/CGCall.cpp index d4e0793fcce..e544ec5c408 100644 --- a/lib/CodeGen/CGCall.cpp +++ b/lib/CodeGen/CGCall.cpp @@ -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) diff --git a/lib/CodeGen/CGDebugInfo.cpp b/lib/CodeGen/CGDebugInfo.cpp index 61993f8d542..83b5e01deef 100644 --- a/lib/CodeGen/CGDebugInfo.cpp +++ b/lib/CodeGen/CGDebugInfo.cpp @@ -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( diff --git a/lib/CodeGen/CodeGenFunction.cpp b/lib/CodeGen/CodeGenFunction.cpp index 39bd2bc28e1..c948f8fdd9f 100644 --- a/lib/CodeGen/CodeGenFunction.cpp +++ b/lib/CodeGen/CodeGenFunction.cpp @@ -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 diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index 5cefc72ed0c..a981dd6e6d2 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -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, diff --git a/lib/Sema/SemaExprCXX.cpp b/lib/Sema/SemaExprCXX.cpp index e52aca14869..a48e634c3cd 100644 --- a/lib/Sema/SemaExprCXX.cpp +++ b/lib/Sema/SemaExprCXX.cpp @@ -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); diff --git a/lib/Sema/SemaOverload.cpp b/lib/Sema/SemaOverload.cpp index 251873542f3..34a03abb96f 100644 --- a/lib/Sema/SemaOverload.cpp +++ b/lib/Sema/SemaOverload.cpp @@ -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); diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 63e69d3281b..012b65b799f 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -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; } -- GitLab