diff options
author | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2013-04-08 18:45:10 +0000 |
commit | c72c57c9e9b69944e3e009cd5e209634839581d3 (patch) | |
tree | 4fc2f184c499d106f29a386c452b49e5197bf63d /lib/AST/ASTContext.cpp | |
parent | 5b20025c30d23d521e12c1f33ec8fa6b821952cd (diff) | |
download | FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.zip FreeBSD-src-c72c57c9e9b69944e3e009cd5e209634839581d3.tar.gz |
Vendor import of clang trunk r178860:
http://llvm.org/svn/llvm-project/cfe/trunk@178860
Diffstat (limited to 'lib/AST/ASTContext.cpp')
-rw-r--r-- | lib/AST/ASTContext.cpp | 767 |
1 files changed, 523 insertions, 244 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 74c68ae..7245c03 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -12,28 +12,29 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTContext.h" +#include "CXXABI.h" +#include "clang/AST/ASTMutationListener.h" +#include "clang/AST/Attr.h" #include "clang/AST/CharUnits.h" +#include "clang/AST/Comment.h" #include "clang/AST/CommentCommandTraits.h" #include "clang/AST/DeclCXX.h" #include "clang/AST/DeclObjC.h" #include "clang/AST/DeclTemplate.h" -#include "clang/AST/TypeLoc.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" #include "clang/AST/ExternalASTSource.h" -#include "clang/AST/ASTMutationListener.h" -#include "clang/AST/RecordLayout.h" #include "clang/AST/Mangle.h" -#include "clang/AST/Comment.h" +#include "clang/AST/RecordLayout.h" +#include "clang/AST/TypeLoc.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/SourceManager.h" #include "clang/Basic/TargetInfo.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Capacity.h" #include "llvm/Support/MathExtras.h" #include "llvm/Support/raw_ostream.h" -#include "llvm/Support/Capacity.h" -#include "CXXABI.h" #include <map> using namespace clang; @@ -84,6 +85,14 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { return NULL; } + if (const ClassTemplateSpecializationDecl *CTSD = + dyn_cast<ClassTemplateSpecializationDecl>(D)) { + TemplateSpecializationKind TSK = CTSD->getSpecializationKind(); + if (TSK == TSK_ImplicitInstantiation || + TSK == TSK_Undeclared) + return NULL; + } + if (const EnumDecl *ED = dyn_cast<EnumDecl>(D)) { if (ED->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) return NULL; @@ -364,10 +373,12 @@ static void addRedeclaredMethods(const ObjCMethodDecl *ObjCMethod, if (!ID) return; // Add redeclared method here. - for (const ObjCCategoryDecl *ClsExtDecl = ID->getFirstClassExtension(); - ClsExtDecl; ClsExtDecl = ClsExtDecl->getNextClassExtension()) { + for (ObjCInterfaceDecl::known_extensions_iterator + Ext = ID->known_extensions_begin(), + ExtEnd = ID->known_extensions_end(); + Ext != ExtEnd; ++Ext) { if (ObjCMethodDecl *RedeclaredMethod = - ClsExtDecl->getMethod(ObjCMethod->getSelector(), + Ext->getMethod(ObjCMethod->getSelector(), ObjCMethod->isInstanceMethod())) Redeclared.push_back(RedeclaredMethod); } @@ -412,15 +423,26 @@ comments::FullComment *ASTContext::getCommentForDecl( if (!RC) { if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) { SmallVector<const NamedDecl*, 8> Overridden; - if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) + const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D); + if (OMD && OMD->isPropertyAccessor()) + if (const ObjCPropertyDecl *PDecl = OMD->findPropertyDecl()) + if (comments::FullComment *FC = getCommentForDecl(PDecl, PP)) + return cloneFullComment(FC, D); + if (OMD) addRedeclaredMethods(OMD, Overridden); getOverriddenMethods(dyn_cast<NamedDecl>(D), Overridden); - for (unsigned i = 0, e = Overridden.size(); i < e; i++) { - if (comments::FullComment *FC = getCommentForDecl(Overridden[i], PP)) { - comments::FullComment *CFC = cloneFullComment(FC, D); - return CFC; - } - } + for (unsigned i = 0, e = Overridden.size(); i < e; i++) + if (comments::FullComment *FC = getCommentForDecl(Overridden[i], PP)) + return cloneFullComment(FC, D); + } + else if (const TypedefDecl *TD = dyn_cast<TypedefDecl>(D)) { + // Attach any tag type's documentation to its typedef if latter + // does not have one of its own. + QualType QT = TD->getUnderlyingType(); + if (const TagType *TT = QT->getAs<TagType>()) + if (const Decl *TD = TT->getDecl()) + if (comments::FullComment *FC = getCommentForDecl(TD, PP)) + return cloneFullComment(FC, D); } return NULL; } @@ -571,12 +593,14 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( CXXABI *ASTContext::createCXXABI(const TargetInfo &T) { if (!LangOpts.CPlusPlus) return 0; - switch (T.getCXXABI()) { - case CXXABI_ARM: + switch (T.getCXXABI().getKind()) { + case TargetCXXABI::GenericARM: + case TargetCXXABI::iOS: return CreateARMCXXABI(*this); - case CXXABI_Itanium: + case TargetCXXABI::GenericAArch64: // Same as Itanium at this level + case TargetCXXABI::GenericItanium: return CreateItaniumCXXABI(*this); - case CXXABI_Microsoft: + case TargetCXXABI::Microsoft: return CreateMicrosoftCXXABI(*this); } llvm_unreachable("Invalid CXXABI type!"); @@ -630,9 +654,9 @@ ASTContext::ASTContext(LangOptions& LOpts, SourceManager &SM, DeclarationNames(*this), ExternalSource(0), Listener(0), Comments(SM), CommentsLoaded(false), - CommentCommandTraits(BumpAlloc), + CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), LastSDM(0, 0), - UniqueBlockByRefTypeID(0) + UniqueBlockByRefTypeID(0) { if (size_reserve > 0) Types.reserve(size_reserve); TUDecl = TranslationUnitDecl::Create(*this); @@ -873,12 +897,26 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target) { InitBuiltinType(ObjCBuiltinIdTy, BuiltinType::ObjCId); InitBuiltinType(ObjCBuiltinClassTy, BuiltinType::ObjCClass); InitBuiltinType(ObjCBuiltinSelTy, BuiltinType::ObjCSel); + + if (LangOpts.OpenCL) { + InitBuiltinType(OCLImage1dTy, BuiltinType::OCLImage1d); + InitBuiltinType(OCLImage1dArrayTy, BuiltinType::OCLImage1dArray); + InitBuiltinType(OCLImage1dBufferTy, BuiltinType::OCLImage1dBuffer); + InitBuiltinType(OCLImage2dTy, BuiltinType::OCLImage2d); + InitBuiltinType(OCLImage2dArrayTy, BuiltinType::OCLImage2dArray); + InitBuiltinType(OCLImage3dTy, BuiltinType::OCLImage3d); + + InitBuiltinType(OCLSamplerTy, BuiltinType::OCLSampler); + InitBuiltinType(OCLEventTy, BuiltinType::OCLEvent); + } // Builtin type for __objc_yes and __objc_no ObjCBuiltinBoolTy = (Target.useSignedCharForObjCBool() ? SignedCharTy : BoolTy); ObjCConstantStringType = QualType(); + + ObjCSuperType = QualType(); // void * type VoidPtrTy = getPointerType(VoidTy); @@ -1411,6 +1449,22 @@ ASTContext::getTypeInfoImpl(const Type *T) const { Width = Target->getPointerWidth(0); Align = Target->getPointerAlign(0); break; + case BuiltinType::OCLSampler: + // Samplers are modeled as integers. + Width = Target->getIntWidth(); + Align = Target->getIntAlign(); + break; + case BuiltinType::OCLEvent: + case BuiltinType::OCLImage1d: + case BuiltinType::OCLImage1dArray: + case BuiltinType::OCLImage1dBuffer: + case BuiltinType::OCLImage2d: + case BuiltinType::OCLImage2dArray: + case BuiltinType::OCLImage3d: + // Currently these types are pointers to opaque types. + Width = Target->getPointerWidth(0); + Align = Target->getPointerAlign(0); + break; } break; case Type::ObjCObjectPointer: @@ -1442,10 +1496,7 @@ ASTContext::getTypeInfoImpl(const Type *T) const { } case Type::MemberPointer: { const MemberPointerType *MPT = cast<MemberPointerType>(T); - std::pair<uint64_t, unsigned> PtrDiffInfo = - getTypeInfo(getPointerDiffType()); - Width = PtrDiffInfo.first * ABI->getMemberPointerSize(MPT); - Align = PtrDiffInfo.second; + llvm::tie(Width, Align) = ABI->getMemberPointerWidthAndAlign(MPT); break; } case Type::Complex: { @@ -1548,18 +1599,21 @@ ASTContext::getTypeInfoImpl(const Type *T) const { } case Type::Atomic: { + // Start with the base type information. std::pair<uint64_t, unsigned> Info = getTypeInfo(cast<AtomicType>(T)->getValueType()); Width = Info.first; Align = Info.second; - if (Width != 0 && Width <= Target->getMaxAtomicPromoteWidth() && - llvm::isPowerOf2_64(Width)) { - // We can potentially perform lock-free atomic operations for this - // type; promote the alignment appropriately. - // FIXME: We could potentially promote the width here as well... - // is that worthwhile? (Non-struct atomic types generally have - // power-of-two size anyway, but structs might not. Requires a bit - // of implementation work to make sure we zero out the extra bits.) + + // If the size of the type doesn't exceed the platform's max + // atomic promotion width, make the size and alignment more + // favorable to atomic operations: + if (Width != 0 && Width <= Target->getMaxAtomicPromoteWidth()) { + // Round the size up to a power of 2. + if (!llvm::isPowerOf2_64(Width)) + Width = llvm::NextPowerOf2(Width); + + // Set the alignment equal to the size. Align = static_cast<unsigned>(Width); } } @@ -1658,9 +1712,13 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, } // Categories of this Interface. - for (const ObjCCategoryDecl *CDeclChain = OI->getCategoryList(); - CDeclChain; CDeclChain = CDeclChain->getNextClassCategory()) - CollectInheritedProtocols(CDeclChain, Protocols); + for (ObjCInterfaceDecl::visible_categories_iterator + Cat = OI->visible_categories_begin(), + CatEnd = OI->visible_categories_end(); + Cat != CatEnd; ++Cat) { + CollectInheritedProtocols(*Cat, Protocols); + } + if (ObjCInterfaceDecl *SD = OI->getSuperClass()) while (SD) { CollectInheritedProtocols(SD, Protocols); @@ -1690,10 +1748,13 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, unsigned ASTContext::CountNonClassIvars(const ObjCInterfaceDecl *OI) const { unsigned count = 0; // Count ivars declared in class extension. - for (const ObjCCategoryDecl *CDecl = OI->getFirstClassExtension(); CDecl; - CDecl = CDecl->getNextClassExtension()) - count += CDecl->ivar_size(); - + for (ObjCInterfaceDecl::known_extensions_iterator + Ext = OI->known_extensions_begin(), + ExtEnd = OI->known_extensions_end(); + Ext != ExtEnd; ++Ext) { + count += Ext->ivar_size(); + } + // Count ivar defined in this class's implementation. This // includes synthesized ivars. if (ObjCImplementationDecl *ImplDecl = OI->getImplementation()) @@ -1750,12 +1811,16 @@ void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD, ObjCImpls[CatD] = ImplD; } -ObjCInterfaceDecl *ASTContext::getObjContainingInterface(NamedDecl *ND) const { - if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(ND->getDeclContext())) +const ObjCInterfaceDecl *ASTContext::getObjContainingInterface( + const NamedDecl *ND) const { + if (const ObjCInterfaceDecl *ID = + dyn_cast<ObjCInterfaceDecl>(ND->getDeclContext())) return ID; - if (ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(ND->getDeclContext())) + if (const ObjCCategoryDecl *CD = + dyn_cast<ObjCCategoryDecl>(ND->getDeclContext())) return CD->getClassInterface(); - if (ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(ND->getDeclContext())) + if (const ObjCImplDecl *IMD = + dyn_cast<ObjCImplDecl>(ND->getDeclContext())) return IMD->getClassInterface(); return 0; @@ -1906,8 +1971,10 @@ const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T, const FunctionProtoType *FPT = cast<FunctionProtoType>(T); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.ExtInfo = Info; - Result = getFunctionType(FPT->getResultType(), FPT->arg_type_begin(), - FPT->getNumArgs(), EPI); + Result = getFunctionType(FPT->getResultType(), + ArrayRef<QualType>(FPT->arg_type_begin(), + FPT->getNumArgs()), + EPI); } return cast<FunctionType>(Result.getTypePtr()); @@ -2562,16 +2629,25 @@ ASTContext::getFunctionNoProtoType(QualType ResultTy, return QualType(New, 0); } +/// \brief Determine whether \p T is canonical as the result type of a function. +static bool isCanonicalResultType(QualType T) { + return T.isCanonical() && + (T.getObjCLifetime() == Qualifiers::OCL_None || + T.getObjCLifetime() == Qualifiers::OCL_ExplicitNone); +} + /// getFunctionType - Return a normal function type with a typed argument /// list. isVariadic indicates whether the argument list includes '...'. QualType -ASTContext::getFunctionType(QualType ResultTy, - const QualType *ArgArray, unsigned NumArgs, +ASTContext::getFunctionType(QualType ResultTy, ArrayRef<QualType> ArgArray, const FunctionProtoType::ExtProtoInfo &EPI) const { + size_t NumArgs = ArgArray.size(); + // Unique functions, to guarantee there is only one function of a particular // structure. llvm::FoldingSetNodeID ID; - FunctionProtoType::Profile(ID, ResultTy, ArgArray, NumArgs, EPI, *this); + FunctionProtoType::Profile(ID, ResultTy, ArgArray.begin(), NumArgs, EPI, + *this); void *InsertPos = 0; if (FunctionProtoType *FTP = @@ -2580,7 +2656,7 @@ ASTContext::getFunctionType(QualType ResultTy, // Determine whether the type being created is already canonical or not. bool isCanonical = - EPI.ExceptionSpecType == EST_None && ResultTy.isCanonical() && + EPI.ExceptionSpecType == EST_None && isCanonicalResultType(ResultTy) && !EPI.HasTrailingReturn; for (unsigned i = 0; i != NumArgs && isCanonical; ++i) if (!ArgArray[i].isCanonicalAsParam()) @@ -2606,9 +2682,15 @@ ASTContext::getFunctionType(QualType ResultTy, CanonicalEPI.ExtInfo = CanonicalEPI.ExtInfo.withCallingConv(getCanonicalCallConv(CallConv)); - Canonical = getFunctionType(getCanonicalType(ResultTy), - CanonicalArgs.data(), NumArgs, - CanonicalEPI); + // Result types do not have ARC lifetime qualifiers. + QualType CanResultTy = getCanonicalType(ResultTy); + if (ResultTy.getQualifiers().hasObjCLifetime()) { + Qualifiers Qs = CanResultTy.getQualifiers(); + Qs.removeObjCLifetime(); + CanResultTy = getQualifiedType(CanResultTy.getUnqualifiedType(), Qs); + } + + Canonical = getFunctionType(CanResultTy, CanonicalArgs, CanonicalEPI); // Get the new insert position for the node we care about. FunctionProtoType *NewIP = @@ -2641,7 +2723,7 @@ ASTContext::getFunctionType(QualType ResultTy, FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment); FunctionProtoType::ExtProtoInfo newEPI = EPI; newEPI.ExtInfo = EPI.ExtInfo.withCallingConv(CallConv); - new (FTP) FunctionProtoType(ResultTy, ArgArray, NumArgs, Canonical, newEPI); + new (FTP) FunctionProtoType(ResultTy, ArgArray, Canonical, newEPI); Types.push_back(FTP); FunctionProtoTypes.InsertNode(FTP, InsertPos); return QualType(FTP, 0); @@ -2877,8 +2959,8 @@ ASTContext::getTemplateSpecializationTypeInfo(TemplateName Name, QualType TST = getTemplateSpecializationType(Name, Args, Underlying); TypeSourceInfo *DI = CreateTypeSourceInfo(TST); - TemplateSpecializationTypeLoc TL - = cast<TemplateSpecializationTypeLoc>(DI->getTypeLoc()); + TemplateSpecializationTypeLoc TL = + DI->getTypeLoc().castAs<TemplateSpecializationTypeLoc>(); TL.setTemplateKeywordLoc(SourceLocation()); TL.setTemplateNameLoc(NameLoc); TL.setLAngleLoc(Args.getLAngleLoc()); @@ -3154,7 +3236,7 @@ ASTContext::getDependentTemplateSpecializationType( } QualType ASTContext::getPackExpansionType(QualType Pattern, - llvm::Optional<unsigned> NumExpansions) { + Optional<unsigned> NumExpansions) { llvm::FoldingSetNodeID ID; PackExpansionType::Profile(ID, Pattern, NumExpansions); @@ -3528,6 +3610,14 @@ QualType ASTContext::getUnsignedWCharType() const { return UnsignedIntTy; } +QualType ASTContext::getIntPtrType() const { + return getFromTargetType(Target->getIntPtrType()); +} + +QualType ASTContext::getUIntPtrType() const { + return getCorrespondingUnsignedType(getIntPtrType()); +} + /// getPointerDiffType - Return the unique type for "ptrdiff_t" (C99 7.17) /// defined in <stddef.h>. Pointer - pointer requires this (C99 6.5.6p9). QualType ASTContext::getPointerDiffType() const { @@ -3993,7 +4083,8 @@ ASTContext::getConstantArrayElementCount(const ConstantArrayType *CA) const { uint64_t ElementCount = 1; do { ElementCount *= CA->getSize().getZExtValue(); - CA = dyn_cast<ConstantArrayType>(CA->getElementType()); + CA = dyn_cast_or_null<ConstantArrayType>( + CA->getElementType()->getAsArrayTypeUnsafe()); } while (CA); return ElementCount; } @@ -4032,7 +4123,7 @@ QualType ASTContext::getFloatingTypeOfSizeWithinDomain(QualType Size, assert(Domain->isRealFloatingType() && "Unknown domain!"); switch (EltRank) { - case HalfRank: llvm_unreachable("Half ranks are not valid here"); + case HalfRank: return HalfTy; case FloatRank: return FloatTy; case DoubleRank: return DoubleTy; case LongDoubleRank: return LongDoubleTy; @@ -4159,8 +4250,8 @@ QualType ASTContext::getPromotedIntegerType(QualType Promotable) const { // At this point, we should have a signed or unsigned integer type. if (Promotable->isSignedIntegerType()) return IntTy; - uint64_t PromotableSize = getTypeSize(Promotable); - uint64_t IntSize = getTypeSize(IntTy); + uint64_t PromotableSize = getIntWidth(Promotable); + uint64_t IntSize = getIntWidth(IntTy); assert(Promotable->isUnsignedIntegerType() && PromotableSize <= IntSize); return (PromotableSize != IntSize) ? IntTy : UnsignedIntTy; } @@ -4273,6 +4364,16 @@ QualType ASTContext::getCFConstantStringType() const { return getTagDeclType(CFConstantStringTypeDecl); } +QualType ASTContext::getObjCSuperType() const { + if (ObjCSuperType.isNull()) { + RecordDecl *ObjCSuperTypeDecl = + CreateRecordDecl(*this, TTK_Struct, TUDecl, &Idents.get("objc_super")); + TUDecl->addDecl(ObjCSuperTypeDecl); + ObjCSuperType = getTagDeclType(ObjCSuperTypeDecl); + } + return ObjCSuperType; +} + void ASTContext::setCFConstantStringType(QualType T) { const RecordType *Rec = T->getAs<RecordType>(); assert(Rec && "Invalid CFConstantStringType"); @@ -4361,78 +4462,68 @@ QualType ASTContext::getBlockDescriptorExtendedType() const { return getTagDeclType(BlockDescriptorExtendedType); } -bool ASTContext::BlockRequiresCopying(QualType Ty) const { - if (Ty->isObjCRetainableType()) +/// BlockRequiresCopying - Returns true if byref variable "D" of type "Ty" +/// requires copy/dispose. Note that this must match the logic +/// in buildByrefHelpers. +bool ASTContext::BlockRequiresCopying(QualType Ty, + const VarDecl *D) { + if (const CXXRecordDecl *record = Ty->getAsCXXRecordDecl()) { + const Expr *copyExpr = getBlockVarCopyInits(D); + if (!copyExpr && record->hasTrivialDestructor()) return false; + return true; - if (getLangOpts().CPlusPlus) { - if (const RecordType *RT = Ty->getAs<RecordType>()) { - CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl()); - return RD->hasConstCopyConstructor(); - + } + + if (!Ty->isObjCRetainableType()) return false; + + Qualifiers qs = Ty.getQualifiers(); + + // If we have lifetime, that dominates. + if (Qualifiers::ObjCLifetime lifetime = qs.getObjCLifetime()) { + assert(getLangOpts().ObjCAutoRefCount); + + switch (lifetime) { + case Qualifiers::OCL_None: llvm_unreachable("impossible"); + + // These are just bits as far as the runtime is concerned. + case Qualifiers::OCL_ExplicitNone: + case Qualifiers::OCL_Autoreleasing: + return false; + + // Tell the runtime that this is ARC __weak, called by the + // byref routines. + case Qualifiers::OCL_Weak: + // ARC __strong __block variables need to be retained. + case Qualifiers::OCL_Strong: + return true; } + llvm_unreachable("fell out of lifetime switch!"); } - return false; + return (Ty->isBlockPointerType() || isObjCNSObjectType(Ty) || + Ty->isObjCObjectPointerType()); } -QualType -ASTContext::BuildByRefType(StringRef DeclName, QualType Ty) const { - // type = struct __Block_byref_1_X { - // void *__isa; - // struct __Block_byref_1_X *__forwarding; - // unsigned int __flags; - // unsigned int __size; - // void *__copy_helper; // as needed - // void *__destroy_help // as needed - // int X; - // } * - - bool HasCopyAndDispose = BlockRequiresCopying(Ty); - - // FIXME: Move up - SmallString<36> Name; - llvm::raw_svector_ostream(Name) << "__Block_byref_" << - ++UniqueBlockByRefTypeID << '_' << DeclName; - RecordDecl *T; - T = CreateRecordDecl(*this, TTK_Struct, TUDecl, &Idents.get(Name.str())); - T->startDefinition(); - QualType Int32Ty = IntTy; - assert(getIntWidth(IntTy) == 32 && "non-32bit int not supported"); - QualType FieldTypes[] = { - getPointerType(VoidPtrTy), - getPointerType(getTagDeclType(T)), - Int32Ty, - Int32Ty, - getPointerType(VoidPtrTy), - getPointerType(VoidPtrTy), - Ty - }; - - StringRef FieldNames[] = { - "__isa", - "__forwarding", - "__flags", - "__size", - "__copy_helper", - "__destroy_helper", - DeclName, - }; - - for (size_t i = 0; i < 7; ++i) { - if (!HasCopyAndDispose && i >=4 && i <= 5) - continue; - FieldDecl *Field = FieldDecl::Create(*this, T, SourceLocation(), - SourceLocation(), - &Idents.get(FieldNames[i]), - FieldTypes[i], /*TInfo=*/0, - /*BitWidth=*/0, /*Mutable=*/false, - ICIS_NoInit); - Field->setAccess(AS_public); - T->addDecl(Field); - } - - T->completeDefinition(); - - return getPointerType(getTagDeclType(T)); +bool ASTContext::getByrefLifetime(QualType Ty, + Qualifiers::ObjCLifetime &LifeTime, + bool &HasByrefExtendedLayout) const { + + if (!getLangOpts().ObjC1 || + getLangOpts().getGC() != LangOptions::NonGC) + return false; + + HasByrefExtendedLayout = false; + if (Ty->isRecordType()) { + HasByrefExtendedLayout = true; + LifeTime = Qualifiers::OCL_None; + } + else if (getLangOpts().ObjCAutoRefCount) + LifeTime = Ty.getObjCLifetime(); + // MRR. + else if (Ty->isObjCObjectPointerType() || Ty->isBlockPointerType()) + LifeTime = Qualifiers::OCL_ExplicitNone; + else + LifeTime = Qualifiers::OCL_None; + return true; } TypedefDecl *ASTContext::getObjCInstanceTypeDecl() { @@ -4793,17 +4884,19 @@ void ASTContext::getObjCEncodingForType(QualType T, std::string& S, true /* outermost type */); } -static char ObjCEncodingForPrimitiveKind(const ASTContext *C, QualType T) { - switch (T->getAs<BuiltinType>()->getKind()) { - default: llvm_unreachable("Unhandled builtin type kind"); +static char getObjCEncodingForPrimitiveKind(const ASTContext *C, + BuiltinType::Kind kind) { + switch (kind) { case BuiltinType::Void: return 'v'; case BuiltinType::Bool: return 'B'; case BuiltinType::Char_U: case BuiltinType::UChar: return 'C'; + case BuiltinType::Char16: case BuiltinType::UShort: return 'S'; + case BuiltinType::Char32: case BuiltinType::UInt: return 'I'; case BuiltinType::ULong: - return C->getIntWidth(T) == 32 ? 'L' : 'Q'; + return C->getTargetInfo().getLongWidth() == 32 ? 'L' : 'Q'; case BuiltinType::UInt128: return 'T'; case BuiltinType::ULongLong: return 'Q'; case BuiltinType::Char_S: @@ -4813,13 +4906,40 @@ static char ObjCEncodingForPrimitiveKind(const ASTContext *C, QualType T) { case BuiltinType::WChar_U: case BuiltinType::Int: return 'i'; case BuiltinType::Long: - return C->getIntWidth(T) == 32 ? 'l' : 'q'; + return C->getTargetInfo().getLongWidth() == 32 ? 'l' : 'q'; case BuiltinType::LongLong: return 'q'; case BuiltinType::Int128: return 't'; case BuiltinType::Float: return 'f'; case BuiltinType::Double: return 'd'; case BuiltinType::LongDouble: return 'D'; + case BuiltinType::NullPtr: return '*'; // like char* + + case BuiltinType::Half: + // FIXME: potentially need @encodes for these! + return ' '; + + case BuiltinType::ObjCId: + case BuiltinType::ObjCClass: + case BuiltinType::ObjCSel: + llvm_unreachable("@encoding ObjC primitive type"); + + // OpenCL and placeholder types don't need @encodings. + case BuiltinType::OCLImage1d: + case BuiltinType::OCLImage1dArray: + case BuiltinType::OCLImage1dBuffer: + case BuiltinType::OCLImage2d: + case BuiltinType::OCLImage2dArray: + case BuiltinType::OCLImage3d: + case BuiltinType::OCLEvent: + case BuiltinType::OCLSampler: + case BuiltinType::Dependent: +#define BUILTIN_TYPE(KIND, ID) +#define PLACEHOLDER_TYPE(KIND, ID) \ + case BuiltinType::KIND: +#include "clang/AST/BuiltinTypes.def" + llvm_unreachable("invalid builtin type for @encode"); } + llvm_unreachable("invalid BuiltinType::Kind value"); } static char ObjCEncodingForEnumType(const ASTContext *C, const EnumType *ET) { @@ -4830,7 +4950,8 @@ static char ObjCEncodingForEnumType(const ASTContext *C, const EnumType *ET) { return 'i'; // The encoding of a fixed enum type matches its fixed underlying type. - return ObjCEncodingForPrimitiveKind(C, Enum->getIntegerType()); + const BuiltinType *BT = Enum->getIntegerType()->castAs<BuiltinType>(); + return getObjCEncodingForPrimitiveKind(C, BT->getKind()); } static void EncodeBitField(const ASTContext *Ctx, std::string& S, @@ -4858,8 +4979,10 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S, S += llvm::utostr(RL.getFieldOffset(FD->getFieldIndex())); if (const EnumType *ET = T->getAs<EnumType>()) S += ObjCEncodingForEnumType(Ctx, ET); - else - S += ObjCEncodingForPrimitiveKind(Ctx, T); + else { + const BuiltinType *BT = T->castAs<BuiltinType>(); + S += getObjCEncodingForPrimitiveKind(Ctx, BT->getKind()); + } } S += llvm::utostr(FD->getBitWidthValue(*Ctx)); } @@ -4873,33 +4996,52 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, bool EncodingProperty, bool StructField, bool EncodeBlockParameters, - bool EncodeClassNames) const { - if (T->getAs<BuiltinType>()) { + bool EncodeClassNames, + bool EncodePointerToObjCTypedef) const { + CanQualType CT = getCanonicalType(T); + switch (CT->getTypeClass()) { + case Type::Builtin: + case Type::Enum: if (FD && FD->isBitField()) return EncodeBitField(this, S, T, FD); - S += ObjCEncodingForPrimitiveKind(this, T); + if (const BuiltinType *BT = dyn_cast<BuiltinType>(CT)) + S += getObjCEncodingForPrimitiveKind(this, BT->getKind()); + else + S += ObjCEncodingForEnumType(this, cast<EnumType>(CT)); return; - } - if (const ComplexType *CT = T->getAs<ComplexType>()) { + case Type::Complex: { + const ComplexType *CT = T->castAs<ComplexType>(); S += 'j'; getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, 0, false, false); return; } - - // encoding for pointer or r3eference types. - QualType PointeeTy; - if (const PointerType *PT = T->getAs<PointerType>()) { - if (PT->isObjCSelType()) { - S += ':'; - return; - } - PointeeTy = PT->getPointeeType(); + + case Type::Atomic: { + const AtomicType *AT = T->castAs<AtomicType>(); + S += 'A'; + getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, 0, + false, false); + return; } - else if (const ReferenceType *RT = T->getAs<ReferenceType>()) - PointeeTy = RT->getPointeeType(); - if (!PointeeTy.isNull()) { + + // encoding for pointer or reference types. + case Type::Pointer: + case Type::LValueReference: + case Type::RValueReference: { + QualType PointeeTy; + if (isa<PointerType>(CT)) { + const PointerType *PT = T->castAs<PointerType>(); + if (PT->isObjCSelType()) { + S += ':'; + return; + } + PointeeTy = PT->getPointeeType(); + } else { + PointeeTy = T->castAs<ReferenceType>()->getPointeeType(); + } + bool isReadOnly = false; // For historical/compatibility reasons, the read-only qualifier of the // pointee gets emitted _before_ the '^'. The read-only qualifier of @@ -4954,10 +5096,12 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, NULL); return; } - - if (const ArrayType *AT = - // Ignore type qualifiers etc. - dyn_cast<ArrayType>(T->getCanonicalTypeInternal())) { + + case Type::ConstantArray: + case Type::IncompleteArray: + case Type::VariableArray: { + const ArrayType *AT = cast<ArrayType>(CT); + if (isa<IncompleteArrayType>(AT) && !StructField) { // Incomplete arrays are encoded as a pointer to the array element. S += '^'; @@ -4986,13 +5130,13 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, return; } - if (T->getAs<FunctionType>()) { + case Type::FunctionNoProto: + case Type::FunctionProto: S += '?'; return; - } - if (const RecordType *RTy = T->getAs<RecordType>()) { - RecordDecl *RDecl = RTy->getDecl(); + case Type::Record: { + RecordDecl *RDecl = cast<RecordType>(CT)->getDecl(); S += RDecl->isUnion() ? '(' : '{'; // Anonymous structures print as '?' if (const IdentifierInfo *II = RDecl->getIdentifier()) { @@ -5000,13 +5144,11 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, if (ClassTemplateSpecializationDecl *Spec = dyn_cast<ClassTemplateSpecializationDecl>(RDecl)) { const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); - std::string TemplateArgsStr - = TemplateSpecializationType::PrintTemplateArgumentList( + llvm::raw_string_ostream OS(S); + TemplateSpecializationType::PrintTemplateArgumentList(OS, TemplateArgs.data(), TemplateArgs.size(), (*this).getPrintingPolicy()); - - S += TemplateArgsStr; } } else { S += '?'; @@ -5043,19 +5185,12 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, S += RDecl->isUnion() ? ')' : '}'; return; } - - if (const EnumType *ET = T->getAs<EnumType>()) { - if (FD && FD->isBitField()) - EncodeBitField(this, S, T, FD); - else - S += ObjCEncodingForEnumType(this, ET); - return; - } - if (const BlockPointerType *BT = T->getAs<BlockPointerType>()) { + case Type::BlockPointer: { + const BlockPointerType *BT = T->castAs<BlockPointerType>(); S += "@?"; // Unlike a pointer-to-function, which is "^?". if (EncodeBlockParameters) { - const FunctionType *FT = BT->getPointeeType()->getAs<FunctionType>(); + const FunctionType *FT = BT->getPointeeType()->castAs<FunctionType>(); S += '<'; // Block return type @@ -5089,11 +5224,14 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, return; } - // Ignore protocol qualifiers when mangling at this level. - if (const ObjCObjectType *OT = T->getAs<ObjCObjectType>()) - T = OT->getBaseType(); + case Type::ObjCObject: + case Type::ObjCInterface: { + // Ignore protocol qualifiers when mangling at this level. + T = T->castAs<ObjCObjectType>()->getBaseType(); - if (const ObjCInterfaceType *OIT = T->getAs<ObjCInterfaceType>()) { + // The assumption seems to be that this assert will succeed + // because nested levels will have filtered out 'id' and 'Class'. + const ObjCInterfaceType *OIT = T->castAs<ObjCInterfaceType>(); // @encode(class_name) ObjCInterfaceDecl *OI = OIT->getDecl(); S += '{'; @@ -5107,13 +5245,16 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, if (Field->isBitField()) getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field); else - getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD); + getObjCEncodingForTypeImpl(Field->getType(), S, false, true, FD, + false, false, false, false, false, + EncodePointerToObjCTypedef); } S += '}'; return; } - if (const ObjCObjectPointerType *OPT = T->getAs<ObjCObjectPointerType>()) { + case Type::ObjCObjectPointer: { + const ObjCObjectPointerType *OPT = T->castAs<ObjCObjectPointerType>(); if (OPT->isObjCIdType()) { S += '@'; return; @@ -5148,14 +5289,17 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, QualType PointeeTy = OPT->getPointeeType(); if (!EncodingProperty && - isa<TypedefType>(PointeeTy.getTypePtr())) { + isa<TypedefType>(PointeeTy.getTypePtr()) && + !EncodePointerToObjCTypedef) { // Another historical/compatibility reason. // We encode the underlying type which comes out as // {...}; S += '^'; getObjCEncodingForTypeImpl(PointeeTy, S, false, ExpandPointedToStructures, - NULL); + NULL, + false, false, false, false, false, + /*EncodePointerToObjCTypedef*/true); return; } @@ -5176,18 +5320,29 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, } // gcc just blithely ignores member pointers. - // TODO: maybe there should be a mangling for these - if (T->getAs<MemberPointerType>()) + // FIXME: we shoul do better than that. 'M' is available. + case Type::MemberPointer: return; - if (T->isVectorType()) { + case Type::Vector: + case Type::ExtVector: // This matches gcc's encoding, even though technically it is // insufficient. // FIXME. We should do a better job than gcc. return; + +#define ABSTRACT_TYPE(KIND, BASE) +#define TYPE(KIND, BASE) +#define DEPENDENT_TYPE(KIND, BASE) \ + case Type::KIND: +#define NON_CANONICAL_TYPE(KIND, BASE) \ + case Type::KIND: +#define NON_CANONICAL_UNLESS_DEPENDENT_TYPE(KIND, BASE) \ + case Type::KIND: +#include "clang/AST/TypeNodes.def" + llvm_unreachable("@encode for dependent type!"); } - - llvm_unreachable("@encode for type not implemented!"); + llvm_unreachable("bad type kind!"); } void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, @@ -5426,6 +5581,85 @@ static TypedefDecl *CreateVoidPtrBuiltinVaListDecl(const ASTContext *Context) { return VaListTypeDecl; } +static TypedefDecl * +CreateAArch64ABIBuiltinVaListDecl(const ASTContext *Context) { + RecordDecl *VaListTagDecl; + if (Context->getLangOpts().CPlusPlus) { + // namespace std { struct __va_list { + NamespaceDecl *NS; + NS = NamespaceDecl::Create(const_cast<ASTContext &>(*Context), + Context->getTranslationUnitDecl(), + /*Inline*/false, SourceLocation(), + SourceLocation(), &Context->Idents.get("std"), + /*PrevDecl*/0); + + VaListTagDecl = CXXRecordDecl::Create(*Context, TTK_Struct, + Context->getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), + &Context->Idents.get("__va_list")); + VaListTagDecl->setDeclContext(NS); + } else { + // struct __va_list + VaListTagDecl = CreateRecordDecl(*Context, TTK_Struct, + Context->getTranslationUnitDecl(), + &Context->Idents.get("__va_list")); + } + + VaListTagDecl->startDefinition(); + + const size_t NumFields = 5; + QualType FieldTypes[NumFields]; + const char *FieldNames[NumFields]; + + // void *__stack; + FieldTypes[0] = Context->getPointerType(Context->VoidTy); + FieldNames[0] = "__stack"; + + // void *__gr_top; + FieldTypes[1] = Context->getPointerType(Context->VoidTy); + FieldNames[1] = "__gr_top"; + + // void *__vr_top; + FieldTypes[2] = Context->getPointerType(Context->VoidTy); + FieldNames[2] = "__vr_top"; + + // int __gr_offs; + FieldTypes[3] = Context->IntTy; + FieldNames[3] = "__gr_offs"; + + // int __vr_offs; + FieldTypes[4] = Context->IntTy; + FieldNames[4] = "__vr_offs"; + + // Create fields + for (unsigned i = 0; i < NumFields; ++i) { + FieldDecl *Field = FieldDecl::Create(const_cast<ASTContext &>(*Context), + VaListTagDecl, + SourceLocation(), + SourceLocation(), + &Context->Idents.get(FieldNames[i]), + FieldTypes[i], /*TInfo=*/0, + /*BitWidth=*/0, + /*Mutable=*/false, + ICIS_NoInit); + Field->setAccess(AS_public); + VaListTagDecl->addDecl(Field); + } + VaListTagDecl->completeDefinition(); + QualType VaListTagType = Context->getRecordType(VaListTagDecl); + Context->VaListTagTy = VaListTagType; + + // } __builtin_va_list; + TypedefDecl *VaListTypedefDecl + = TypedefDecl::Create(const_cast<ASTContext &>(*Context), + Context->getTranslationUnitDecl(), + SourceLocation(), SourceLocation(), + &Context->Idents.get("__builtin_va_list"), + Context->getTrivialTypeSourceInfo(VaListTagType)); + + return VaListTypedefDecl; +} + static TypedefDecl *CreatePowerABIBuiltinVaListDecl(const ASTContext *Context) { // typedef struct __va_list_tag { RecordDecl *VaListTagDecl; @@ -5659,6 +5893,8 @@ static TypedefDecl *CreateVaListDecl(const ASTContext *Context, return CreateCharPtrBuiltinVaListDecl(Context); case TargetInfo::VoidPtrBuiltinVaList: return CreateVoidPtrBuiltinVaListDecl(Context); + case TargetInfo::AArch64ABIBuiltinVaList: + return CreateAArch64ABIBuiltinVaListDecl(Context); case TargetInfo::PowerABIBuiltinVaList: return CreatePowerABIBuiltinVaListDecl(Context); case TargetInfo::X86_64ABIBuiltinVaList: @@ -6496,14 +6732,14 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, if (lbaseInfo.getProducesResult() != rbaseInfo.getProducesResult()) return QualType(); - // functypes which return are preferred over those that do not. - if (lbaseInfo.getNoReturn() && !rbaseInfo.getNoReturn()) - allLTypes = false; - else if (!lbaseInfo.getNoReturn() && rbaseInfo.getNoReturn()) - allRTypes = false; // FIXME: some uses, e.g. conditional exprs, really want this to be 'both'. bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn(); + if (lbaseInfo.getNoReturn() != NoReturn) + allLTypes = false; + if (rbaseInfo.getNoReturn() != NoReturn) + allRTypes = false; + FunctionType::ExtInfo einfo = lbaseInfo.withNoReturn(NoReturn); if (lproto && rproto) { // two C99 style function prototypes @@ -6557,7 +6793,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, FunctionProtoType::ExtProtoInfo EPI = lproto->getExtProtoInfo(); EPI.ExtInfo = einfo; - return getFunctionType(retType, types.begin(), types.size(), EPI); + return getFunctionType(retType, types, EPI); } if (lproto) allRTypes = false; @@ -6594,8 +6830,10 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, FunctionProtoType::ExtProtoInfo EPI = proto->getExtProtoInfo(); EPI.ExtInfo = einfo; - return getFunctionType(retType, proto->arg_type_begin(), - proto->getNumArgs(), EPI); + return getFunctionType(retType, + ArrayRef<QualType>(proto->arg_type_begin(), + proto->getNumArgs()), + EPI); } if (allLTypes) return lhs; @@ -6603,6 +6841,27 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, return getFunctionNoProtoType(retType, einfo); } +/// Given that we have an enum type and a non-enum type, try to merge them. +static QualType mergeEnumWithInteger(ASTContext &Context, const EnumType *ET, + QualType other, bool isBlockReturnType) { + // C99 6.7.2.2p4: Each enumerated type shall be compatible with char, + // a signed integer type, or an unsigned integer type. + // Compatibility is based on the underlying type, not the promotion + // type. + QualType underlyingType = ET->getDecl()->getIntegerType(); + if (underlyingType.isNull()) return QualType(); + if (Context.hasSameType(underlyingType, other)) + return other; + + // In block return types, we're more permissive and accept any + // integral type of the same size. + if (isBlockReturnType && other->isIntegerType() && + Context.getTypeSize(underlyingType) == Context.getTypeSize(other)) + return other; + + return QualType(); +} + QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, bool OfBlockPointer, bool Unqualified, bool BlockReturnType) { @@ -6684,19 +6943,13 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, // If the canonical type classes don't match. if (LHSClass != RHSClass) { - // C99 6.7.2.2p4: Each enumerated type shall be compatible with char, - // a signed integer type, or an unsigned integer type. - // Compatibility is based on the underlying type, not the promotion - // type. + // Note that we only have special rules for turning block enum + // returns into block int returns, not vice-versa. if (const EnumType* ETy = LHS->getAs<EnumType>()) { - QualType TINT = ETy->getDecl()->getIntegerType(); - if (!TINT.isNull() && hasSameType(TINT, RHSCan.getUnqualifiedType())) - return RHS; + return mergeEnumWithInteger(*this, ETy, RHS, false); } if (const EnumType* ETy = RHS->getAs<EnumType>()) { - QualType TINT = ETy->getDecl()->getIntegerType(); - if (!TINT.isNull() && hasSameType(TINT, LHSCan.getUnqualifiedType())) - return LHS; + return mergeEnumWithInteger(*this, ETy, LHS, BlockReturnType); } // allow block pointer type to match an 'id' type. if (OfBlockPointer && !BlockReturnType) { @@ -6928,8 +7181,10 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.ExtInfo = getFunctionExtInfo(LHS); QualType ResultType - = getFunctionType(OldReturnType, FPT->arg_type_begin(), - FPT->getNumArgs(), EPI); + = getFunctionType(OldReturnType, + ArrayRef<QualType>(FPT->arg_type_begin(), + FPT->getNumArgs()), + EPI); return ResultType; } } @@ -7137,6 +7392,9 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, case 'H': Type = Context.getObjCSelType(); break; + case 'M': + Type = Context.getObjCSuperType(); + break; case 'a': Type = Context.getBuiltinVaListType(); assert(!Type.isNull() && "builtin va list type not initialized!"); @@ -7318,7 +7576,7 @@ QualType ASTContext::GetBuiltinType(unsigned Id, EPI.ExtInfo = EI; EPI.Variadic = Variadic; - return getFunctionType(ResType, ArgTypes.data(), ArgTypes.size(), EPI); + return getFunctionType(ResType, ArgTypes, EPI); } GVALinkage ASTContext::GetGVALinkageForFunction(const FunctionDecl *FD) { @@ -7383,9 +7641,6 @@ GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) { TSK = VD->getTemplateSpecializationKind(); Linkage L = VD->getLinkage(); - if (L == ExternalLinkage && getLangOpts().CPlusPlus && - VD->getType()->getLinkage() == UniqueExternalLinkage) - L = UniqueExternalLinkage; switch (L) { case NoLinkage: @@ -7418,7 +7673,15 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { if (!VD->isFileVarDecl()) return false; - } else if (!isa<FunctionDecl>(D)) + } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + // We never need to emit an uninstantiated function template. + if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate) + return false; + } else + return false; + + // If this is a member of a class template, we do not need to emit it. + if (D->getDeclContext()->isDependentContext()) return false; // Weak references don't produce any output by themselves. @@ -7438,13 +7701,16 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>()) return true; - // The key function for a class is required. - if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { - const CXXRecordDecl *RD = MD->getParent(); - if (MD->isOutOfLine() && RD->isDynamicClass()) { - const CXXMethodDecl *KeyFunc = getKeyFunction(RD); - if (KeyFunc && KeyFunc->getCanonicalDecl() == MD->getCanonicalDecl()) - return true; + // The key function for a class is required. This rule only comes + // into play when inline functions can be key functions, though. + if (getTargetInfo().getCXXABI().canKeyFunctionBeInline()) { + if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) { + const CXXRecordDecl *RD = MD->getParent(); + if (MD->isOutOfLine() && RD->isDynamicClass()) { + const CXXMethodDecl *KeyFunc = getCurrentKeyFunction(RD); + if (KeyFunc && KeyFunc->getCanonicalDecl() == MD->getCanonicalDecl()) + return true; + } } } @@ -7465,27 +7731,20 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly) return false; - // Structs that have non-trivial constructors or destructors are required. + // Variables that can be needed in other TUs are required. + GVALinkage L = GetGVALinkageForVariable(VD); + if (L != GVA_Internal && L != GVA_TemplateInstantiation) + return true; - // FIXME: Handle references. - // FIXME: Be more selective about which constructors we care about. - if (const RecordType *RT = VD->getType()->getAs<RecordType>()) { - if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl())) { - if (RD->hasDefinition() && !(RD->hasTrivialDefaultConstructor() && - RD->hasTrivialCopyConstructor() && - RD->hasTrivialMoveConstructor() && - RD->hasTrivialDestructor())) - return true; - } - } + // Variables that have destruction with side-effects are required. + if (VD->getType().isDestructedType()) + return true; - GVALinkage L = GetGVALinkageForVariable(VD); - if (L == GVA_Internal || L == GVA_TemplateInstantiation) { - if (!(VD->getInit() && VD->getInit()->HasSideEffects(*this))) - return false; - } + // Variables that have initialization with side-effects are required. + if (VD->getInit() && VD->getInit()->HasSideEffects(*this)) + return true; - return true; + return false; } CallingConv ASTContext::getDefaultCXXMethodCallConv(bool isVariadic) { @@ -7494,7 +7753,8 @@ CallingConv ASTContext::getDefaultCXXMethodCallConv(bool isVariadic) { } CallingConv ASTContext::getCanonicalCallConv(CallingConv CC) const { - if (CC == CC_C && !LangOpts.MRTD && getTargetInfo().getCXXABI() != CXXABI_Microsoft) + if (CC == CC_C && !LangOpts.MRTD && + getTargetInfo().getCXXABI().isMemberFunctionCCDefault()) return CC_Default; return CC; } @@ -7505,11 +7765,13 @@ bool ASTContext::isNearlyEmpty(const CXXRecordDecl *RD) const { } MangleContext *ASTContext::createMangleContext() { - switch (Target->getCXXABI()) { - case CXXABI_ARM: - case CXXABI_Itanium: + switch (Target->getCXXABI().getKind()) { + case TargetCXXABI::GenericAArch64: + case TargetCXXABI::GenericItanium: + case TargetCXXABI::GenericARM: + case TargetCXXABI::iOS: return createItaniumMangleContext(*this, getDiagnostics()); - case CXXABI_Microsoft: + case TargetCXXABI::Microsoft: return createMicrosoftMangleContext(*this, getDiagnostics()); } llvm_unreachable("Unsupported ABI"); @@ -7534,6 +7796,23 @@ size_t ASTContext::getSideTableAllocatedMemory() const { + llvm::capacity_in_bytes(ClassScopeSpecializationPattern); } +void ASTContext::addUnnamedTag(const TagDecl *Tag) { + // FIXME: This mangling should be applied to function local classes too + if (!Tag->getName().empty() || Tag->getTypedefNameForAnonDecl() || + !isa<CXXRecordDecl>(Tag->getParent()) || Tag->getLinkage() != ExternalLinkage) + return; + + std::pair<llvm::DenseMap<const DeclContext *, unsigned>::iterator, bool> P = + UnnamedMangleContexts.insert(std::make_pair(Tag->getParent(), 0)); + UnnamedMangleNumbers.insert(std::make_pair(Tag, P.first->second++)); +} + +int ASTContext::getUnnamedTagManglingNumber(const TagDecl *Tag) const { + llvm::DenseMap<const TagDecl *, unsigned>::const_iterator I = + UnnamedMangleNumbers.find(Tag); + return I != UnnamedMangleNumbers.end() ? I->second : -1; +} + unsigned ASTContext::getLambdaManglingNumber(CXXMethodDecl *CallOperator) { CXXRecordDecl *Lambda = CallOperator->getParent(); return LambdaMangleContexts[Lambda->getDeclContext()] |