From c26905fb57d33edf623a5708090fb6f4a7988d57 Mon Sep 17 00:00:00 2001 From: NAKAMURA Takumi Date: Fri, 17 Jan 2014 07:33:47 +0000 Subject: [PATCH] Revert r199416, "MS ABI: Improve selection of an inheritance model" It broke tests for targeting x86_64-pc-win32: Clang Tools :: clang-modernize/LoopConvert/array.cpp Clang :: CodeGenCXX/2010-05-10-Var-DbgInfo.cpp Clang :: CodeGenCXX/member-call-parens.cpp Clang :: CodeGenCXX/ptr-to-datamember.cpp Clang :: SemaTemplate/instantiate-function-1.cpp git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@199475 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/AST/DeclCXX.h | 15 +++-- include/clang/AST/Type.h | 1 - include/clang/Basic/Attr.td | 9 ++- lib/AST/MicrosoftCXXABI.cpp | 82 +++++++++++---------------- lib/AST/Type.cpp | 4 -- lib/CodeGen/MicrosoftCXXABI.cpp | 89 +++++++++++++----------------- lib/Sema/SemaCast.cpp | 8 --- lib/Sema/SemaType.cpp | 41 ++++++++++---- test/SemaCXX/microsoft-abi-ptm.cpp | 24 -------- 9 files changed, 118 insertions(+), 155 deletions(-) delete mode 100644 test/SemaCXX/microsoft-abi-ptm.cpp diff --git a/include/clang/AST/DeclCXX.h b/include/clang/AST/DeclCXX.h index aee2aad475..75f20e2462 100644 --- a/include/clang/AST/DeclCXX.h +++ b/include/clang/AST/DeclCXX.h @@ -17,7 +17,6 @@ #define LLVM_CLANG_AST_DECLCXX_H #include "clang/AST/ASTUnresolvedSet.h" -#include "clang/AST/Attr.h" #include "clang/AST/Decl.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" @@ -259,6 +258,16 @@ public: TypeSourceInfo *getTypeSourceInfo() const { return BaseTypeInfo; } }; +/// The inheritance model to use for member pointers of a given CXXRecordDecl. +enum MSInheritanceModel { + MSIM_Single, + MSIM_SinglePolymorphic, + MSIM_Multiple, + MSIM_MultiplePolymorphic, + MSIM_Virtual, + MSIM_Unspecified +}; + /// \brief Represents a C++ struct/union/class. /// /// FIXME: This class will disappear once we've properly taught RecordDecl @@ -1599,9 +1608,7 @@ public: } /// \brief Returns the inheritance model used for this record. - MSInheritanceAttr::Spelling getMSInheritanceModel() const; - /// \brief Locks-in the inheritance model for this class. - void setMSInheritanceModel(); + MSInheritanceModel getMSInheritanceModel() const; /// \brief Determine whether this lambda expression was known to be dependent /// at the time it was created, even if its context does not appear to be diff --git a/include/clang/AST/Type.h b/include/clang/AST/Type.h index 3a14c01f43..6b11b5892c 100644 --- a/include/clang/AST/Type.h +++ b/include/clang/AST/Type.h @@ -2205,7 +2205,6 @@ public: } const Type *getClass() const { return Class; } - CXXRecordDecl *getMostRecentCXXRecordDecl() const; bool isSugared() const { return false; } QualType desugar() const { return QualType(this, 0); } diff --git a/include/clang/Basic/Attr.td b/include/clang/Basic/Attr.td index cb739fb99f..73def038b8 100644 --- a/include/clang/Basic/Attr.td +++ b/include/clang/Basic/Attr.td @@ -1378,11 +1378,16 @@ def MSInheritance : InheritableAttr { let Spellings = [Keyword<"__single_inheritance">, Keyword<"__multiple_inheritance">, Keyword<"__virtual_inheritance">, - Keyword<"__unspecified_inheritance">]; + // We use an empty string to denote an unspecified + // inheritance attribute. + Keyword<"">]; let Accessors = [Accessor<"IsSingle", [Keyword<"__single_inheritance">]>, Accessor<"IsMultiple", [Keyword<"__multiple_inheritance">]>, Accessor<"IsVirtual", [Keyword<"__virtual_inheritance">]>, - Accessor<"IsUnspecified", [Keyword<"__unspecified_inheritance">]>]; + Accessor<"IsUnspecified", [Keyword<"">]>]; + // This index is based off the Spellings list and corresponds to the empty + // keyword "spelling." + let AdditionalMembers = [{static const int UnspecifiedSpellingIndex = 3;}]; } def Unaligned : IgnoredAttr { diff --git a/lib/AST/MicrosoftCXXABI.cpp b/lib/AST/MicrosoftCXXABI.cpp index c3478747a6..26e967570a 100644 --- a/lib/AST/MicrosoftCXXABI.cpp +++ b/lib/AST/MicrosoftCXXABI.cpp @@ -92,43 +92,28 @@ static bool usesMultipleInheritanceModel(const CXXRecordDecl *RD) { return false; } -static MSInheritanceAttr::Spelling -MSInheritanceAttrToModel(const MSInheritanceAttr *Attr) { +static MSInheritanceModel MSInheritanceAttrToModel(MSInheritanceAttr *Attr) { if (Attr->IsSingle()) - return MSInheritanceAttr::Keyword_single_inheritance; + return MSIM_Single; else if (Attr->IsMultiple()) - return MSInheritanceAttr::Keyword_multiple_inheritance; + return MSIM_Multiple; else if (Attr->IsVirtual()) - return MSInheritanceAttr::Keyword_virtual_inheritance; + return MSIM_Virtual; assert(Attr->IsUnspecified() && "Expected unspecified inheritance attr"); - return MSInheritanceAttr::Keyword_unspecified_inheritance; + return MSIM_Unspecified; } -static MSInheritanceAttr::Spelling -calculateInheritanceModel(const CXXRecordDecl *RD) { - if (!RD->hasDefinition()) - return MSInheritanceAttr::Keyword_unspecified_inheritance; - if (RD->getNumVBases() > 0) - return MSInheritanceAttr::Keyword_virtual_inheritance; - if (usesMultipleInheritanceModel(RD)) - return MSInheritanceAttr::Keyword_multiple_inheritance; - return MSInheritanceAttr::Keyword_single_inheritance; -} - -MSInheritanceAttr::Spelling -CXXRecordDecl::getMSInheritanceModel() const { - MSInheritanceAttr *IA = getAttr(); - assert(IA && "Expected MSInheritanceAttr on the CXXRecordDecl!"); - return MSInheritanceAttrToModel(IA); -} - -void CXXRecordDecl::setMSInheritanceModel() { - if (hasAttr()) - return; - - addAttr(MSInheritanceAttr::CreateImplicit( - getASTContext(), calculateInheritanceModel(this), getSourceRange())); +MSInheritanceModel CXXRecordDecl::getMSInheritanceModel() const { + if (MSInheritanceAttr *IA = this->getAttr()) + return MSInheritanceAttrToModel(IA); + // If there was no explicit attribute, the record must be defined already, and + // we can figure out the inheritance model from its other properties. + if (this->getNumVBases() > 0) + return MSIM_Virtual; + if (usesMultipleInheritanceModel(this)) + return this->isPolymorphic() ? MSIM_MultiplePolymorphic : MSIM_Multiple; + return this->isPolymorphic() ? MSIM_SinglePolymorphic : MSIM_Single; } // Returns the number of pointer and integer slots used to represent a member @@ -161,9 +146,9 @@ void CXXRecordDecl::setMSInheritanceModel() { // }; static std::pair getMSMemberPointerSlots(const MemberPointerType *MPT) { - const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); - MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); - unsigned Ptrs = 0; + const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl(); + MSInheritanceModel Inheritance = RD->getMSInheritanceModel(); + unsigned Ptrs; unsigned Ints = 0; if (MPT->isMemberFunctionPointer()) { // Member function pointers are a struct of a function pointer followed by a @@ -171,29 +156,26 @@ getMSMemberPointerSlots(const MemberPointerType *MPT) { // function pointer is a real function if it is non-virtual and a vftable // slot thunk if it is virtual. The ints select the object base passed for // the 'this' pointer. - Ptrs = 1; // First slot is always a function pointer. + Ptrs = 1; // First slot is always a function pointer. switch (Inheritance) { - case MSInheritanceAttr::Keyword_unspecified_inheritance: - ++Ints; // VBTableOffset - case MSInheritanceAttr::Keyword_virtual_inheritance: - ++Ints; // VirtualBaseAdjustmentOffset - case MSInheritanceAttr::Keyword_multiple_inheritance: - ++Ints; // NonVirtualBaseAdjustment - case MSInheritanceAttr::Keyword_single_inheritance: - break; // Nothing + case MSIM_Unspecified: ++Ints; // VBTableOffset + case MSIM_Virtual: ++Ints; // VirtualBaseAdjustmentOffset + case MSIM_MultiplePolymorphic: + case MSIM_Multiple: ++Ints; // NonVirtualBaseAdjustment + case MSIM_SinglePolymorphic: + case MSIM_Single: break; // Nothing } } else { // Data pointers are an aggregate of ints. The first int is an offset // followed by vbtable-related offsets. - Ints = 1; // We always have a field offset. + Ptrs = 0; switch (Inheritance) { - case MSInheritanceAttr::Keyword_unspecified_inheritance: - ++Ints; // VBTableOffset - case MSInheritanceAttr::Keyword_virtual_inheritance: - ++Ints; // VirtualBaseAdjustmentOffset - case MSInheritanceAttr::Keyword_multiple_inheritance: - case MSInheritanceAttr::Keyword_single_inheritance: - break; // Nothing + case MSIM_Unspecified: ++Ints; // VBTableOffset + case MSIM_Virtual: ++Ints; // VirtualBaseAdjustmentOffset + case MSIM_MultiplePolymorphic: + case MSIM_Multiple: // Nothing + case MSIM_SinglePolymorphic: + case MSIM_Single: ++Ints; // Field offset } } return std::make_pair(Ptrs, Ints); diff --git a/lib/AST/Type.cpp b/lib/AST/Type.cpp index 3d4a7454f7..fac10768d5 100644 --- a/lib/AST/Type.cpp +++ b/lib/AST/Type.cpp @@ -2469,7 +2469,3 @@ QualType::DestructionKind QualType::isDestructedTypeImpl(QualType type) { return DK_none; } - -CXXRecordDecl *MemberPointerType::getMostRecentCXXRecordDecl() const { - return getClass()->getAsCXXRecordDecl()->getMostRecentDecl(); -} diff --git a/lib/CodeGen/MicrosoftCXXABI.cpp b/lib/CodeGen/MicrosoftCXXABI.cpp index 875591d0df..32f8ab2fb5 100644 --- a/lib/CodeGen/MicrosoftCXXABI.cpp +++ b/lib/CodeGen/MicrosoftCXXABI.cpp @@ -1322,29 +1322,25 @@ void MicrosoftCXXABI::EmitGuardedInit(CodeGenFunction &CGF, const VarDecl &D, } // Member pointer helpers. -static bool hasVBPtrOffsetField(MSInheritanceAttr::Spelling Inheritance) { - return Inheritance == MSInheritanceAttr::Keyword_unspecified_inheritance; +static bool hasVBPtrOffsetField(MSInheritanceModel Inheritance) { + return Inheritance == MSIM_Unspecified; } static bool hasOnlyOneField(bool IsMemberFunction, - MSInheritanceAttr::Spelling Inheritance) { - if (IsMemberFunction) - return Inheritance <= MSInheritanceAttr::Keyword_single_inheritance; - return Inheritance <= MSInheritanceAttr::Keyword_multiple_inheritance; + MSInheritanceModel Inheritance) { + return Inheritance <= MSIM_SinglePolymorphic || + (!IsMemberFunction && Inheritance <= MSIM_MultiplePolymorphic); } // Only member pointers to functions need a this adjustment, since it can be // combined with the field offset for data pointers. -static bool -hasNonVirtualBaseAdjustmentField(bool IsMemberFunction, - MSInheritanceAttr::Spelling Inheritance) { - return IsMemberFunction && - Inheritance >= MSInheritanceAttr::Keyword_multiple_inheritance; +static bool hasNonVirtualBaseAdjustmentField(bool IsMemberFunction, + MSInheritanceModel Inheritance) { + return (IsMemberFunction && Inheritance >= MSIM_Multiple); } -static bool -hasVirtualBaseAdjustmentField(MSInheritanceAttr::Spelling Inheritance) { - return Inheritance >= MSInheritanceAttr::Keyword_virtual_inheritance; +static bool hasVirtualBaseAdjustmentField(MSInheritanceModel Inheritance) { + return Inheritance >= MSIM_Virtual; } // Use zero for the field offset of a null data member pointer if we can @@ -1353,10 +1349,8 @@ hasVirtualBaseAdjustmentField(MSInheritanceAttr::Spelling Inheritance) { // use zero for null. If there are multiple fields, we can use zero even if it // is a valid field offset because null-ness testing will check the other // fields. -static bool nullFieldOffsetIsZero(const CXXRecordDecl *RD) { - return RD->getMSInheritanceModel() >= - MSInheritanceAttr::Keyword_virtual_inheritance || - (RD->hasDefinition() && RD->isPolymorphic()); +static bool nullFieldOffsetIsZero(MSInheritanceModel Inheritance) { + return Inheritance != MSIM_Multiple && Inheritance != MSIM_Single; } bool MicrosoftCXXABI::isZeroInitializable(const MemberPointerType *MPT) { @@ -1368,16 +1362,16 @@ bool MicrosoftCXXABI::isZeroInitializable(const MemberPointerType *MPT) { // The virtual base adjustment field is always -1 for null, so if we have one // we can't zero initialize. The field offset is sometimes also -1 if 0 is a // valid field offset. - const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); - MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); + const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl(); + MSInheritanceModel Inheritance = RD->getMSInheritanceModel(); return (!hasVirtualBaseAdjustmentField(Inheritance) && - nullFieldOffsetIsZero(RD)); + nullFieldOffsetIsZero(Inheritance)); } llvm::Type * MicrosoftCXXABI::ConvertMemberPointerType(const MemberPointerType *MPT) { - const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); - MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); + const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl(); + MSInheritanceModel Inheritance = RD->getMSInheritanceModel(); llvm::SmallVector fields; if (MPT->isMemberFunctionPointer()) fields.push_back(CGM.VoidPtrTy); // FunctionPointerOrVirtualThunk @@ -1401,13 +1395,13 @@ void MicrosoftCXXABI:: GetNullMemberPointerFields(const MemberPointerType *MPT, llvm::SmallVectorImpl &fields) { assert(fields.empty()); - const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); - MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); + const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl(); + MSInheritanceModel Inheritance = RD->getMSInheritanceModel(); if (MPT->isMemberFunctionPointer()) { // FunctionPointerOrVirtualThunk fields.push_back(llvm::Constant::getNullValue(CGM.VoidPtrTy)); } else { - if (nullFieldOffsetIsZero(RD)) + if (nullFieldOffsetIsZero(Inheritance)) fields.push_back(getZeroInt()); // FieldOffset else fields.push_back(getAllOnesInt()); // FieldOffset @@ -1439,7 +1433,7 @@ MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField, const CXXRecordDecl *RD, CharUnits NonVirtualBaseAdjustment) { - MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); + MSInheritanceModel Inheritance = RD->getMSInheritanceModel(); // Single inheritance class member pointer are represented as scalars instead // of aggregates. @@ -1470,7 +1464,7 @@ MicrosoftCXXABI::EmitFullMemberPointer(llvm::Constant *FirstField, llvm::Constant * MicrosoftCXXABI::EmitMemberDataPointer(const MemberPointerType *MPT, CharUnits offset) { - const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); + const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl(); llvm::Constant *FirstField = llvm::ConstantInt::get(CGM.IntTy, offset.getQuantity()); return EmitFullMemberPointer(FirstField, /*IsMemberFunction=*/false, RD, @@ -1493,8 +1487,8 @@ llvm::Constant *MicrosoftCXXABI::EmitMemberPointer(const APValue &MP, // FIXME PR15713: Support virtual inheritance paths. if (const CXXMethodDecl *MD = dyn_cast(MPD)) - return BuildMemberPointer(MPT->getMostRecentCXXRecordDecl(), MD, - ThisAdjustment); + return BuildMemberPointer(MPT->getClass()->getAsCXXRecordDecl(), + MD, ThisAdjustment); CharUnits FieldOffset = getContext().toCharUnitsFromBits(getContext().getFieldOffset(MPD)); @@ -1507,7 +1501,6 @@ MicrosoftCXXABI::BuildMemberPointer(const CXXRecordDecl *RD, CharUnits NonVirtualBaseAdjustment) { assert(MD->isInstance() && "Member function must not be static!"); MD = MD->getCanonicalDecl(); - RD = RD->getMostRecentDecl(); CodeGenTypes &Types = CGM.getTypes(); llvm::Constant *FirstField; @@ -1585,8 +1578,8 @@ MicrosoftCXXABI::EmitMemberPointerComparison(CodeGenFunction &CGF, // If this is a single field member pointer (single inheritance), this is a // single icmp. - const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); - MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); + const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl(); + MSInheritanceModel Inheritance = RD->getMSInheritanceModel(); if (hasOnlyOneField(MPT->isMemberFunctionPointer(), Inheritance)) return Builder.CreateICmp(Eq, L, R); @@ -1767,8 +1760,8 @@ MicrosoftCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, llvm::Type *PType = CGF.ConvertTypeForMem(MPT->getPointeeType())->getPointerTo(AS); CGBuilderTy &Builder = CGF.Builder; - const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); - MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); + const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl(); + MSInheritanceModel Inheritance = RD->getMSInheritanceModel(); // Extract the fields we need, regardless of model. We'll apply them if we // have them. @@ -1802,9 +1795,9 @@ MicrosoftCXXABI::EmitMemberDataPointerAddress(CodeGenFunction &CGF, return Builder.CreateBitCast(Addr, PType); } -static MSInheritanceAttr::Spelling +static MSInheritanceModel getInheritanceFromMemptr(const MemberPointerType *MPT) { - return MPT->getMostRecentCXXRecordDecl()->getMSInheritanceModel(); + return MPT->getClass()->getAsCXXRecordDecl()->getMSInheritanceModel(); } llvm::Value * @@ -1824,17 +1817,15 @@ MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, const MemberPointerType *SrcTy = E->getSubExpr()->getType()->castAs(); const MemberPointerType *DstTy = E->getType()->castAs(); + MSInheritanceModel SrcInheritance = getInheritanceFromMemptr(SrcTy); + MSInheritanceModel DstInheritance = getInheritanceFromMemptr(DstTy); bool IsFunc = SrcTy->isMemberFunctionPointer(); // If the classes use the same null representation, reinterpret_cast is a nop. bool IsReinterpret = E->getCastKind() == CK_ReinterpretMemberPointer; - if (IsReinterpret && IsFunc) - return Src; - - CXXRecordDecl *SrcRD = SrcTy->getMostRecentCXXRecordDecl(); - CXXRecordDecl *DstRD = DstTy->getMostRecentCXXRecordDecl(); - if (IsReinterpret && - nullFieldOffsetIsZero(SrcRD) == nullFieldOffsetIsZero(DstRD)) + if (IsReinterpret && (IsFunc || + nullFieldOffsetIsZero(SrcInheritance) == + nullFieldOffsetIsZero(DstInheritance))) return Src; CGBuilderTy &Builder = CGF.Builder; @@ -1863,7 +1854,6 @@ MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, llvm::Value *NonVirtualBaseAdjustment = 0; llvm::Value *VirtualBaseAdjustmentOffset = 0; llvm::Value *VBPtrOffset = 0; - MSInheritanceAttr::Spelling SrcInheritance = SrcRD->getMSInheritanceModel(); if (!hasOnlyOneField(IsFunc, SrcInheritance)) { // We need to extract values. unsigned I = 0; @@ -1894,7 +1884,6 @@ MicrosoftCXXABI::EmitMemberPointerConversion(CodeGenFunction &CGF, // FIXME PR15713: Support conversions through virtually derived classes. // Recompose dst from the null struct and the adjusted fields from src. - MSInheritanceAttr::Spelling DstInheritance = DstRD->getMSInheritanceModel(); llvm::Value *Dst; if (hasOnlyOneField(IsFunc, DstInheritance)) { Dst = FirstField; @@ -1940,8 +1929,8 @@ MicrosoftCXXABI::EmitMemberPointerConversion(const CastExpr *E, if (E->getCastKind() == CK_ReinterpretMemberPointer) return Src; - MSInheritanceAttr::Spelling SrcInheritance = getInheritanceFromMemptr(SrcTy); - MSInheritanceAttr::Spelling DstInheritance = getInheritanceFromMemptr(DstTy); + MSInheritanceModel SrcInheritance = getInheritanceFromMemptr(SrcTy); + MSInheritanceModel DstInheritance = getInheritanceFromMemptr(DstTy); // Decompose src. llvm::Constant *FirstField = Src; @@ -2002,13 +1991,13 @@ MicrosoftCXXABI::EmitLoadOfMemberFunctionPointer(CodeGenFunction &CGF, assert(MPT->isMemberFunctionPointer()); const FunctionProtoType *FPT = MPT->getPointeeType()->castAs(); - const CXXRecordDecl *RD = MPT->getMostRecentCXXRecordDecl(); + const CXXRecordDecl *RD = MPT->getClass()->getAsCXXRecordDecl(); llvm::FunctionType *FTy = CGM.getTypes().GetFunctionType( CGM.getTypes().arrangeCXXMethodType(RD, FPT)); CGBuilderTy &Builder = CGF.Builder; - MSInheritanceAttr::Spelling Inheritance = RD->getMSInheritanceModel(); + MSInheritanceModel Inheritance = RD->getMSInheritanceModel(); // Extract the fields we need, regardless of model. We'll apply them if we // have them. diff --git a/lib/Sema/SemaCast.cpp b/lib/Sema/SemaCast.cpp index 499e8b18be..63cb15db52 100644 --- a/lib/Sema/SemaCast.cpp +++ b/lib/Sema/SemaCast.cpp @@ -21,7 +21,6 @@ #include "clang/AST/ExprObjC.h" #include "clang/AST/RecordLayout.h" #include "clang/Basic/PartialDiagnostic.h" -#include "clang/Basic/TargetInfo.h" #include "clang/Sema/Initialization.h" #include "llvm/ADT/SmallVector.h" #include @@ -1780,13 +1779,6 @@ static TryCastResult TryReinterpretCast(Sema &Self, ExprResult &SrcExpr, return TC_Failed; } - if (Self.Context.getTargetInfo().getCXXABI().isMicrosoft()) { - // We need to determine the inheritance model that the class will use if - // haven't yet. - Self.RequireCompleteType(OpRange.getBegin(), SrcType, 0); - Self.RequireCompleteType(OpRange.getBegin(), DestType, 0); - } - // Don't allow casting between member pointers of different sizes. if (Self.Context.getTypeSize(DestMemPtr) != Self.Context.getTypeSize(SrcMemPtr)) { diff --git a/lib/Sema/SemaType.cpp b/lib/Sema/SemaType.cpp index 30edc48dd5..bc674d53d7 100644 --- a/lib/Sema/SemaType.cpp +++ b/lib/Sema/SemaType.cpp @@ -1753,6 +1753,35 @@ QualType Sema::BuildMemberPointerType(QualType T, QualType Class, return QualType(); } + // C++ allows the class type in a member pointer to be an incomplete type. + // In the Microsoft ABI, the size of the member pointer can vary + // according to the class type, which means that we really need a + // complete type if possible, which means we need to instantiate templates. + // + // If template instantiation fails or the type is just incomplete, we have to + // add an extra slot to the member pointer. Yes, this does cause problems + // when passing pointers between TUs that disagree about the size. + if (Context.getTargetInfo().getCXXABI().isMicrosoft()) { + CXXRecordDecl *RD = Class->getAsCXXRecordDecl(); + if (RD && !RD->hasAttr()) { + // Lock in the inheritance model on the first use of a member pointer. + // Otherwise we may disagree about the size at different points in the TU. + // FIXME: MSVC picks a model on the first use that needs to know the size, + // rather than on the first mention of the type, e.g. typedefs. + if (RequireCompleteType(Loc, Class, 0) && !RD->isBeingDefined()) { + // We know it doesn't have an attribute and it's incomplete, so use the + // unspecified inheritance model. If we're in the record body, we can + // figure out the inheritance model. + for (CXXRecordDecl::redecl_iterator I = RD->redecls_begin(), + E = RD->redecls_end(); I != E; ++I) { + I->addAttr(::new (Context) MSInheritanceAttr(RD->getSourceRange(), + Context, + MSInheritanceAttr::UnspecifiedSpellingIndex)); + } + } + } + } + // Adjust the default free function calling convention to the default method // calling convention. if (T->isFunctionType()) @@ -5067,18 +5096,6 @@ bool Sema::RequireCompleteTypeImpl(SourceLocation Loc, QualType T, } } - // 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()) { - if (!MPTy->getClass()->isDependentType()) { - RequireCompleteType(Loc, QualType(MPTy->getClass(), 0), 0); - - MPTy->getMostRecentCXXRecordDecl()->setMSInheritanceModel(); - } - } - } - return false; } diff --git a/test/SemaCXX/microsoft-abi-ptm.cpp b/test/SemaCXX/microsoft-abi-ptm.cpp deleted file mode 100644 index 8ee8a2d4a2..0000000000 --- a/test/SemaCXX/microsoft-abi-ptm.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// RUN: %clang_cc1 -triple %ms_abi_triple -std=c++11 -fsyntax-only -fms-extensions -fms-compatibility %s - -namespace Test1 { -struct A; -void f(int A::*mp); -struct A { }; -static_assert(sizeof(int A::*) == sizeof(int), "pointer-to-member should be sizeof(int)"); -} - -namespace Test2 { -struct A; -void f(int A::*mp); -static_assert(sizeof(int A::*) == sizeof(int) * 3, "pointer-to-member should be sizeof(int) * 3"); -struct A { }; -static_assert(sizeof(int A::*) == sizeof(int) * 3, "pointer-to-member should still be sizeof(int) * 3"); -} - -namespace Test3 { -struct A; -typedef int A::*p; -struct __single_inheritance A; -p my_ptr; -static_assert(sizeof(int A::*) == sizeof(int), "pointer-to-member should be sizeof(int)"); -} -- 2.40.0