diff options
Diffstat (limited to 'lib/AST/ASTContext.cpp')
-rw-r--r-- | lib/AST/ASTContext.cpp | 1307 |
1 files changed, 883 insertions, 424 deletions
diff --git a/lib/AST/ASTContext.cpp b/lib/AST/ASTContext.cpp index 3dc961d4f12b..25dc4441aafd 100644 --- a/lib/AST/ASTContext.cpp +++ b/lib/AST/ASTContext.cpp @@ -47,6 +47,7 @@ #include "clang/Basic/AddressSpaces.h" #include "clang/Basic/Builtins.h" #include "clang/Basic/CommentOptions.h" +#include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" #include "clang/Basic/LangOptions.h" @@ -130,35 +131,34 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { return nullptr; // User can not attach documentation to implicit instantiations. - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + if (const auto *FD = dyn_cast<FunctionDecl>(D)) { if (FD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) return nullptr; } - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (const auto *VD = dyn_cast<VarDecl>(D)) { if (VD->isStaticDataMember() && VD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) return nullptr; } - if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) { + if (const auto *CRD = dyn_cast<CXXRecordDecl>(D)) { if (CRD->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) return nullptr; } - if (const ClassTemplateSpecializationDecl *CTSD = - dyn_cast<ClassTemplateSpecializationDecl>(D)) { + if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D)) { TemplateSpecializationKind TSK = CTSD->getSpecializationKind(); if (TSK == TSK_ImplicitInstantiation || TSK == TSK_Undeclared) return nullptr; } - if (const EnumDecl *ED = dyn_cast<EnumDecl>(D)) { + if (const auto *ED = dyn_cast<EnumDecl>(D)) { if (ED->getTemplateSpecializationKind() == TSK_ImplicitInstantiation) return nullptr; } - if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { + if (const auto *TD = dyn_cast<TagDecl>(D)) { // When tag declaration (but not definition!) is part of the // decl-specifier-seq of some other declaration, it doesn't get comment if (TD->isEmbeddedInDeclarator() && !TD->isCompleteDefinition()) @@ -201,7 +201,7 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { // declared via a macro. Try using declaration's starting location as // the "declaration location". DeclLoc = D->getLocStart(); - } else if (const TagDecl *TD = dyn_cast<TagDecl>(D)) { + } else if (const auto *TD = dyn_cast<TagDecl>(D)) { // If location of the tag decl is inside a macro, but the spelling of // the tag name comes from a macro argument, it looks like a special // macro like NS_ENUM is being used to define the tag decl. In that @@ -226,8 +226,7 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { // for is usually among the last two comments we parsed -- check them // first. RawComment CommentAtDeclLoc( - SourceMgr, SourceRange(DeclLoc), false, - LangOpts.CommentOpts.ParseAllComments); + SourceMgr, SourceRange(DeclLoc), LangOpts.CommentOpts, false); BeforeThanCompare<RawComment> Compare(SourceMgr); ArrayRef<RawComment *>::iterator MaybeBeforeDecl = RawComments.end() - 1; bool Found = Compare(*MaybeBeforeDecl, &CommentAtDeclLoc); @@ -253,7 +252,8 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { // First check whether we have a trailing comment. if (Comment != RawComments.end() && - (*Comment)->isDocumentation() && (*Comment)->isTrailingComment() && + ((*Comment)->isDocumentation() || LangOpts.CommentOpts.ParseAllComments) + && (*Comment)->isTrailingComment() && (isa<FieldDecl>(D) || isa<EnumConstantDecl>(D) || isa<VarDecl>(D) || isa<ObjCMethodDecl>(D) || isa<ObjCPropertyDecl>(D))) { std::pair<FileID, unsigned> CommentBeginDecomp @@ -275,7 +275,9 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { --Comment; // Check that we actually have a non-member Doxygen comment. - if (!(*Comment)->isDocumentation() || (*Comment)->isTrailingComment()) + if (!((*Comment)->isDocumentation() || + LangOpts.CommentOpts.ParseAllComments) || + (*Comment)->isTrailingComment()) return nullptr; // Decompose the end of the comment. @@ -310,7 +312,7 @@ RawComment *ASTContext::getRawCommentForDeclNoCache(const Decl *D) const { /// refer to the actual template. /// If we have an implicit instantiation, adjust 'D' to refer to template. static const Decl *adjustDeclToTemplate(const Decl *D) { - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + if (const auto *FD = dyn_cast<FunctionDecl>(D)) { // Is this function declaration part of a function template? if (const FunctionTemplateDecl *FTD = FD->getDescribedFunctionTemplate()) return FTD; @@ -330,7 +332,7 @@ static const Decl *adjustDeclToTemplate(const Decl *D) { return D; } - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (const auto *VD = dyn_cast<VarDecl>(D)) { // Static data member is instantiated from a member definition of a class // template? if (VD->isStaticDataMember()) @@ -339,15 +341,14 @@ static const Decl *adjustDeclToTemplate(const Decl *D) { return D; } - if (const CXXRecordDecl *CRD = dyn_cast<CXXRecordDecl>(D)) { + if (const auto *CRD = dyn_cast<CXXRecordDecl>(D)) { // Is this class declaration part of a class template? if (const ClassTemplateDecl *CTD = CRD->getDescribedClassTemplate()) return CTD; // Class is an implicit instantiation of a class template or partial // specialization? - if (const ClassTemplateSpecializationDecl *CTSD = - dyn_cast<ClassTemplateSpecializationDecl>(CRD)) { + if (const auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(CRD)) { if (CTSD->getSpecializationKind() != TSK_ImplicitInstantiation) return D; llvm::PointerUnion<ClassTemplateDecl *, @@ -366,7 +367,7 @@ static const Decl *adjustDeclToTemplate(const Decl *D) { return D; } - if (const EnumDecl *ED = dyn_cast<EnumDecl>(D)) { + if (const auto *ED = dyn_cast<EnumDecl>(D)) { // Enum is instantiated from a member definition of a class template? if (const EnumDecl *MemberDecl = ED->getInstantiatedFromMemberEnum()) return MemberDecl; @@ -428,7 +429,7 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl( } // If we found a comment, it should be a documentation comment. - assert(!RC || RC->isDocumentation()); + assert(!RC || RC->isDocumentation() || LangOpts.CommentOpts.ParseAllComments); if (OriginalDecl) *OriginalDecl = OriginalDeclForRC; @@ -451,7 +452,7 @@ const RawComment *ASTContext::getRawCommentForAnyRedecl( static void addRedeclaredMethods(const ObjCMethodDecl *ObjCMethod, SmallVectorImpl<const NamedDecl *> &Redeclared) { const DeclContext *DC = ObjCMethod->getDeclContext(); - if (const ObjCImplDecl *IMD = dyn_cast<ObjCImplDecl>(DC)) { + if (const auto *IMD = dyn_cast<ObjCImplDecl>(DC)) { const ObjCInterfaceDecl *ID = IMD->getClassInterface(); if (!ID) return; @@ -467,7 +468,7 @@ static void addRedeclaredMethods(const ObjCMethodDecl *ObjCMethod, comments::FullComment *ASTContext::cloneFullComment(comments::FullComment *FC, const Decl *D) const { - comments::DeclInfo *ThisDeclInfo = new (*this) comments::DeclInfo; + auto *ThisDeclInfo = new (*this) comments::DeclInfo; ThisDeclInfo->CommentDecl = D; ThisDeclInfo->IsFilled = false; ThisDeclInfo->fill(); @@ -511,7 +512,7 @@ comments::FullComment *ASTContext::getCommentForDecl( if (!RC) { if (isa<ObjCMethodDecl>(D) || isa<FunctionDecl>(D)) { SmallVector<const NamedDecl*, 8> Overridden; - const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D); + const auto *OMD = dyn_cast<ObjCMethodDecl>(D); if (OMD && OMD->isPropertyAccessor()) if (const ObjCPropertyDecl *PDecl = OMD->findPropertyDecl()) if (comments::FullComment *FC = getCommentForDecl(PDecl, PP)) @@ -523,28 +524,28 @@ comments::FullComment *ASTContext::getCommentForDecl( if (comments::FullComment *FC = getCommentForDecl(Overridden[i], PP)) return cloneFullComment(FC, D); } - else if (const TypedefNameDecl *TD = dyn_cast<TypedefNameDecl>(D)) { + else if (const auto *TD = dyn_cast<TypedefNameDecl>(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 auto *TT = QT->getAs<TagType>()) if (const Decl *TD = TT->getDecl()) if (comments::FullComment *FC = getCommentForDecl(TD, PP)) return cloneFullComment(FC, D); } - else if (const ObjCInterfaceDecl *IC = dyn_cast<ObjCInterfaceDecl>(D)) { + else if (const auto *IC = dyn_cast<ObjCInterfaceDecl>(D)) { while (IC->getSuperClass()) { IC = IC->getSuperClass(); if (comments::FullComment *FC = getCommentForDecl(IC, PP)) return cloneFullComment(FC, D); } } - else if (const ObjCCategoryDecl *CD = dyn_cast<ObjCCategoryDecl>(D)) { + else if (const auto *CD = dyn_cast<ObjCCategoryDecl>(D)) { if (const ObjCInterfaceDecl *IC = CD->getClassInterface()) if (comments::FullComment *FC = getCommentForDecl(IC, PP)) return cloneFullComment(FC, D); } - else if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(D)) { + else if (const auto *RD = dyn_cast<CXXRecordDecl>(D)) { if (!(RD = RD->getDefinition())) return nullptr; // Check non-virtual bases. @@ -604,13 +605,13 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID, for (TemplateParameterList::const_iterator P = Params->begin(), PEnd = Params->end(); P != PEnd; ++P) { - if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) { + if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) { ID.AddInteger(0); ID.AddBoolean(TTP->isParameterPack()); continue; } - if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { + if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { ID.AddInteger(1); ID.AddBoolean(NTTP->isParameterPack()); ID.AddPointer(NTTP->getType().getCanonicalType().getAsOpaquePtr()); @@ -626,7 +627,7 @@ ASTContext::CanonicalTemplateTemplateParm::Profile(llvm::FoldingSetNodeID &ID, continue; } - TemplateTemplateParmDecl *TTP = cast<TemplateTemplateParmDecl>(*P); + auto *TTP = cast<TemplateTemplateParmDecl>(*P); ID.AddInteger(2); Profile(ID, TTP); } @@ -651,7 +652,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( for (TemplateParameterList::const_iterator P = Params->begin(), PEnd = Params->end(); P != PEnd; ++P) { - if (TemplateTypeParmDecl *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) + if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(*P)) CanonParams.push_back( TemplateTypeParmDecl::Create(*this, getTranslationUnitDecl(), SourceLocation(), @@ -659,8 +660,7 @@ ASTContext::getCanonicalTemplateTemplateParmDecl( TTP->getDepth(), TTP->getIndex(), nullptr, false, TTP->isParameterPack())); - else if (NonTypeTemplateParmDecl *NTTP - = dyn_cast<NonTypeTemplateParmDecl>(*P)) { + else if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P)) { QualType T = getCanonicalType(NTTP->getType()); TypeSourceInfo *TInfo = getTrivialTypeSourceInfo(T); NonTypeTemplateParmDecl *Param; @@ -788,10 +788,12 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager &SM, SubstTemplateTemplateParmPacks(this_()), SourceMgr(SM), LangOpts(LOpts), SanitizerBL(new SanitizerBlacklist(LangOpts.SanitizerBlacklistFiles, SM)), XRayFilter(new XRayFunctionFilter(LangOpts.XRayAlwaysInstrumentFiles, - LangOpts.XRayNeverInstrumentFiles, SM)), + LangOpts.XRayNeverInstrumentFiles, + LangOpts.XRayAttrListFiles, SM)), PrintingPolicy(LOpts), Idents(idents), Selectors(sels), BuiltinInfo(builtins), DeclarationNames(*this), Comments(SM), - CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), LastSDM(nullptr, 0) { + CommentCommandTraits(BumpAlloc, LOpts.CommentOpts), + CompCategories(this_()), LastSDM(nullptr, 0) { TUDecl = TranslationUnitDecl::Create(*this); } @@ -812,13 +814,13 @@ ASTContext::~ASTContext() { const ASTRecordLayout*>::iterator I = ObjCLayouts.begin(), E = ObjCLayouts.end(); I != E; ) // Increment in loop to prevent using deallocated memory. - if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second)) + if (auto *R = const_cast<ASTRecordLayout *>((I++)->second)) R->Destroy(*this); for (llvm::DenseMap<const RecordDecl*, const ASTRecordLayout*>::iterator I = ASTRecordLayouts.begin(), E = ASTRecordLayouts.end(); I != E; ) { // Increment in loop to prevent using deallocated memory. - if (ASTRecordLayout *R = const_cast<ASTRecordLayout*>((I++)->second)) + if (auto *R = const_cast<ASTRecordLayout *>((I++)->second)) R->Destroy(*this); } @@ -966,7 +968,7 @@ void ASTContext::PerModuleInitializers::resolve(ASTContext &Ctx) { void ASTContext::addModuleInitializer(Module *M, Decl *D) { // One special case: if we add a module initializer that imports another // module, and that module's only initializer is an ImportDecl, simplify. - if (auto *ID = dyn_cast<ImportDecl>(D)) { + if (const auto *ID = dyn_cast<ImportDecl>(D)) { auto It = ModuleInitializers.find(ID->getImportedModule()); // Maybe the ImportDecl does nothing at all. (Common case.) @@ -997,7 +999,7 @@ void ASTContext::addLazyModuleInitializers(Module *M, ArrayRef<uint32_t> IDs) { IDs.begin(), IDs.end()); } -ArrayRef<Decl*> ASTContext::getModuleInitializers(Module *M) { +ArrayRef<Decl *> ASTContext::getModuleInitializers(Module *M) { auto It = ModuleInitializers.find(M); if (It == ModuleInitializers.end()) return None; @@ -1079,7 +1081,7 @@ TypedefDecl *ASTContext::getUInt128Decl() const { } void ASTContext::InitBuiltinType(CanQualType &R, BuiltinType::Kind K) { - BuiltinType *Ty = new (*this, TypeAlignment) BuiltinType(K); + auto *Ty = new (*this, TypeAlignment) BuiltinType(K); R = CanQualType::CreateUnsafe(QualType(Ty, 0)); Types.push_back(Ty); } @@ -1132,6 +1134,32 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target, // C11 extension ISO/IEC TS 18661-3 InitBuiltinType(Float16Ty, BuiltinType::Float16); + // ISO/IEC JTC1 SC22 WG14 N1169 Extension + InitBuiltinType(ShortAccumTy, BuiltinType::ShortAccum); + InitBuiltinType(AccumTy, BuiltinType::Accum); + InitBuiltinType(LongAccumTy, BuiltinType::LongAccum); + InitBuiltinType(UnsignedShortAccumTy, BuiltinType::UShortAccum); + InitBuiltinType(UnsignedAccumTy, BuiltinType::UAccum); + InitBuiltinType(UnsignedLongAccumTy, BuiltinType::ULongAccum); + InitBuiltinType(ShortFractTy, BuiltinType::ShortFract); + InitBuiltinType(FractTy, BuiltinType::Fract); + InitBuiltinType(LongFractTy, BuiltinType::LongFract); + InitBuiltinType(UnsignedShortFractTy, BuiltinType::UShortFract); + InitBuiltinType(UnsignedFractTy, BuiltinType::UFract); + InitBuiltinType(UnsignedLongFractTy, BuiltinType::ULongFract); + InitBuiltinType(SatShortAccumTy, BuiltinType::SatShortAccum); + InitBuiltinType(SatAccumTy, BuiltinType::SatAccum); + InitBuiltinType(SatLongAccumTy, BuiltinType::SatLongAccum); + InitBuiltinType(SatUnsignedShortAccumTy, BuiltinType::SatUShortAccum); + InitBuiltinType(SatUnsignedAccumTy, BuiltinType::SatUAccum); + InitBuiltinType(SatUnsignedLongAccumTy, BuiltinType::SatULongAccum); + InitBuiltinType(SatShortFractTy, BuiltinType::SatShortFract); + InitBuiltinType(SatFractTy, BuiltinType::SatFract); + InitBuiltinType(SatLongFractTy, BuiltinType::SatLongFract); + InitBuiltinType(SatUnsignedShortFractTy, BuiltinType::SatUShortFract); + InitBuiltinType(SatUnsignedFractTy, BuiltinType::SatUFract); + InitBuiltinType(SatUnsignedLongFractTy, BuiltinType::SatULongFract); + // GNU extension, 128-bit integers. InitBuiltinType(Int128Ty, BuiltinType::Int128); InitBuiltinType(UnsignedInt128Ty, BuiltinType::UInt128); @@ -1150,6 +1178,9 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target, WIntTy = getFromTargetType(Target.getWIntType()); + // C++20 (proposed) + InitBuiltinType(Char8Ty, BuiltinType::Char8); + if (LangOpts.CPlusPlus) // C++0x 3.9.1p5, extension for C++ InitBuiltinType(Char16Ty, BuiltinType::Char16); else // C99 @@ -1254,7 +1285,7 @@ AttrVec& ASTContext::getDeclAttrs(const Decl *D) { return *Result; } -/// \brief Erase the attributes corresponding to the given declaration. +/// Erase the attributes corresponding to the given declaration. void ASTContext::eraseDeclAttrs(const Decl *D) { llvm::DenseMap<const Decl*, AttrVec*>::iterator Pos = DeclAttrs.find(D); if (Pos != DeclAttrs.end()) { @@ -1276,7 +1307,7 @@ ASTContext::getTemplateOrSpecializationInfo(const VarDecl *Var) { llvm::DenseMap<const VarDecl *, TemplateOrSpecializationInfo>::iterator Pos = TemplateOrInstantiation.find(Var); if (Pos == TemplateOrInstantiation.end()) - return TemplateOrSpecializationInfo(); + return {}; return Pos->second; } @@ -1412,13 +1443,13 @@ void ASTContext::getOverriddenMethods( SmallVectorImpl<const NamedDecl *> &Overridden) const { assert(D); - if (const CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) { + if (const auto *CXXMethod = dyn_cast<CXXMethodDecl>(D)) { Overridden.append(overridden_methods_begin(CXXMethod), overridden_methods_end(CXXMethod)); return; } - const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D); + const auto *Method = dyn_cast<ObjCMethodDecl>(D); if (!Method) return; @@ -1447,7 +1478,7 @@ void ASTContext::addedLocalImportDecl(ImportDecl *Import) { /// getFloatTypeSemantics - Return the APFloat 'semantics' for the specified /// scalar floating point type. const llvm::fltSemantics &ASTContext::getFloatTypeSemantics(QualType T) const { - const BuiltinType *BT = T->getAs<BuiltinType>(); + const auto *BT = T->getAs<BuiltinType>(); assert(BT && "Not a floating point type!"); switch (BT->getKind()) { default: llvm_unreachable("Not a floating point type!"); @@ -1490,9 +1521,9 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { // else about the declaration and its type. if (UseAlignAttrOnly) { // do nothing - } else if (const ValueDecl *VD = dyn_cast<ValueDecl>(D)) { + } else if (const auto *VD = dyn_cast<ValueDecl>(D)) { QualType T = VD->getType(); - if (const ReferenceType *RT = T->getAs<ReferenceType>()) { + if (const auto *RT = T->getAs<ReferenceType>()) { if (ForAlignof) T = RT->getPointeeType(); else @@ -1517,7 +1548,7 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { Align = std::max(Align, getPreferredTypeAlign(T.getTypePtr())); if (BaseT.getQualifiers().hasUnaligned()) Align = Target->getCharWidth(); - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (const auto *VD = dyn_cast<VarDecl>(D)) { if (VD->hasGlobalStorage() && !ForAlignof) Align = std::max(Align, getTargetInfo().getMinGlobalAlign()); } @@ -1528,7 +1559,7 @@ CharUnits ASTContext::getDeclAlign(const Decl *D, bool ForAlignof) const { // a max-field-alignment constraint (#pragma pack). So calculate // the actual alignment of the field within the struct, and then // (as we're expected to) constrain that by the alignment of the type. - if (const FieldDecl *Field = dyn_cast<FieldDecl>(VD)) { + if (const auto *Field = dyn_cast<FieldDecl>(VD)) { const RecordDecl *Parent = Field->getParent(); // We can only produce a sensible answer if the record is valid. if (!Parent->isInvalidDecl()) { @@ -1567,7 +1598,7 @@ ASTContext::getTypeInfoDataSizeInChars(QualType T) const { // of a base-class subobject. We decide whether that's possible // during class layout, so here we can just trust the layout results. if (getLangOpts().CPlusPlus) { - if (const RecordType *RT = T->getAs<RecordType>()) { + if (const auto *RT = T->getAs<RecordType>()) { const ASTRecordLayout &layout = getASTRecordLayout(RT->getDecl()); sizeAndAlign.first = layout.getDataSize(); } @@ -1598,7 +1629,7 @@ static getConstantArrayInfoInChars(const ASTContext &Context, std::pair<CharUnits, CharUnits> ASTContext::getTypeInfoInChars(const Type *T) const { - if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(T)) + if (const auto *CAT = dyn_cast<ConstantArrayType>(T)) return getConstantArrayInfoInChars(*this, CAT); TypeInfo Info = getTypeInfo(T); return std::make_pair(toCharUnitsFromBits(Info.Width), @@ -1620,7 +1651,7 @@ bool ASTContext::isAlignmentRequired(QualType T) const { unsigned ASTContext::getTypeAlignIfKnown(QualType T) const { // An alignment on a typedef overrides anything else. - if (auto *TT = T->getAs<TypedefType>()) + if (const auto *TT = T->getAs<TypedefType>()) if (unsigned Align = TT->getDecl()->getMaxAlignment()) return Align; @@ -1631,12 +1662,12 @@ unsigned ASTContext::getTypeAlignIfKnown(QualType T) const { // If we had an array type, its element type might be a typedef // type with an alignment attribute. - if (auto *TT = T->getAs<TypedefType>()) + if (const auto *TT = T->getAs<TypedefType>()) if (unsigned Align = TT->getDecl()->getMaxAlignment()) return Align; // Otherwise, see if the declaration of the type had an attribute. - if (auto *TT = T->getAs<TagType>()) + if (const auto *TT = T->getAs<TagType>()) return TT->getDecl()->getMaxAlignment(); return 0; @@ -1690,7 +1721,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { break; case Type::ConstantArray: { - const ConstantArrayType *CAT = cast<ConstantArrayType>(T); + const auto *CAT = cast<ConstantArrayType>(T); TypeInfo EltInfo = getTypeInfo(CAT->getElementType()); uint64_t Size = CAT->getSize().getZExtValue(); @@ -1705,7 +1736,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { } case Type::ExtVector: case Type::Vector: { - const VectorType *VT = cast<VectorType>(T); + const auto *VT = cast<VectorType>(T); TypeInfo EltInfo = getTypeInfo(VT->getElementType()); Width = EltInfo.Width * VT->getNumElements(); Align = Width; @@ -1738,6 +1769,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { case BuiltinType::Char_U: case BuiltinType::UChar: case BuiltinType::SChar: + case BuiltinType::Char8: Width = Target->getCharWidth(); Align = Target->getCharAlign(); break; @@ -1779,6 +1811,48 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Width = 128; Align = 128; // int128_t is 128-bit aligned on all targets. break; + case BuiltinType::ShortAccum: + case BuiltinType::UShortAccum: + case BuiltinType::SatShortAccum: + case BuiltinType::SatUShortAccum: + Width = Target->getShortAccumWidth(); + Align = Target->getShortAccumAlign(); + break; + case BuiltinType::Accum: + case BuiltinType::UAccum: + case BuiltinType::SatAccum: + case BuiltinType::SatUAccum: + Width = Target->getAccumWidth(); + Align = Target->getAccumAlign(); + break; + case BuiltinType::LongAccum: + case BuiltinType::ULongAccum: + case BuiltinType::SatLongAccum: + case BuiltinType::SatULongAccum: + Width = Target->getLongAccumWidth(); + Align = Target->getLongAccumAlign(); + break; + case BuiltinType::ShortFract: + case BuiltinType::UShortFract: + case BuiltinType::SatShortFract: + case BuiltinType::SatUShortFract: + Width = Target->getShortFractWidth(); + Align = Target->getShortFractAlign(); + break; + case BuiltinType::Fract: + case BuiltinType::UFract: + case BuiltinType::SatFract: + case BuiltinType::SatUFract: + Width = Target->getFractWidth(); + Align = Target->getFractAlign(); + break; + case BuiltinType::LongFract: + case BuiltinType::ULongFract: + case BuiltinType::SatLongFract: + case BuiltinType::SatULongFract: + Width = Target->getLongFractWidth(); + Align = Target->getLongFractAlign(); + break; case BuiltinType::Float16: case BuiltinType::Half: Width = Target->getHalfWidth(); @@ -1848,7 +1922,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Align = Target->getPointerAlign(AS); break; case Type::MemberPointer: { - const MemberPointerType *MPT = cast<MemberPointerType>(T); + const auto *MPT = cast<MemberPointerType>(T); CXXABI::MemberPointerInfo MPI = ABI->getMemberPointerInfo(MPT); Width = MPI.Width; Align = MPI.Align; @@ -1868,7 +1942,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { case Type::Decayed: return getTypeInfo(cast<AdjustedType>(T)->getAdjustedType().getTypePtr()); case Type::ObjCInterface: { - const ObjCInterfaceType *ObjCI = cast<ObjCInterfaceType>(T); + const auto *ObjCI = cast<ObjCInterfaceType>(T); const ASTRecordLayout &Layout = getASTObjCInterfaceLayout(ObjCI->getDecl()); Width = toBits(Layout.getSize()); Align = toBits(Layout.getAlignment()); @@ -1876,7 +1950,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { } case Type::Record: case Type::Enum: { - const TagType *TT = cast<TagType>(T); + const auto *TT = cast<TagType>(T); if (TT->getDecl()->isInvalidDecl()) { Width = 8; @@ -1884,7 +1958,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { break; } - if (const EnumType *ET = dyn_cast<EnumType>(TT)) { + if (const auto *ET = dyn_cast<EnumType>(TT)) { const EnumDecl *ED = ET->getDecl(); TypeInfo Info = getTypeInfo(ED->getIntegerType()->getUnqualifiedDesugaredType()); @@ -1895,7 +1969,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { return Info; } - const RecordType *RT = cast<RecordType>(TT); + const auto *RT = cast<RecordType>(TT); const RecordDecl *RD = RT->getDecl(); const ASTRecordLayout &Layout = getASTRecordLayout(RD); Width = toBits(Layout.getSize()); @@ -1910,7 +1984,7 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { case Type::Auto: case Type::DeducedTemplateSpecialization: { - const DeducedType *A = cast<DeducedType>(T); + const auto *A = cast<DeducedType>(T); assert(!A->getDeducedType().isNull() && "cannot request the size of an undeduced or dependent auto type"); return getTypeInfo(A->getDeducedType().getTypePtr()); @@ -1952,10 +2026,16 @@ TypeInfo ASTContext::getTypeInfoImpl(const Type *T) const { Width = Info.Width; Align = Info.Align; - // 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()) { + if (!Width) { + // An otherwise zero-sized type should still generate an + // atomic operation. + Width = Target->getCharWidth(); + assert(Align); + } else if (Width <= Target->getMaxAtomicPromoteWidth()) { + // 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: + // Round the size up to a power of 2. if (!llvm::isPowerOf2_64(Width)) Width = llvm::NextPowerOf2(Width); @@ -2033,9 +2113,9 @@ unsigned ASTContext::getPreferredTypeAlign(const Type *T) const { return ABIAlign; // Double and long long should be naturally aligned if possible. - if (const ComplexType *CT = T->getAs<ComplexType>()) + if (const auto *CT = T->getAs<ComplexType>()) T = CT->getElementType().getTypePtr(); - if (const EnumType *ET = T->getAs<EnumType>()) + if (const auto *ET = T->getAs<EnumType>()) T = ET->getDecl()->getIntegerType().getTypePtr(); if (T->isSpecificBuiltinType(BuiltinType::Double) || T->isSpecificBuiltinType(BuiltinType::LongLong) || @@ -2091,7 +2171,7 @@ void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, for (const auto *I : OI->ivars()) Ivars.push_back(I); } else { - ObjCInterfaceDecl *IDecl = const_cast<ObjCInterfaceDecl *>(OI); + auto *IDecl = const_cast<ObjCInterfaceDecl *>(OI); for (const ObjCIvarDecl *Iv = IDecl->all_declared_ivar_begin(); Iv; Iv= Iv->getNextIvar()) Ivars.push_back(Iv); @@ -2102,7 +2182,7 @@ void ASTContext::DeepCollectObjCIvars(const ObjCInterfaceDecl *OI, /// those inherited by it. void ASTContext::CollectInheritedProtocols(const Decl *CDecl, llvm::SmallPtrSet<ObjCProtocolDecl*, 8> &Protocols) { - if (const ObjCInterfaceDecl *OI = dyn_cast<ObjCInterfaceDecl>(CDecl)) { + if (const auto *OI = dyn_cast<ObjCInterfaceDecl>(CDecl)) { // We can use protocol_iterator here instead of // all_referenced_protocol_iterator since we are walking all categories. for (auto *Proto : OI->all_referenced_protocols()) { @@ -2118,11 +2198,11 @@ void ASTContext::CollectInheritedProtocols(const Decl *CDecl, CollectInheritedProtocols(SD, Protocols); SD = SD->getSuperClass(); } - } else if (const ObjCCategoryDecl *OC = dyn_cast<ObjCCategoryDecl>(CDecl)) { + } else if (const auto *OC = dyn_cast<ObjCCategoryDecl>(CDecl)) { for (auto *Proto : OC->protocols()) { CollectInheritedProtocols(Proto, Protocols); } - } else if (const ObjCProtocolDecl *OP = dyn_cast<ObjCProtocolDecl>(CDecl)) { + } else if (const auto *OP = dyn_cast<ObjCProtocolDecl>(CDecl)) { // Insert the protocol. if (!Protocols.insert( const_cast<ObjCProtocolDecl *>(OP->getCanonicalDecl())).second) @@ -2145,7 +2225,7 @@ static bool unionHasUniqueObjectRepresentations(const ASTContext &Context, if (FieldSize != UnionSize) return false; } - return true; + return !RD->field_empty(); } static bool isStructEmpty(QualType Ty) { @@ -2184,7 +2264,7 @@ structHasUniqueObjectRepresentations(const ASTContext &Context, } } - std::sort( + llvm::sort( Bases.begin(), Bases.end(), [&](const std::pair<QualType, int64_t> &L, const std::pair<QualType, int64_t> &R) { return Layout.getBaseClassOffset(L.first->getAsCXXRecordDecl()) < @@ -2264,7 +2344,7 @@ bool ASTContext::hasUniqueObjectRepresentations(QualType Ty) const { return true; if (Ty->isMemberPointerType()) { - const MemberPointerType *MPT = Ty->getAs<MemberPointerType>(); + const auto *MPT = Ty->getAs<MemberPointerType>(); return !ABI->getMemberPointerInfo(MPT).HasPadding; } @@ -2330,7 +2410,7 @@ bool ASTContext::isSentinelNullExpr(const Expr *E) { return false; } -/// \brief Get the implementation of ObjCInterfaceDecl, or nullptr if none +/// Get the implementation of ObjCInterfaceDecl, or nullptr if none /// exists. ObjCImplementationDecl *ASTContext::getObjCImplementation(ObjCInterfaceDecl *D) { llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*>::iterator @@ -2340,7 +2420,7 @@ ObjCImplementationDecl *ASTContext::getObjCImplementation(ObjCInterfaceDecl *D) return nullptr; } -/// \brief Get the implementation of ObjCCategoryDecl, or nullptr if none +/// Get the implementation of ObjCCategoryDecl, or nullptr if none /// exists. ObjCCategoryImplDecl *ASTContext::getObjCImplementation(ObjCCategoryDecl *D) { llvm::DenseMap<ObjCContainerDecl*, ObjCImplDecl*>::iterator @@ -2350,14 +2430,14 @@ ObjCCategoryImplDecl *ASTContext::getObjCImplementation(ObjCCategoryDecl *D) { return nullptr; } -/// \brief Set the implementation of ObjCInterfaceDecl. +/// Set the implementation of ObjCInterfaceDecl. void ASTContext::setObjCImplementation(ObjCInterfaceDecl *IFaceD, ObjCImplementationDecl *ImplD) { assert(IFaceD && ImplD && "Passed null params"); ObjCImpls[IFaceD] = ImplD; } -/// \brief Set the implementation of ObjCCategoryDecl. +/// Set the implementation of ObjCCategoryDecl. void ASTContext::setObjCImplementation(ObjCCategoryDecl *CatD, ObjCCategoryImplDecl *ImplD) { assert(CatD && ImplD && "Passed null params"); @@ -2377,20 +2457,17 @@ void ASTContext::setObjCMethodRedeclaration(const ObjCMethodDecl *MD, const ObjCInterfaceDecl *ASTContext::getObjContainingInterface( const NamedDecl *ND) const { - if (const ObjCInterfaceDecl *ID = - dyn_cast<ObjCInterfaceDecl>(ND->getDeclContext())) + if (const auto *ID = dyn_cast<ObjCInterfaceDecl>(ND->getDeclContext())) return ID; - if (const ObjCCategoryDecl *CD = - dyn_cast<ObjCCategoryDecl>(ND->getDeclContext())) + if (const auto *CD = dyn_cast<ObjCCategoryDecl>(ND->getDeclContext())) return CD->getClassInterface(); - if (const ObjCImplDecl *IMD = - dyn_cast<ObjCImplDecl>(ND->getDeclContext())) + if (const auto *IMD = dyn_cast<ObjCImplDecl>(ND->getDeclContext())) return IMD->getClassInterface(); return nullptr; } -/// \brief Get the copy initialization expression of VarDecl, or nullptr if +/// Get the copy initialization expression of VarDecl, or nullptr if /// none exists. Expr *ASTContext::getBlockVarCopyInits(const VarDecl*VD) { assert(VD && "Passed null params"); @@ -2398,10 +2475,10 @@ Expr *ASTContext::getBlockVarCopyInits(const VarDecl*VD) { "getBlockVarCopyInits - not __block var"); llvm::DenseMap<const VarDecl*, Expr*>::iterator I = BlockVarCopyInits.find(VD); - return (I != BlockVarCopyInits.end()) ? cast<Expr>(I->second) : nullptr; + return (I != BlockVarCopyInits.end()) ? I->second : nullptr; } -/// \brief Set the copy inialization expression of a block var decl. +/// Set the copy inialization expression of a block var decl. void ASTContext::setBlockVarCopyInits(VarDecl*VD, Expr* Init) { assert(VD && Init && "Passed null params"); assert(VD->hasAttr<BlocksAttr>() && @@ -2417,7 +2494,7 @@ TypeSourceInfo *ASTContext::CreateTypeSourceInfo(QualType T, assert(DataSize == TypeLoc::getFullDataSizeForType(T) && "incorrect data size provided to CreateTypeSourceInfo!"); - TypeSourceInfo *TInfo = + auto *TInfo = (TypeSourceInfo*)BumpAlloc.Allocate(sizeof(TypeSourceInfo) + DataSize, 8); new (TInfo) TypeSourceInfo(T); return TInfo; @@ -2470,7 +2547,7 @@ ASTContext::getExtQualType(const Type *baseType, Qualifiers quals) const { (void) ExtQualNodes.FindNodeOrInsertPos(ID, insertPos); } - ExtQuals *eq = new (*this, TypeAlignment) ExtQuals(baseType, canon, quals); + auto *eq = new (*this, TypeAlignment) ExtQuals(baseType, canon, quals); ExtQualNodes.InsertNode(eq, insertPos); return QualType(eq, fastQuals); } @@ -2522,7 +2599,7 @@ QualType ASTContext::getObjCGCQualType(QualType T, if (CanT.getObjCGCAttr() == GCAttr) return T; - if (const PointerType *ptr = T->getAs<PointerType>()) { + if (const auto *ptr = T->getAs<PointerType>()) { QualType Pointee = ptr->getPointeeType(); if (Pointee->isAnyPointerType()) { QualType ResultType = getObjCGCQualType(Pointee, GCAttr); @@ -2550,10 +2627,10 @@ const FunctionType *ASTContext::adjustFunctionType(const FunctionType *T, return T; QualType Result; - if (const FunctionNoProtoType *FNPT = dyn_cast<FunctionNoProtoType>(T)) { + if (const auto *FNPT = dyn_cast<FunctionNoProtoType>(T)) { Result = getFunctionNoProtoType(FNPT->getReturnType(), Info); } else { - const FunctionProtoType *FPT = cast<FunctionProtoType>(T); + const auto *FPT = cast<FunctionProtoType>(T); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.ExtInfo = Info; Result = getFunctionType(FPT->getReturnType(), FPT->getParamTypes(), EPI); @@ -2566,7 +2643,7 @@ void ASTContext::adjustDeducedFunctionResultType(FunctionDecl *FD, QualType ResultType) { FD = FD->getMostRecentDecl(); while (true) { - const FunctionProtoType *FPT = FD->getType()->castAs<FunctionProtoType>(); + const auto *FPT = FD->getType()->castAs<FunctionProtoType>(); FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); FD->setType(getFunctionType(ResultType, FPT->getParamTypes(), EPI)); if (FunctionDecl *Next = FD->getPreviousDecl()) @@ -2582,26 +2659,24 @@ void ASTContext::adjustDeducedFunctionResultType(FunctionDecl *FD, /// specified exception specification. Type sugar that can be present on a /// declaration of a function with an exception specification is permitted /// and preserved. Other type sugar (for instance, typedefs) is not. -static QualType getFunctionTypeWithExceptionSpec( - ASTContext &Context, QualType Orig, - const FunctionProtoType::ExceptionSpecInfo &ESI) { +QualType ASTContext::getFunctionTypeWithExceptionSpec( + QualType Orig, const FunctionProtoType::ExceptionSpecInfo &ESI) { // Might have some parens. - if (auto *PT = dyn_cast<ParenType>(Orig)) - return Context.getParenType( - getFunctionTypeWithExceptionSpec(Context, PT->getInnerType(), ESI)); + if (const auto *PT = dyn_cast<ParenType>(Orig)) + return getParenType( + getFunctionTypeWithExceptionSpec(PT->getInnerType(), ESI)); // Might have a calling-convention attribute. - if (auto *AT = dyn_cast<AttributedType>(Orig)) - return Context.getAttributedType( + if (const auto *AT = dyn_cast<AttributedType>(Orig)) + return getAttributedType( AT->getAttrKind(), - getFunctionTypeWithExceptionSpec(Context, AT->getModifiedType(), ESI), - getFunctionTypeWithExceptionSpec(Context, AT->getEquivalentType(), - ESI)); + getFunctionTypeWithExceptionSpec(AT->getModifiedType(), ESI), + getFunctionTypeWithExceptionSpec(AT->getEquivalentType(), ESI)); // Anything else must be a function type. Rebuild it with the new exception // specification. - const FunctionProtoType *Proto = cast<FunctionProtoType>(Orig); - return Context.getFunctionType( + const auto *Proto = cast<FunctionProtoType>(Orig); + return getFunctionType( Proto->getReturnType(), Proto->getParamTypes(), Proto->getExtProtoInfo().withExceptionSpec(ESI)); } @@ -2610,8 +2685,8 @@ bool ASTContext::hasSameFunctionTypeIgnoringExceptionSpec(QualType T, QualType U) { return hasSameType(T, U) || (getLangOpts().CPlusPlus17 && - hasSameType(getFunctionTypeWithExceptionSpec(*this, T, EST_None), - getFunctionTypeWithExceptionSpec(*this, U, EST_None))); + hasSameType(getFunctionTypeWithExceptionSpec(T, EST_None), + getFunctionTypeWithExceptionSpec(U, EST_None))); } void ASTContext::adjustExceptionSpec( @@ -2619,7 +2694,7 @@ void ASTContext::adjustExceptionSpec( bool AsWritten) { // Update the type. QualType Updated = - getFunctionTypeWithExceptionSpec(*this, FD->getType(), ESI); + getFunctionTypeWithExceptionSpec(FD->getType(), ESI); FD->setType(Updated); if (!AsWritten) @@ -2630,7 +2705,7 @@ void ASTContext::adjustExceptionSpec( // If the type and the type-as-written differ, we may need to update // the type-as-written too. if (TSInfo->getType() != FD->getType()) - Updated = getFunctionTypeWithExceptionSpec(*this, TSInfo->getType(), ESI); + Updated = getFunctionTypeWithExceptionSpec(TSInfo->getType(), ESI); // FIXME: When we get proper type location information for exceptions, // we'll also have to rebuild the TypeSourceInfo. For now, we just patch @@ -2664,7 +2739,7 @@ QualType ASTContext::getComplexType(QualType T) const { ComplexType *NewIP = ComplexTypes.FindNodeOrInsertPos(ID, InsertPos); assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - ComplexType *New = new (*this, TypeAlignment) ComplexType(T, Canonical); + auto *New = new (*this, TypeAlignment) ComplexType(T, Canonical); Types.push_back(New); ComplexTypes.InsertNode(New, InsertPos); return QualType(New, 0); @@ -2692,7 +2767,7 @@ QualType ASTContext::getPointerType(QualType T) const { PointerType *NewIP = PointerTypes.FindNodeOrInsertPos(ID, InsertPos); assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - PointerType *New = new (*this, TypeAlignment) PointerType(T, Canonical); + auto *New = new (*this, TypeAlignment) PointerType(T, Canonical); Types.push_back(New); PointerTypes.InsertNode(New, InsertPos); return QualType(New, 0); @@ -2783,8 +2858,7 @@ QualType ASTContext::getBlockPointerType(QualType T) const { BlockPointerTypes.FindNodeOrInsertPos(ID, InsertPos); assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - BlockPointerType *New - = new (*this, TypeAlignment) BlockPointerType(T, Canonical); + auto *New = new (*this, TypeAlignment) BlockPointerType(T, Canonical); Types.push_back(New); BlockPointerTypes.InsertNode(New, InsertPos); return QualType(New, 0); @@ -2807,7 +2881,7 @@ ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) const { LValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(RT, 0); - const ReferenceType *InnerRef = T->getAs<ReferenceType>(); + const auto *InnerRef = T->getAs<ReferenceType>(); // If the referencee type isn't canonical, this won't be a canonical type // either, so fill in the canonical type field. @@ -2822,9 +2896,8 @@ ASTContext::getLValueReferenceType(QualType T, bool SpelledAsLValue) const { assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - LValueReferenceType *New - = new (*this, TypeAlignment) LValueReferenceType(T, Canonical, - SpelledAsLValue); + auto *New = new (*this, TypeAlignment) LValueReferenceType(T, Canonical, + SpelledAsLValue); Types.push_back(New); LValueReferenceTypes.InsertNode(New, InsertPos); @@ -2844,7 +2917,7 @@ QualType ASTContext::getRValueReferenceType(QualType T) const { RValueReferenceTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(RT, 0); - const ReferenceType *InnerRef = T->getAs<ReferenceType>(); + const auto *InnerRef = T->getAs<ReferenceType>(); // If the referencee type isn't canonical, this won't be a canonical type // either, so fill in the canonical type field. @@ -2859,8 +2932,7 @@ QualType ASTContext::getRValueReferenceType(QualType T) const { assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - RValueReferenceType *New - = new (*this, TypeAlignment) RValueReferenceType(T, Canonical); + auto *New = new (*this, TypeAlignment) RValueReferenceType(T, Canonical); Types.push_back(New); RValueReferenceTypes.InsertNode(New, InsertPos); return QualType(New, 0); @@ -2890,8 +2962,7 @@ QualType ASTContext::getMemberPointerType(QualType T, const Type *Cls) const { MemberPointerTypes.FindNodeOrInsertPos(ID, InsertPos); assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - MemberPointerType *New - = new (*this, TypeAlignment) MemberPointerType(T, Cls, Canonical); + auto *New = new (*this, TypeAlignment) MemberPointerType(T, Cls, Canonical); Types.push_back(New); MemberPointerTypes.InsertNode(New, InsertPos); return QualType(New, 0); @@ -2935,7 +3006,7 @@ QualType ASTContext::getConstantArrayType(QualType EltTy, assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - ConstantArrayType *New = new(*this,TypeAlignment) + auto *New = new (*this,TypeAlignment) ConstantArrayType(EltTy, Canon, ArySize, ASM, IndexTypeQuals); ConstantArrayTypes.InsertNode(New, InsertPos); Types.push_back(New); @@ -2964,6 +3035,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { case Type::Builtin: case Type::Complex: case Type::Vector: + case Type::DependentVector: case Type::ExtVector: case Type::DependentSizedExtVector: case Type::DependentAddressSpace: @@ -3007,7 +3079,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { break; case Type::LValueReference: { - const LValueReferenceType *lv = cast<LValueReferenceType>(ty); + const auto *lv = cast<LValueReferenceType>(ty); result = getLValueReferenceType( getVariableArrayDecayedType(lv->getPointeeType()), lv->isSpelledAsLValue()); @@ -3015,20 +3087,20 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { } case Type::RValueReference: { - const RValueReferenceType *lv = cast<RValueReferenceType>(ty); + const auto *lv = cast<RValueReferenceType>(ty); result = getRValueReferenceType( getVariableArrayDecayedType(lv->getPointeeType())); break; } case Type::Atomic: { - const AtomicType *at = cast<AtomicType>(ty); + const auto *at = cast<AtomicType>(ty); result = getAtomicType(getVariableArrayDecayedType(at->getValueType())); break; } case Type::ConstantArray: { - const ConstantArrayType *cat = cast<ConstantArrayType>(ty); + const auto *cat = cast<ConstantArrayType>(ty); result = getConstantArrayType( getVariableArrayDecayedType(cat->getElementType()), cat->getSize(), @@ -3038,7 +3110,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { } case Type::DependentSizedArray: { - const DependentSizedArrayType *dat = cast<DependentSizedArrayType>(ty); + const auto *dat = cast<DependentSizedArrayType>(ty); result = getDependentSizedArrayType( getVariableArrayDecayedType(dat->getElementType()), dat->getSizeExpr(), @@ -3050,7 +3122,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { // Turn incomplete types into [*] types. case Type::IncompleteArray: { - const IncompleteArrayType *iat = cast<IncompleteArrayType>(ty); + const auto *iat = cast<IncompleteArrayType>(ty); result = getVariableArrayType( getVariableArrayDecayedType(iat->getElementType()), /*size*/ nullptr, @@ -3062,7 +3134,7 @@ QualType ASTContext::getVariableArrayDecayedType(QualType type) const { // Turn VLA types into [*] types. case Type::VariableArray: { - const VariableArrayType *vat = cast<VariableArrayType>(ty); + const auto *vat = cast<VariableArrayType>(ty); result = getVariableArrayType( getVariableArrayDecayedType(vat->getElementType()), /*size*/ nullptr, @@ -3096,7 +3168,7 @@ QualType ASTContext::getVariableArrayType(QualType EltTy, Canon = getQualifiedType(Canon, canonSplit.Quals); } - VariableArrayType *New = new(*this, TypeAlignment) + auto *New = new (*this, TypeAlignment) VariableArrayType(EltTy, Canon, NumElts, ASM, IndexTypeQuals, Brackets); VariableArrayTypes.push_back(New); @@ -3121,7 +3193,7 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType, // initializer. We do no canonicalization here at all, which is okay // because they can't be used in most locations. if (!numElements) { - DependentSizedArrayType *newType + auto *newType = new (*this, TypeAlignment) DependentSizedArrayType(*this, elementType, QualType(), numElements, ASM, elementTypeQuals, @@ -3167,7 +3239,7 @@ QualType ASTContext::getDependentSizedArrayType(QualType elementType, // Otherwise, we need to build a type which follows the spelling // of the element type. - DependentSizedArrayType *sugaredType + auto *sugaredType = new (*this, TypeAlignment) DependentSizedArrayType(*this, elementType, canon, numElements, ASM, elementTypeQuals, brackets); @@ -3203,7 +3275,7 @@ QualType ASTContext::getIncompleteArrayType(QualType elementType, assert(!existing && "Shouldn't be in the map!"); (void) existing; } - IncompleteArrayType *newType = new (*this, TypeAlignment) + auto *newType = new (*this, TypeAlignment) IncompleteArrayType(elementType, canon, ASM, elementTypeQuals); IncompleteArrayTypes.InsertNode(newType, insertPos); @@ -3235,13 +3307,52 @@ QualType ASTContext::getVectorType(QualType vecType, unsigned NumElts, VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos); assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - VectorType *New = new (*this, TypeAlignment) + auto *New = new (*this, TypeAlignment) VectorType(vecType, NumElts, Canonical, VecKind); VectorTypes.InsertNode(New, InsertPos); Types.push_back(New); return QualType(New, 0); } +QualType +ASTContext::getDependentVectorType(QualType VecType, Expr *SizeExpr, + SourceLocation AttrLoc, + VectorType::VectorKind VecKind) const { + llvm::FoldingSetNodeID ID; + DependentVectorType::Profile(ID, *this, getCanonicalType(VecType), SizeExpr, + VecKind); + void *InsertPos = nullptr; + DependentVectorType *Canon = + DependentVectorTypes.FindNodeOrInsertPos(ID, InsertPos); + DependentVectorType *New; + + if (Canon) { + New = new (*this, TypeAlignment) DependentVectorType( + *this, VecType, QualType(Canon, 0), SizeExpr, AttrLoc, VecKind); + } else { + QualType CanonVecTy = getCanonicalType(VecType); + if (CanonVecTy == VecType) { + New = new (*this, TypeAlignment) DependentVectorType( + *this, VecType, QualType(), SizeExpr, AttrLoc, VecKind); + + DependentVectorType *CanonCheck = + DependentVectorTypes.FindNodeOrInsertPos(ID, InsertPos); + assert(!CanonCheck && + "Dependent-sized vector_size canonical type broken"); + (void)CanonCheck; + DependentVectorTypes.InsertNode(New, InsertPos); + } else { + QualType Canon = getDependentSizedExtVectorType(CanonVecTy, SizeExpr, + SourceLocation()); + New = new (*this, TypeAlignment) DependentVectorType( + *this, VecType, Canon, SizeExpr, AttrLoc, VecKind); + } + } + + Types.push_back(New); + return QualType(New, 0); +} + /// getExtVectorType - Return the unique reference to an extended vector type of /// the specified element type and size. VectorType must be a built-in type. QualType @@ -3266,7 +3377,7 @@ ASTContext::getExtVectorType(QualType vecType, unsigned NumElts) const { VectorType *NewIP = VectorTypes.FindNodeOrInsertPos(ID, InsertPos); assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - ExtVectorType *New = new (*this, TypeAlignment) + auto *New = new (*this, TypeAlignment) ExtVectorType(vecType, NumElts, Canonical); VectorTypes.InsertNode(New, InsertPos); Types.push_back(New); @@ -3342,7 +3453,7 @@ QualType ASTContext::getDependentAddressSpaceType(QualType PointeeType, canonTy->getAddrSpaceExpr() == AddrSpaceExpr) return QualType(canonTy, 0); - DependentAddressSpaceType *sugaredType + auto *sugaredType = new (*this, TypeAlignment) DependentAddressSpaceType(*this, PointeeType, QualType(canonTy, 0), AddrSpaceExpr, AttrLoc); @@ -3350,7 +3461,7 @@ QualType ASTContext::getDependentAddressSpaceType(QualType PointeeType, return QualType(sugaredType, 0); } -/// \brief Determine whether \p T is canonical as the result type of a function. +/// 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 || @@ -3382,7 +3493,7 @@ ASTContext::getFunctionNoProtoType(QualType ResultTy, assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - FunctionNoProtoType *New = new (*this, TypeAlignment) + auto *New = new (*this, TypeAlignment) FunctionNoProtoType(ResultTy, Canonical, Info); Types.push_back(New); FunctionNoProtoTypes.InsertNode(New, InsertPos); @@ -3416,6 +3527,11 @@ static bool isCanonicalExceptionSpecification( if (ESI.Type == EST_BasicNoexcept) return true; + // A noexcept(expr) specification is (possibly) canonical if expr is + // value-dependent. + if (ESI.Type == EST_DependentNoexcept) + return true; + // A dynamic exception specification is canonical if it only contains pack // expansions (so we can't tell whether it's non-throwing) and all its // contained types are canonical. @@ -3430,11 +3546,6 @@ static bool isCanonicalExceptionSpecification( return AnyPackExpansions; } - // A noexcept(expr) specification is (possibly) canonical if expr is - // value-dependent. - if (ESI.Type == EST_ComputedNoexcept) - return ESI.NoexceptExpr && ESI.NoexceptExpr->isValueDependent(); - return false; } @@ -3462,7 +3573,7 @@ QualType ASTContext::getFunctionTypeInternal( // noexcept expression, or we're just looking for a canonical type. // Otherwise, we're going to need to create a type // sugar node to hold the concrete expression. - if (OnlyWantCanonical || EPI.ExceptionSpec.Type != EST_ComputedNoexcept || + if (OnlyWantCanonical || !isComputedNoexcept(EPI.ExceptionSpec.Type) || EPI.ExceptionSpec.NoexceptExpr == FPT->getNoexceptExpr()) return Existing; @@ -3509,7 +3620,7 @@ QualType ASTContext::getFunctionTypeInternal( // We don't know yet. It shouldn't matter what we pick here; no-one // should ever look at this. LLVM_FALLTHROUGH; - case EST_None: case EST_MSAny: + case EST_None: case EST_MSAny: case EST_NoexceptFalse: CanonicalEPI.ExceptionSpec.Type = EST_None; break; @@ -3531,24 +3642,12 @@ QualType ASTContext::getFunctionTypeInternal( break; } - case EST_DynamicNone: case EST_BasicNoexcept: + case EST_DynamicNone: case EST_BasicNoexcept: case EST_NoexceptTrue: CanonicalEPI.ExceptionSpec.Type = EST_BasicNoexcept; break; - case EST_ComputedNoexcept: - llvm::APSInt Value(1); - auto *E = CanonicalEPI.ExceptionSpec.NoexceptExpr; - if (!E || !E->isIntegerConstantExpr(Value, *this, nullptr, - /*IsEvaluated*/false)) { - // This noexcept specification is invalid. - // FIXME: Should this be able to happen? - CanonicalEPI.ExceptionSpec.Type = EST_None; - break; - } - - CanonicalEPI.ExceptionSpec.Type = - Value.getBoolValue() ? EST_BasicNoexcept : EST_None; - break; + case EST_DependentNoexcept: + llvm_unreachable("dependent noexcept is already canonical"); } } else { CanonicalEPI.ExceptionSpec = FunctionProtoType::ExceptionSpecInfo(); @@ -3573,18 +3672,10 @@ QualType ASTContext::getFunctionTypeInternal( // Instead of the exception types, there could be a noexcept // expression, or information used to resolve the exception // specification. - size_t Size = sizeof(FunctionProtoType) + - NumArgs * sizeof(QualType); - - if (EPI.ExceptionSpec.Type == EST_Dynamic) { - Size += EPI.ExceptionSpec.Exceptions.size() * sizeof(QualType); - } else if (EPI.ExceptionSpec.Type == EST_ComputedNoexcept) { - Size += sizeof(Expr*); - } else if (EPI.ExceptionSpec.Type == EST_Uninstantiated) { - Size += 2 * sizeof(FunctionDecl*); - } else if (EPI.ExceptionSpec.Type == EST_Unevaluated) { - Size += sizeof(FunctionDecl*); - } + size_t Size = + sizeof(FunctionProtoType) + NumArgs * sizeof(QualType) + + FunctionProtoType::getExceptionSpecSize( + EPI.ExceptionSpec.Type, EPI.ExceptionSpec.Exceptions.size()); // Put the ExtParameterInfos last. If all were equal, it would make // more sense to put these before the exception specification, because @@ -3596,7 +3687,7 @@ QualType ASTContext::getFunctionTypeInternal( Size += NumArgs * sizeof(FunctionProtoType::ExtParameterInfo); } - FunctionProtoType *FTP = (FunctionProtoType*) Allocate(Size, TypeAlignment); + auto *FTP = (FunctionProtoType *) Allocate(Size, TypeAlignment); FunctionProtoType::ExtProtoInfo newEPI = EPI; new (FTP) FunctionProtoType(ResultTy, ArgArray, Canonical, newEPI); Types.push_back(FTP); @@ -3624,12 +3715,18 @@ QualType ASTContext::getPipeType(QualType T, bool ReadOnly) const { assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - PipeType *New = new (*this, TypeAlignment) PipeType(T, Canonical, ReadOnly); + auto *New = new (*this, TypeAlignment) PipeType(T, Canonical, ReadOnly); Types.push_back(New); PipeTypes.InsertNode(New, InsertPos); return QualType(New, 0); } +QualType ASTContext::adjustStringLiteralBaseType(QualType Ty) const { + // OpenCL v1.1 s6.5.3: a string literal is in the constant address space. + return LangOpts.OpenCL ? getAddrSpaceQualType(Ty, LangAS::opencl_constant) + : Ty; +} + QualType ASTContext::getReadPipeType(QualType T) const { return getPipeType(T, true); } @@ -3641,7 +3738,7 @@ QualType ASTContext::getWritePipeType(QualType T) const { #ifndef NDEBUG static bool NeedsInjectedClassNameType(const RecordDecl *D) { if (!isa<CXXRecordDecl>(D)) return false; - const CXXRecordDecl *RD = cast<CXXRecordDecl>(D); + const auto *RD = cast<CXXRecordDecl>(D); if (isa<ClassTemplatePartialSpecializationDecl>(RD)) return true; if (RD->getDescribedClassTemplate() && @@ -3677,21 +3774,20 @@ QualType ASTContext::getTypeDeclTypeSlow(const TypeDecl *Decl) const { assert(Decl && "Passed null for Decl param"); assert(!Decl->TypeForDecl && "TypeForDecl present in slow case"); - if (const TypedefNameDecl *Typedef = dyn_cast<TypedefNameDecl>(Decl)) + if (const auto *Typedef = dyn_cast<TypedefNameDecl>(Decl)) return getTypedefType(Typedef); assert(!isa<TemplateTypeParmDecl>(Decl) && "Template type parameter types are always available."); - if (const RecordDecl *Record = dyn_cast<RecordDecl>(Decl)) { + if (const auto *Record = dyn_cast<RecordDecl>(Decl)) { assert(Record->isFirstDecl() && "struct/union has previous declaration"); assert(!NeedsInjectedClassNameType(Record)); return getRecordType(Record); - } else if (const EnumDecl *Enum = dyn_cast<EnumDecl>(Decl)) { + } else if (const auto *Enum = dyn_cast<EnumDecl>(Decl)) { assert(Enum->isFirstDecl() && "enum has previous declaration"); return getEnumType(Enum); - } else if (const UnresolvedUsingTypenameDecl *Using = - dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) { + } else if (const auto *Using = dyn_cast<UnresolvedUsingTypenameDecl>(Decl)) { Type *newType = new (*this, TypeAlignment) UnresolvedUsingType(Using); Decl->TypeForDecl = newType; Types.push_back(newType); @@ -3710,7 +3806,7 @@ ASTContext::getTypedefType(const TypedefNameDecl *Decl, if (Canonical.isNull()) Canonical = getCanonicalType(Decl->getUnderlyingType()); - TypedefType *newType = new(*this, TypeAlignment) + auto *newType = new (*this, TypeAlignment) TypedefType(Type::Typedef, Decl, Canonical); Decl->TypeForDecl = newType; Types.push_back(newType); @@ -3724,7 +3820,7 @@ QualType ASTContext::getRecordType(const RecordDecl *Decl) const { if (PrevDecl->TypeForDecl) return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0); - RecordType *newType = new (*this, TypeAlignment) RecordType(Decl); + auto *newType = new (*this, TypeAlignment) RecordType(Decl); Decl->TypeForDecl = newType; Types.push_back(newType); return QualType(newType, 0); @@ -3737,7 +3833,7 @@ QualType ASTContext::getEnumType(const EnumDecl *Decl) const { if (PrevDecl->TypeForDecl) return QualType(Decl->TypeForDecl = PrevDecl->TypeForDecl, 0); - EnumType *newType = new (*this, TypeAlignment) EnumType(Decl); + auto *newType = new (*this, TypeAlignment) EnumType(Decl); Decl->TypeForDecl = newType; Types.push_back(newType); return QualType(newType, 0); @@ -3763,7 +3859,7 @@ QualType ASTContext::getAttributedType(AttributedType::Kind attrKind, return QualType(type, 0); } -/// \brief Retrieve a substitution-result type. +/// Retrieve a substitution-result type. QualType ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm, QualType Replacement) const { @@ -3786,7 +3882,7 @@ ASTContext::getSubstTemplateTypeParmType(const TemplateTypeParmType *Parm, return QualType(SubstParm, 0); } -/// \brief Retrieve a +/// Retrieve a QualType ASTContext::getSubstTemplateTypeParmPackType( const TemplateTypeParmType *Parm, const TemplateArgument &ArgPack) { @@ -3812,7 +3908,7 @@ QualType ASTContext::getSubstTemplateTypeParmPackType( SubstTemplateTypeParmPackTypes.FindNodeOrInsertPos(ID, InsertPos); } - SubstTemplateTypeParmPackType *SubstParm + auto *SubstParm = new (*this, TypeAlignment) SubstTemplateTypeParmPackType(Parm, Canon, ArgPack); Types.push_back(SubstParm); @@ -3820,7 +3916,7 @@ QualType ASTContext::getSubstTemplateTypeParmPackType( return QualType(SubstParm, 0); } -/// \brief Retrieve the template type parameter type for a template +/// Retrieve the template type parameter type for a template /// parameter or parameter pack with the given depth, index, and (optionally) /// name. QualType ASTContext::getTemplateTypeParmType(unsigned Depth, unsigned Index, @@ -3931,7 +4027,7 @@ ASTContext::getTemplateSpecializationType(TemplateName Template, sizeof(TemplateArgument) * Args.size() + (IsTypeAlias? sizeof(QualType) : 0), TypeAlignment); - TemplateSpecializationType *Spec + auto *Spec = new (Mem) TemplateSpecializationType(Template, Args, CanonType, IsTypeAlias ? Underlying : QualType()); @@ -3983,12 +4079,12 @@ QualType ASTContext::getCanonicalTemplateSpecializationType( return QualType(Spec, 0); } -QualType -ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword, - NestedNameSpecifier *NNS, - QualType NamedType) const { +QualType ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword, + NestedNameSpecifier *NNS, + QualType NamedType, + TagDecl *OwnedTagDecl) const { llvm::FoldingSetNodeID ID; - ElaboratedType::Profile(ID, Keyword, NNS, NamedType); + ElaboratedType::Profile(ID, Keyword, NNS, NamedType, OwnedTagDecl); void *InsertPos = nullptr; ElaboratedType *T = ElaboratedTypes.FindNodeOrInsertPos(ID, InsertPos); @@ -4003,7 +4099,8 @@ ASTContext::getElaboratedType(ElaboratedTypeKeyword Keyword, (void)CheckT; } - T = new (*this, TypeAlignment) ElaboratedType(Keyword, NNS, NamedType, Canon); + T = new (*this, TypeAlignment) + ElaboratedType(Keyword, NNS, NamedType, Canon, OwnedTagDecl); Types.push_back(T); ElaboratedTypes.InsertNode(T, InsertPos); return QualType(T, 0); @@ -4126,7 +4223,7 @@ ASTContext::getDependentTemplateSpecializationType( TemplateArgument ASTContext::getInjectedTemplateArg(NamedDecl *Param) { TemplateArgument Arg; - if (auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { + if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(Param)) { QualType ArgType = getTypeDeclType(TTP); if (TTP->isParameterPack()) ArgType = getPackExpansionType(ArgType, None); @@ -4265,7 +4362,7 @@ QualType ASTContext::getObjCObjectType( // type. ArrayRef<QualType> effectiveTypeArgs = typeArgs; if (effectiveTypeArgs.empty()) { - if (auto baseObject = baseType->getAs<ObjCObjectType>()) + if (const auto *baseObject = baseType->getAs<ObjCObjectType>()) effectiveTypeArgs = baseObject->getTypeArgs(); } @@ -4313,7 +4410,7 @@ QualType ASTContext::getObjCObjectType( size += typeArgs.size() * sizeof(QualType); size += protocols.size() * sizeof(ObjCProtocolDecl *); void *mem = Allocate(size, TypeAlignment); - ObjCObjectTypeImpl *T = + auto *T = new (mem) ObjCObjectTypeImpl(canonical, baseType, typeArgs, protocols, isKindOf); @@ -4331,15 +4428,14 @@ ASTContext::applyObjCProtocolQualifiers(QualType type, bool allowOnPointerType) const { hasError = false; - if (const ObjCTypeParamType *objT = - dyn_cast<ObjCTypeParamType>(type.getTypePtr())) { + if (const auto *objT = dyn_cast<ObjCTypeParamType>(type.getTypePtr())) { return getObjCTypeParamType(objT->getDecl(), protocols); } // Apply protocol qualifiers to ObjCObjectPointerType. if (allowOnPointerType) { - if (const ObjCObjectPointerType *objPtr = - dyn_cast<ObjCObjectPointerType>(type.getTypePtr())) { + if (const auto *objPtr = + dyn_cast<ObjCObjectPointerType>(type.getTypePtr())) { const ObjCObjectType *objT = objPtr->getObjectType(); // Merge protocol lists and construct ObjCObjectType. SmallVector<ObjCProtocolDecl*, 8> protocolsVec; @@ -4357,7 +4453,7 @@ ASTContext::applyObjCProtocolQualifiers(QualType type, } // Apply protocol qualifiers to ObjCObjectType. - if (const ObjCObjectType *objT = dyn_cast<ObjCObjectType>(type.getTypePtr())){ + if (const auto *objT = dyn_cast<ObjCObjectType>(type.getTypePtr())){ // FIXME: Check for protocols to which the class type is already // known to conform. @@ -4379,7 +4475,7 @@ ASTContext::applyObjCProtocolQualifiers(QualType type, // id<protocol-list> if (type->isObjCIdType()) { - const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>(); + const auto *objPtr = type->castAs<ObjCObjectPointerType>(); type = getObjCObjectType(ObjCBuiltinIdTy, {}, protocols, objPtr->isKindOfType()); return getObjCObjectPointerType(type); @@ -4387,7 +4483,7 @@ ASTContext::applyObjCProtocolQualifiers(QualType type, // Class<protocol-list> if (type->isObjCClassType()) { - const ObjCObjectPointerType *objPtr = type->castAs<ObjCObjectPointerType>(); + const auto *objPtr = type->castAs<ObjCObjectPointerType>(); type = getObjCObjectType(ObjCBuiltinClassTy, {}, protocols, objPtr->isKindOfType()); return getObjCObjectPointerType(type); @@ -4424,8 +4520,7 @@ ASTContext::getObjCTypeParamType(const ObjCTypeParamDecl *Decl, unsigned size = sizeof(ObjCTypeParamType); size += protocols.size() * sizeof(ObjCProtocolDecl *); void *mem = Allocate(size, TypeAlignment); - ObjCTypeParamType *newType = new (mem) - ObjCTypeParamType(Decl, Canonical, protocols); + auto *newType = new (mem) ObjCTypeParamType(Decl, Canonical, protocols); Types.push_back(newType); ObjCTypeParamTypes.InsertNode(newType, InsertPos); @@ -4440,7 +4535,7 @@ bool ASTContext::ObjCObjectAdoptsQTypeProtocols(QualType QT, if (!QT->isObjCQualifiedIdType()) return false; - if (const ObjCObjectPointerType *OPT = QT->getAs<ObjCObjectPointerType>()) { + if (const auto *OPT = QT->getAs<ObjCObjectPointerType>()) { // If both the right and left sides have qualifiers. for (auto *Proto : OPT->quals()) { if (!IC->ClassImplementsProtocol(Proto, false)) @@ -4458,7 +4553,7 @@ bool ASTContext::QIdProtocolsAdoptObjCObjectProtocols(QualType QT, ObjCInterfaceDecl *IDecl) { if (!QT->isObjCQualifiedIdType()) return false; - const ObjCObjectPointerType *OPT = QT->getAs<ObjCObjectPointerType>(); + const auto *OPT = QT->getAs<ObjCObjectPointerType>(); if (!OPT) return false; if (!IDecl->hasDefinition()) @@ -4467,7 +4562,7 @@ bool ASTContext::QIdProtocolsAdoptObjCObjectProtocols(QualType QT, CollectInheritedProtocols(IDecl, InheritedProtocols); if (InheritedProtocols.empty()) return false; - // Check that if every protocol in list of id<plist> conforms to a protcol + // Check that if every protocol in list of id<plist> conforms to a protocol // of IDecl's, then bridge casting is ok. bool Conforms = false; for (auto *Proto : OPT->quals()) { @@ -4520,7 +4615,7 @@ QualType ASTContext::getObjCObjectPointerType(QualType ObjectT) const { // No match. void *Mem = Allocate(sizeof(ObjCObjectPointerType), TypeAlignment); - ObjCObjectPointerType *QType = + auto *QType = new (Mem) ObjCObjectPointerType(Canonical, ObjectT); Types.push_back(QType); @@ -4546,7 +4641,7 @@ QualType ASTContext::getObjCInterfaceType(const ObjCInterfaceDecl *Decl, Decl = Def; void *Mem = Allocate(sizeof(ObjCInterfaceType), TypeAlignment); - ObjCInterfaceType *T = new (Mem) ObjCInterfaceType(Decl); + auto *T = new (Mem) ObjCInterfaceType(Decl); Decl->TypeForDecl = T; Types.push_back(T); return QualType(T, 0); @@ -4593,12 +4688,12 @@ QualType ASTContext::getTypeOfExprType(Expr *tofExpr) const { /// on canonical types (which are always unique). QualType ASTContext::getTypeOfType(QualType tofType) const { QualType Canonical = getCanonicalType(tofType); - TypeOfType *tot = new (*this, TypeAlignment) TypeOfType(tofType, Canonical); + auto *tot = new (*this, TypeAlignment) TypeOfType(tofType, Canonical); Types.push_back(tot); return QualType(tot, 0); } -/// \brief Unlike many "get<Type>" functions, we don't unique DecltypeType +/// Unlike many "get<Type>" functions, we don't unique DecltypeType /// nodes. This would never be helpful, since each such type has its own /// expression, and would not give a significant memory saving, since there /// is an Expr tree under each such type. @@ -4683,9 +4778,8 @@ QualType ASTContext::getAutoType(QualType DeducedType, AutoTypeKeyword Keyword, if (AutoType *AT = AutoTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(AT, 0); - AutoType *AT = new (*this, TypeAlignment) AutoType(DeducedType, - Keyword, - IsDependent); + auto *AT = new (*this, TypeAlignment) + AutoType(DeducedType, Keyword, IsDependent); Types.push_back(AT); if (InsertPos) AutoTypes.InsertNode(AT, InsertPos); @@ -4706,7 +4800,7 @@ QualType ASTContext::getDeducedTemplateSpecializationType( DeducedTemplateSpecializationTypes.FindNodeOrInsertPos(ID, InsertPos)) return QualType(DTST, 0); - DeducedTemplateSpecializationType *DTST = new (*this, TypeAlignment) + auto *DTST = new (*this, TypeAlignment) DeducedTemplateSpecializationType(Template, DeducedType, IsDependent); Types.push_back(DTST); if (InsertPos) @@ -4736,7 +4830,7 @@ QualType ASTContext::getAtomicType(QualType T) const { AtomicType *NewIP = AtomicTypes.FindNodeOrInsertPos(ID, InsertPos); assert(!NewIP && "Shouldn't be in the map!"); (void)NewIP; } - AtomicType *New = new (*this, TypeAlignment) AtomicType(T, Canonical); + auto *New = new (*this, TypeAlignment) AtomicType(T, Canonical); Types.push_back(New); AtomicTypes.InsertNode(New, InsertPos); return QualType(New, 0); @@ -4820,14 +4914,14 @@ QualType ASTContext::getPointerDiffType() const { return getFromTargetType(Target->getPtrDiffType(0)); } -/// \brief Return the unique unsigned counterpart of "ptrdiff_t" +/// Return the unique unsigned counterpart of "ptrdiff_t" /// integer type. The standard (C11 7.21.6.1p7) refers to this type /// in the definition of %tu format specifier. QualType ASTContext::getUnsignedPointerDiffType() const { return getFromTargetType(Target->getUnsignedPtrDiffType(0)); } -/// \brief Return the unique type for "pid_t" defined in +/// Return the unique type for "pid_t" defined in /// <sys/types.h>. We need this to compute the correct type for vfork(). QualType ASTContext::getProcessIDType() const { return getFromTargetType(Target->getProcessIDType()); @@ -4863,8 +4957,8 @@ QualType ASTContext::getUnqualifiedArrayType(QualType type, // the unqualified desugared type and then drops it on the floor. // We then have to strip that sugar back off with // getUnqualifiedDesugaredType(), which is silly. - const ArrayType *AT = - dyn_cast<ArrayType>(splitType.Ty->getUnqualifiedDesugaredType()); + const auto *AT = + dyn_cast<ArrayType>(splitType.Ty->getUnqualifiedDesugaredType()); // If we don't have an array, just use the results in splitType. if (!AT) { @@ -4888,16 +4982,16 @@ QualType ASTContext::getUnqualifiedArrayType(QualType type, // build the type back up. quals.addConsistentQualifiers(splitType.Quals); - if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) { + if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) { return getConstantArrayType(unqualElementType, CAT->getSize(), CAT->getSizeModifier(), 0); } - if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(AT)) { + if (const auto *IAT = dyn_cast<IncompleteArrayType>(AT)) { return getIncompleteArrayType(unqualElementType, IAT->getSizeModifier(), 0); } - if (const VariableArrayType *VAT = dyn_cast<VariableArrayType>(AT)) { + if (const auto *VAT = dyn_cast<VariableArrayType>(AT)) { return getVariableArrayType(unqualElementType, VAT->getSizeExpr(), VAT->getSizeModifier(), @@ -4905,31 +4999,66 @@ QualType ASTContext::getUnqualifiedArrayType(QualType type, VAT->getBracketsRange()); } - const DependentSizedArrayType *DSAT = cast<DependentSizedArrayType>(AT); + const auto *DSAT = cast<DependentSizedArrayType>(AT); return getDependentSizedArrayType(unqualElementType, DSAT->getSizeExpr(), DSAT->getSizeModifier(), 0, SourceRange()); } -/// UnwrapSimilarPointerTypes - If T1 and T2 are pointer types that -/// may be similar (C++ 4.4), replaces T1 and T2 with the type that -/// they point to and return true. If T1 and T2 aren't pointer types -/// or pointer-to-member types, or if they are not similar at this -/// level, returns false and leaves T1 and T2 unchanged. Top-level -/// qualifiers on T1 and T2 are ignored. This function will typically -/// be called in a loop that successively "unwraps" pointer and -/// pointer-to-member types to compare them at each level. -bool ASTContext::UnwrapSimilarPointerTypes(QualType &T1, QualType &T2) { - const PointerType *T1PtrType = T1->getAs<PointerType>(), - *T2PtrType = T2->getAs<PointerType>(); +/// Attempt to unwrap two types that may both be array types with the same bound +/// (or both be array types of unknown bound) for the purpose of comparing the +/// cv-decomposition of two types per C++ [conv.qual]. +bool ASTContext::UnwrapSimilarArrayTypes(QualType &T1, QualType &T2) { + bool UnwrappedAny = false; + while (true) { + auto *AT1 = getAsArrayType(T1); + if (!AT1) return UnwrappedAny; + + auto *AT2 = getAsArrayType(T2); + if (!AT2) return UnwrappedAny; + + // If we don't have two array types with the same constant bound nor two + // incomplete array types, we've unwrapped everything we can. + if (auto *CAT1 = dyn_cast<ConstantArrayType>(AT1)) { + auto *CAT2 = dyn_cast<ConstantArrayType>(AT2); + if (!CAT2 || CAT1->getSize() != CAT2->getSize()) + return UnwrappedAny; + } else if (!isa<IncompleteArrayType>(AT1) || + !isa<IncompleteArrayType>(AT2)) { + return UnwrappedAny; + } + + T1 = AT1->getElementType(); + T2 = AT2->getElementType(); + UnwrappedAny = true; + } +} + +/// Attempt to unwrap two types that may be similar (C++ [conv.qual]). +/// +/// If T1 and T2 are both pointer types of the same kind, or both array types +/// with the same bound, unwraps layers from T1 and T2 until a pointer type is +/// unwrapped. Top-level qualifiers on T1 and T2 are ignored. +/// +/// This function will typically be called in a loop that successively +/// "unwraps" pointer and pointer-to-member types to compare them at each +/// level. +/// +/// \return \c true if a pointer type was unwrapped, \c false if we reached a +/// pair of types that can't be unwrapped further. +bool ASTContext::UnwrapSimilarTypes(QualType &T1, QualType &T2) { + UnwrapSimilarArrayTypes(T1, T2); + + const auto *T1PtrType = T1->getAs<PointerType>(); + const auto *T2PtrType = T2->getAs<PointerType>(); if (T1PtrType && T2PtrType) { T1 = T1PtrType->getPointeeType(); T2 = T2PtrType->getPointeeType(); return true; } - - const MemberPointerType *T1MPType = T1->getAs<MemberPointerType>(), - *T2MPType = T2->getAs<MemberPointerType>(); + + const auto *T1MPType = T1->getAs<MemberPointerType>(); + const auto *T2MPType = T2->getAs<MemberPointerType>(); if (T1MPType && T2MPType && hasSameUnqualifiedType(QualType(T1MPType->getClass(), 0), QualType(T2MPType->getClass(), 0))) { @@ -4939,8 +5068,8 @@ bool ASTContext::UnwrapSimilarPointerTypes(QualType &T1, QualType &T2) { } if (getLangOpts().ObjC1) { - const ObjCObjectPointerType *T1OPType = T1->getAs<ObjCObjectPointerType>(), - *T2OPType = T2->getAs<ObjCObjectPointerType>(); + const auto *T1OPType = T1->getAs<ObjCObjectPointerType>(); + const auto *T2OPType = T2->getAs<ObjCObjectPointerType>(); if (T1OPType && T2OPType) { T1 = T1OPType->getPointeeType(); T2 = T2OPType->getPointeeType(); @@ -4953,6 +5082,37 @@ bool ASTContext::UnwrapSimilarPointerTypes(QualType &T1, QualType &T2) { return false; } +bool ASTContext::hasSimilarType(QualType T1, QualType T2) { + while (true) { + Qualifiers Quals; + T1 = getUnqualifiedArrayType(T1, Quals); + T2 = getUnqualifiedArrayType(T2, Quals); + if (hasSameType(T1, T2)) + return true; + if (!UnwrapSimilarTypes(T1, T2)) + return false; + } +} + +bool ASTContext::hasCvrSimilarType(QualType T1, QualType T2) { + while (true) { + Qualifiers Quals1, Quals2; + T1 = getUnqualifiedArrayType(T1, Quals1); + T2 = getUnqualifiedArrayType(T2, Quals2); + + Quals1.removeCVRQualifiers(); + Quals2.removeCVRQualifiers(); + if (Quals1 != Quals2) + return false; + + if (hasSameType(T1, T2)) + return true; + + if (!UnwrapSimilarTypes(T1, T2)) + return false; + } +} + DeclarationNameInfo ASTContext::getNameForTemplate(TemplateName Name, SourceLocation NameLoc) const { @@ -5008,8 +5168,7 @@ TemplateName ASTContext::getCanonicalTemplateName(TemplateName Name) const { case TemplateName::QualifiedTemplate: case TemplateName::Template: { TemplateDecl *Template = Name.getAsTemplateDecl(); - if (TemplateTemplateParmDecl *TTP - = dyn_cast<TemplateTemplateParmDecl>(Template)) + if (auto *TTP = dyn_cast<TemplateTemplateParmDecl>(Template)) Template = getCanonicalTemplateTemplateParmDecl(TTP); // The canonical template name is the canonical template declaration. @@ -5061,7 +5220,7 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { return Arg; case TemplateArgument::Declaration: { - ValueDecl *D = cast<ValueDecl>(Arg.getAsDecl()->getCanonicalDecl()); + auto *D = cast<ValueDecl>(Arg.getAsDecl()->getCanonicalDecl()); return TemplateArgument(D, Arg.getParamTypeForDecl()); } @@ -5087,8 +5246,7 @@ ASTContext::getCanonicalTemplateArgument(const TemplateArgument &Arg) const { if (Arg.pack_size() == 0) return Arg; - TemplateArgument *CanonArgs - = new (*this) TemplateArgument[Arg.pack_size()]; + auto *CanonArgs = new (*this) TemplateArgument[Arg.pack_size()]; unsigned Idx = 0; for (TemplateArgument::pack_iterator A = Arg.pack_begin(), AEnd = Arg.pack_end(); @@ -5139,7 +5297,7 @@ ASTContext::getCanonicalNestedNameSpecifier(NestedNameSpecifier *NNS) const { // types, e.g., // typedef typename T::type T1; // typedef typename T1::type T2; - if (const DependentNameType *DNT = T->getAs<DependentNameType>()) + if (const auto *DNT = T->getAs<DependentNameType>()) return NestedNameSpecifier::Create(*this, DNT->getQualifier(), const_cast<IdentifierInfo *>(DNT->getIdentifier())); @@ -5163,7 +5321,7 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const { // Handle the non-qualified case efficiently. if (!T.hasLocalQualifiers()) { // Handle the common positive case fast. - if (const ArrayType *AT = dyn_cast<ArrayType>(T)) + if (const auto *AT = dyn_cast<ArrayType>(T)) return AT; } @@ -5183,7 +5341,7 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const { Qualifiers qs = split.Quals; // If we have a simple case, just return now. - const ArrayType *ATy = dyn_cast<ArrayType>(split.Ty); + const auto *ATy = dyn_cast<ArrayType>(split.Ty); if (!ATy || qs.empty()) return ATy; @@ -5191,17 +5349,16 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const { // qualifiers into the array element type and return a new array type. QualType NewEltTy = getQualifiedType(ATy->getElementType(), qs); - if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(ATy)) + if (const auto *CAT = dyn_cast<ConstantArrayType>(ATy)) return cast<ArrayType>(getConstantArrayType(NewEltTy, CAT->getSize(), CAT->getSizeModifier(), CAT->getIndexTypeCVRQualifiers())); - if (const IncompleteArrayType *IAT = dyn_cast<IncompleteArrayType>(ATy)) + if (const auto *IAT = dyn_cast<IncompleteArrayType>(ATy)) return cast<ArrayType>(getIncompleteArrayType(NewEltTy, IAT->getSizeModifier(), IAT->getIndexTypeCVRQualifiers())); - if (const DependentSizedArrayType *DSAT - = dyn_cast<DependentSizedArrayType>(ATy)) + if (const auto *DSAT = dyn_cast<DependentSizedArrayType>(ATy)) return cast<ArrayType>( getDependentSizedArrayType(NewEltTy, DSAT->getSizeExpr(), @@ -5209,7 +5366,7 @@ const ArrayType *ASTContext::getAsArrayType(QualType T) const { DSAT->getIndexTypeCVRQualifiers(), DSAT->getBracketsRange())); - const VariableArrayType *VAT = cast<VariableArrayType>(ATy); + const auto *VAT = cast<VariableArrayType>(ATy); return cast<ArrayType>(getVariableArrayType(NewEltTy, VAT->getSizeExpr(), VAT->getSizeModifier(), @@ -5303,7 +5460,7 @@ ASTContext::getConstantArrayElementCount(const ConstantArrayType *CA) const { /// getFloatingRank - Return a relative rank for floating point types. /// This routine will assert if passed a built-in type that isn't a float. static FloatingRank getFloatingRank(QualType T) { - if (const ComplexType *CT = T->getAs<ComplexType>()) + if (const auto *CT = T->getAs<ComplexType>()) return getFloatingRank(CT->getElementType()); assert(T->getAs<BuiltinType>() && "getFloatingRank(): not a floating type"); @@ -5396,14 +5553,20 @@ unsigned ASTContext::getIntegerRank(const Type *T) const { } } -/// \brief Whether this is a promotable bitfield reference according +/// Whether this is a promotable bitfield reference according /// to C99 6.3.1.1p2, bullet 2 (and GCC extensions). /// /// \returns the type this bit-field will promote to, or NULL if no /// promotion occurs. QualType ASTContext::isPromotableBitField(Expr *E) const { if (E->isTypeDependent() || E->isValueDependent()) - return QualType(); + return {}; + + // C++ [conv.prom]p5: + // If the bit-field has an enumerated type, it is treated as any other + // value of that type for promotion purposes. + if (getLangOpts().CPlusPlus && E->getType()->isEnumeralType()) + return {}; // FIXME: We should not do this unless E->refersToBitField() is true. This // matters in C where getSourceBitField() will find bit-fields for various @@ -5411,7 +5574,7 @@ QualType ASTContext::isPromotableBitField(Expr *E) const { FieldDecl *Field = E->getSourceBitField(); // FIXME: conditional bit-fields? if (!Field) - return QualType(); + return {}; QualType FT = Field->getType(); @@ -5431,18 +5594,20 @@ QualType ASTContext::isPromotableBitField(Expr *E) const { // // FIXME: C does not permit promotion of a 'long : 3' bitfield to int. // We perform that promotion here to match GCC and C++. + // FIXME: C does not permit promotion of an enum bit-field whose rank is + // greater than that of 'int'. We perform that promotion to match GCC. if (BitWidth < IntSize) return IntTy; if (BitWidth == IntSize) return FT->isSignedIntegerType() ? IntTy : UnsignedIntTy; - // Types bigger than int are not subject to promotions, and therefore act + // Bit-fields wider than int are not subject to promotions, and therefore act // like the base type. GCC has some weird bugs in this area that we // deliberately do not follow (GCC follows a pre-standard resolution to // C's DR315 which treats bit-width as being part of the type, and this leaks // into their semantics in some cases). - return QualType(); + return {}; } /// getPromotedIntegerType - Returns the type that Promotable will @@ -5451,10 +5616,10 @@ QualType ASTContext::isPromotableBitField(Expr *E) const { QualType ASTContext::getPromotedIntegerType(QualType Promotable) const { assert(!Promotable.isNull()); assert(Promotable->isPromotableIntegerType()); - if (const EnumType *ET = Promotable->getAs<EnumType>()) + if (const auto *ET = Promotable->getAs<EnumType>()) return ET->getDecl()->getPromotionType(); - if (const BuiltinType *BT = Promotable->getAs<BuiltinType>()) { + if (const auto *BT = Promotable->getAs<BuiltinType>()) { // C++ [conv.prom]: A prvalue of type char16_t, char32_t, or wchar_t // (3.9.1) can be converted to a prvalue of the first of the following // types that can represent all the values of its underlying type: @@ -5463,6 +5628,7 @@ QualType ASTContext::getPromotedIntegerType(QualType Promotable) const { // FIXME: Is there some better way to compute this? if (BT->getKind() == BuiltinType::WChar_S || BT->getKind() == BuiltinType::WChar_U || + BT->getKind() == BuiltinType::Char8 || BT->getKind() == BuiltinType::Char16 || BT->getKind() == BuiltinType::Char32) { bool FromIsSigned = BT->getKind() == BuiltinType::WChar_S; @@ -5489,7 +5655,7 @@ QualType ASTContext::getPromotedIntegerType(QualType Promotable) const { return (PromotableSize != IntSize) ? IntTy : UnsignedIntTy; } -/// \brief Recurses in pointer/array types until it finds an objc retainable +/// Recurses in pointer/array types until it finds an objc retainable /// type and returns its ownership. Qualifiers::ObjCLifetime ASTContext::getInnerObjCOwnership(QualType T) const { while (!T.isNull()) { @@ -5497,9 +5663,9 @@ Qualifiers::ObjCLifetime ASTContext::getInnerObjCOwnership(QualType T) const { return T.getObjCLifetime(); if (T->isArrayType()) T = getBaseElementType(T); - else if (const PointerType *PT = T->getAs<PointerType>()) + else if (const auto *PT = T->getAs<PointerType>()) T = PT->getPointeeType(); - else if (const ReferenceType *RT = T->getAs<ReferenceType>()) + else if (const auto *RT = T->getAs<ReferenceType>()) T = RT->getPointeeType(); else break; @@ -5524,9 +5690,9 @@ int ASTContext::getIntegerTypeOrder(QualType LHS, QualType RHS) const { const Type *RHSC = getCanonicalType(RHS).getTypePtr(); // Unwrap enums to their underlying type. - if (const EnumType *ET = dyn_cast<EnumType>(LHSC)) + if (const auto *ET = dyn_cast<EnumType>(LHSC)) LHSC = getIntegerTypeForEnum(ET); - if (const EnumType *ET = dyn_cast<EnumType>(RHSC)) + if (const auto *ET = dyn_cast<EnumType>(RHSC)) RHSC = getIntegerTypeForEnum(ET); if (LHSC == RHSC) return 0; @@ -5633,10 +5799,10 @@ QualType ASTContext::getObjCSuperType() const { } void ASTContext::setCFConstantStringType(QualType T) { - const TypedefType *TD = T->getAs<TypedefType>(); + const auto *TD = T->getAs<TypedefType>(); assert(TD && "Invalid CFConstantStringType"); CFConstantStringTypeDecl = cast<TypedefDecl>(TD->getDecl()); - auto TagType = + const auto *TagType = CFConstantStringTypeDecl->getUnderlyingType()->getAs<RecordType>(); assert(TagType && "Invalid CFConstantStringType"); CFConstantStringTagDecl = TagType->getDecl(); @@ -5717,7 +5883,7 @@ QualType ASTContext::getBlockDescriptorExtendedType() const { } TargetInfo::OpenCLTypeKind ASTContext::getOpenCLTypeKind(const Type *T) const { - auto BT = dyn_cast<BuiltinType>(T); + const auto *BT = dyn_cast<BuiltinType>(T); if (!BT) { if (isa<PipeType>(T)) @@ -5768,6 +5934,11 @@ bool ASTContext::BlockRequiresCopying(QualType Ty, return true; } + // The block needs copy/destroy helpers if Ty is non-trivial to destructively + // move or destroy. + if (Ty.isNonTrivialToPrimitiveDestructiveMove() || Ty.isDestructedType()) + return true; + if (!Ty->isObjCRetainableType()) return false; Qualifiers qs = Ty.getQualifiers(); @@ -5781,13 +5952,12 @@ bool ASTContext::BlockRequiresCopying(QualType Ty, case Qualifiers::OCL_ExplicitNone: case Qualifiers::OCL_Autoreleasing: return false; - - // Tell the runtime that this is ARC __weak, called by the - // byref routines. + + // These cases should have been taken care of when checking the type's + // non-triviality. case Qualifiers::OCL_Weak: - // ARC __strong __block variables need to be retained. case Qualifiers::OCL_Strong: - return true; + llvm_unreachable("impossible"); } llvm_unreachable("fell out of lifetime switch!"); } @@ -5827,7 +5997,7 @@ TypedefDecl *ASTContext::getObjCInstanceTypeDecl() { // This returns true if a type has been typedefed to BOOL: // typedef <type> BOOL; static bool isTypeTypedefedAsBOOL(QualType T) { - if (const TypedefType *TT = dyn_cast<TypedefType>(T)) + if (const auto *TT = dyn_cast<TypedefType>(T)) if (IdentifierInfo *II = TT->getDecl()->getIdentifier()) return II->isStr("BOOL"); @@ -5879,8 +6049,7 @@ ASTContext::getInlineVariableDefinitionKind(const VarDecl *VD) const { return InlineVariableDefinitionKind::WeakUnknown; } -static inline -std::string charUnitsToString(const CharUnits &CU) { +static std::string charUnitsToString(const CharUnits &CU) { return llvm::itostr(CU.getQuantity()); } @@ -5921,8 +6090,8 @@ std::string ASTContext::getObjCEncodingForBlock(const BlockExpr *Expr) const { ParmOffset = PtrSize; for (auto PVDecl : Decl->parameters()) { QualType PType = PVDecl->getOriginalType(); - if (const ArrayType *AT = - dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) { + if (const auto *AT = + dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) { // Use array's original type only if it has known number of // elements. if (!isa<ConstantArrayType>(AT)) @@ -5964,8 +6133,8 @@ ASTContext::getObjCEncodingForFunctionDecl(const FunctionDecl *Decl) const { // Argument types. for (auto PVDecl : Decl->parameters()) { QualType PType = PVDecl->getOriginalType(); - if (const ArrayType *AT = - dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) { + if (const auto *AT = + dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) { // Use array's original type only if it has known number of // elements. if (!isa<ConstantArrayType>(AT)) @@ -6034,8 +6203,8 @@ std::string ASTContext::getObjCEncodingForMethodDecl(const ObjCMethodDecl *Decl, E = Decl->sel_param_end(); PI != E; ++PI) { const ParmVarDecl *PVDecl = *PI; QualType PType = PVDecl->getOriginalType(); - if (const ArrayType *AT = - dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) { + if (const auto *AT = + dyn_cast<ArrayType>(PType->getCanonicalTypeInternal())) { // Use array's original type only if it has known number of // elements. if (!isa<ConstantArrayType>(AT)) @@ -6057,13 +6226,12 @@ ASTContext::getObjCPropertyImplDeclForPropertyDecl( const Decl *Container) const { if (!Container) return nullptr; - if (const ObjCCategoryImplDecl *CID = - dyn_cast<ObjCCategoryImplDecl>(Container)) { + if (const auto *CID = dyn_cast<ObjCCategoryImplDecl>(Container)) { for (auto *PID : CID->property_impls()) if (PID->getPropertyDecl() == PD) return PID; } else { - const ObjCImplementationDecl *OID=cast<ObjCImplementationDecl>(Container); + const auto *OID = cast<ObjCImplementationDecl>(Container); for (auto *PID : OID->property_impls()) if (PID->getPropertyDecl() == PD) return PID; @@ -6170,7 +6338,7 @@ ASTContext::getObjCEncodingForPropertyDecl(const ObjCPropertyDecl *PD, /// 'i' or 'I' instead if encoding a struct field, or a pointer! void ASTContext::getLegacyIntegralTypeEncoding (QualType &PointeeTy) const { if (isa<TypedefType>(PointeeTy.getTypePtr())) { - if (const BuiltinType *BT = PointeeTy->getAs<BuiltinType>()) { + if (const auto *BT = PointeeTy->getAs<BuiltinType>()) { if (BT->getKind() == BuiltinType::ULong && getIntWidth(PointeeTy) == 32) PointeeTy = UnsignedIntTy; else @@ -6207,6 +6375,7 @@ static char getObjCEncodingForPrimitiveKind(const ASTContext *C, switch (kind) { case BuiltinType::Void: return 'v'; case BuiltinType::Bool: return 'B'; + case BuiltinType::Char8: case BuiltinType::Char_U: case BuiltinType::UChar: return 'C'; case BuiltinType::Char16: @@ -6235,6 +6404,30 @@ static char getObjCEncodingForPrimitiveKind(const ASTContext *C, case BuiltinType::Float16: case BuiltinType::Float128: case BuiltinType::Half: + case BuiltinType::ShortAccum: + case BuiltinType::Accum: + case BuiltinType::LongAccum: + case BuiltinType::UShortAccum: + case BuiltinType::UAccum: + case BuiltinType::ULongAccum: + case BuiltinType::ShortFract: + case BuiltinType::Fract: + case BuiltinType::LongFract: + case BuiltinType::UShortFract: + case BuiltinType::UFract: + case BuiltinType::ULongFract: + case BuiltinType::SatShortAccum: + case BuiltinType::SatAccum: + case BuiltinType::SatLongAccum: + case BuiltinType::SatUShortAccum: + case BuiltinType::SatUAccum: + case BuiltinType::SatULongAccum: + case BuiltinType::SatShortFract: + case BuiltinType::SatFract: + case BuiltinType::SatLongFract: + case BuiltinType::SatUShortFract: + case BuiltinType::SatUFract: + case BuiltinType::SatULongFract: // FIXME: potentially need @encodes for these! return ' '; @@ -6270,7 +6463,7 @@ static char ObjCEncodingForEnumType(const ASTContext *C, const EnumType *ET) { return 'i'; // The encoding of a fixed enum type matches its fixed underlying type. - const BuiltinType *BT = Enum->getIntegerType()->castAs<BuiltinType>(); + const auto *BT = Enum->getIntegerType()->castAs<BuiltinType>(); return getObjCEncodingForPrimitiveKind(C, BT->getKind()); } @@ -6307,10 +6500,10 @@ static void EncodeBitField(const ASTContext *Ctx, std::string& S, S += llvm::utostr(Offset); - if (const EnumType *ET = T->getAs<EnumType>()) + if (const auto *ET = T->getAs<EnumType>()) S += ObjCEncodingForEnumType(Ctx, ET); else { - const BuiltinType *BT = T->castAs<BuiltinType>(); + const auto *BT = T->castAs<BuiltinType>(); S += getObjCEncodingForPrimitiveKind(Ctx, BT->getKind()); } } @@ -6335,21 +6528,21 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, case Type::Enum: if (FD && FD->isBitField()) return EncodeBitField(this, S, T, FD); - if (const BuiltinType *BT = dyn_cast<BuiltinType>(CT)) + if (const auto *BT = dyn_cast<BuiltinType>(CT)) S += getObjCEncodingForPrimitiveKind(this, BT->getKind()); else S += ObjCEncodingForEnumType(this, cast<EnumType>(CT)); return; case Type::Complex: { - const ComplexType *CT = T->castAs<ComplexType>(); + const auto *CT = T->castAs<ComplexType>(); S += 'j'; getObjCEncodingForTypeImpl(CT->getElementType(), S, false, false, nullptr); return; } case Type::Atomic: { - const AtomicType *AT = T->castAs<AtomicType>(); + const auto *AT = T->castAs<AtomicType>(); S += 'A'; getObjCEncodingForTypeImpl(AT->getValueType(), S, false, false, nullptr); return; @@ -6361,7 +6554,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, case Type::RValueReference: { QualType PointeeTy; if (isa<PointerType>(CT)) { - const PointerType *PT = T->castAs<PointerType>(); + const auto *PT = T->castAs<PointerType>(); if (PT->isObjCSelType()) { S += ':'; return; @@ -6405,7 +6598,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, S += '*'; return; } - } else if (const RecordType *RTy = PointeeTy->getAs<RecordType>()) { + } else if (const auto *RTy = PointeeTy->getAs<RecordType>()) { // GCC binary compat: Need to convert "struct objc_class *" to "#". if (RTy->getDecl()->getIdentifier() == &Idents.get("objc_class")) { S += '#'; @@ -6430,7 +6623,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, case Type::ConstantArray: case Type::IncompleteArray: case Type::VariableArray: { - const ArrayType *AT = cast<ArrayType>(CT); + const auto *AT = cast<ArrayType>(CT); if (isa<IncompleteArrayType>(AT) && !StructField) { // Incomplete arrays are encoded as a pointer to the array element. @@ -6441,7 +6634,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, } else { S += '['; - if (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(AT)) + if (const auto *CAT = dyn_cast<ConstantArrayType>(AT)) S += llvm::utostr(CAT->getSize().getZExtValue()); else { //Variable length arrays are encoded as a regular array with 0 elements. @@ -6470,8 +6663,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, // Anonymous structures print as '?' if (const IdentifierInfo *II = RDecl->getIdentifier()) { S += II->getName(); - if (ClassTemplateSpecializationDecl *Spec - = dyn_cast<ClassTemplateSpecializationDecl>(RDecl)) { + if (const auto *Spec = dyn_cast<ClassTemplateSpecializationDecl>(RDecl)) { const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs(); llvm::raw_string_ostream OS(S); printTemplateArgumentList(OS, TemplateArgs.asArray(), @@ -6513,10 +6705,10 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, } case Type::BlockPointer: { - const BlockPointerType *BT = T->castAs<BlockPointerType>(); + const auto *BT = T->castAs<BlockPointerType>(); S += "@?"; // Unlike a pointer-to-function, which is "^?". if (EncodeBlockParameters) { - const FunctionType *FT = BT->getPointeeType()->castAs<FunctionType>(); + const auto *FT = BT->getPointeeType()->castAs<FunctionType>(); S += '<'; // Block return type @@ -6528,7 +6720,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, // Block self S += "@?"; // Block parameters - if (const FunctionProtoType *FPT = dyn_cast<FunctionProtoType>(FT)) { + if (const auto *FPT = dyn_cast<FunctionProtoType>(FT)) { for (const auto &I : FPT->param_types()) getObjCEncodingForTypeImpl( I, S, ExpandPointedToStructures, ExpandStructures, FD, @@ -6552,7 +6744,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, S += "{objc_class=}"; return; } - // TODO: Double check to make sure this intentially falls through. + // TODO: Double check to make sure this intentionally falls through. LLVM_FALLTHROUGH; } @@ -6567,7 +6759,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, SmallVector<const ObjCIvarDecl*, 32> Ivars; DeepCollectObjCIvars(OI, true, Ivars); for (unsigned i = 0, e = Ivars.size(); i != e; ++i) { - const FieldDecl *Field = cast<FieldDecl>(Ivars[i]); + const FieldDecl *Field = Ivars[i]; if (Field->isBitField()) getObjCEncodingForTypeImpl(Field->getType(), S, false, true, Field); else @@ -6582,7 +6774,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, } case Type::ObjCObjectPointer: { - const ObjCObjectPointerType *OPT = T->castAs<ObjCObjectPointerType>(); + const auto *OPT = T->castAs<ObjCObjectPointerType>(); if (OPT->isObjCIdType()) { S += '@'; return; @@ -6591,7 +6783,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) { // FIXME: Consider if we need to output qualifiers for 'Class<p>'. // Since this is a binary compatibility issue, need to consult with runtime - // folks. Fortunately, this is a *very* obsure construct. + // folks. Fortunately, this is a *very* obscure construct. S += '#'; return; } @@ -6628,7 +6820,7 @@ void ASTContext::getObjCEncodingForTypeImpl(QualType T, std::string& S, SmallVector<const ObjCIvarDecl*, 32> Ivars; DeepCollectObjCIvars(OI, true, Ivars); for (unsigned i = 0, e = Ivars.size(); i != e; ++i) { - if (cast<FieldDecl>(Ivars[i]) == FD) { + if (Ivars[i] == FD) { S += '{'; S += OI->getObjCRuntimeNameAsString(); S += '}'; @@ -6702,7 +6894,7 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, if (!RDecl->getDefinition() || RDecl->getDefinition()->isInvalidDecl()) return; - CXXRecordDecl *CXXRec = dyn_cast<CXXRecordDecl>(RDecl); + const auto *CXXRec = dyn_cast<CXXRecordDecl>(RDecl); std::multimap<uint64_t, NamedDecl *> FieldOrBaseOffsets; const ASTRecordLayout &layout = getASTRecordLayout(RDecl); @@ -6795,7 +6987,7 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, if (!dcl) break; // reached end of structure. - if (CXXRecordDecl *base = dyn_cast<CXXRecordDecl>(dcl)) { + if (auto *base = dyn_cast<CXXRecordDecl>(dcl)) { // We expand the bases without their virtual bases since those are going // in the initial structure. Note that this differs from gcc which // expands virtual bases each time one is encountered in the hierarchy, @@ -6807,7 +6999,7 @@ void ASTContext::getObjCEncodingForStructureImpl(RecordDecl *RDecl, CurOffs += toBits(getASTRecordLayout(base).getNonVirtualSize()); #endif } else { - FieldDecl *field = cast<FieldDecl>(dcl); + const auto *field = cast<FieldDecl>(dcl); if (FD) { S += '"'; S += field->getNameAsString(); @@ -7250,6 +7442,10 @@ TypedefDecl *ASTContext::getBuiltinMSVaListDecl() const { return BuiltinMSVaListDecl; } +bool ASTContext::canBuiltinBeRedeclared(const FunctionDecl *FD) const { + return BuiltinInfo.canBeRedeclared(FD->getBuiltinID()); +} + void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) { assert(ObjCConstantStringType.isNull() && "'NSConstantString' type already set!"); @@ -7257,7 +7453,7 @@ void ASTContext::setObjCConstantStringInterface(ObjCInterfaceDecl *Decl) { ObjCConstantStringType = getObjCInterfaceType(Decl); } -/// \brief Retrieve the template name that corresponds to a non-empty +/// Retrieve the template name that corresponds to a non-empty /// lookup. TemplateName ASTContext::getOverloadedTemplateName(UnresolvedSetIterator Begin, @@ -7267,12 +7463,13 @@ ASTContext::getOverloadedTemplateName(UnresolvedSetIterator Begin, void *memory = Allocate(sizeof(OverloadedTemplateStorage) + size * sizeof(FunctionTemplateDecl*)); - OverloadedTemplateStorage *OT = new(memory) OverloadedTemplateStorage(size); + auto *OT = new (memory) OverloadedTemplateStorage(size); NamedDecl **Storage = OT->getStorage(); for (UnresolvedSetIterator I = Begin; I != End; ++I) { NamedDecl *D = *I; assert(isa<FunctionTemplateDecl>(D) || + isa<UnresolvedUsingValueDecl>(D) || (isa<UsingShadowDecl>(D) && isa<FunctionTemplateDecl>(D->getUnderlyingDecl()))); *Storage++ = D; @@ -7281,7 +7478,7 @@ ASTContext::getOverloadedTemplateName(UnresolvedSetIterator Begin, return TemplateName(OT); } -/// \brief Retrieve the template name that represents a qualified +/// Retrieve the template name that represents a qualified /// template name such as \c std::vector. TemplateName ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, @@ -7305,7 +7502,7 @@ ASTContext::getQualifiedTemplateName(NestedNameSpecifier *NNS, return TemplateName(QTN); } -/// \brief Retrieve the template name that represents a dependent +/// Retrieve the template name that represents a dependent /// template name such as \c MetaFun::template apply. TemplateName ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, @@ -7341,7 +7538,7 @@ ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, return TemplateName(QTN); } -/// \brief Retrieve the template name that represents a dependent +/// Retrieve the template name that represents a dependent /// template name such as \c MetaFun::template operator+. TemplateName ASTContext::getDependentTemplateName(NestedNameSpecifier *NNS, @@ -7399,7 +7596,7 @@ ASTContext::getSubstTemplateTemplateParm(TemplateTemplateParmDecl *param, TemplateName ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param, const TemplateArgument &ArgPack) const { - ASTContext &Self = const_cast<ASTContext &>(*this); + auto &Self = const_cast<ASTContext &>(*this); llvm::FoldingSetNodeID ID; SubstTemplateTemplateParmPackStorage::Profile(ID, Self, Param, ArgPack); @@ -7422,7 +7619,7 @@ ASTContext::getSubstTemplateTemplateParmPack(TemplateTemplateParmDecl *Param, /// is actually a value of type @c TargetInfo::IntType. CanQualType ASTContext::getFromTargetType(unsigned Type) const { switch (Type) { - case TargetInfo::NoInt: return CanQualType(); + case TargetInfo::NoInt: return {}; case TargetInfo::SignedChar: return SignedCharTy; case TargetInfo::UnsignedChar: return UnsignedCharTy; case TargetInfo::SignedShort: return ShortTy; @@ -7465,7 +7662,7 @@ Qualifiers::GC ASTContext::getObjCGCAttrKind(QualType Ty) const { // pointer. #ifndef NDEBUG QualType CT = Ty->getCanonicalTypeInternal(); - while (const ArrayType *AT = dyn_cast<ArrayType>(CT)) + while (const auto *AT = dyn_cast<ArrayType>(CT)) CT = AT->getElementType(); assert(CT->isAnyPointerType() || CT->isBlockPointerType()); #endif @@ -7496,8 +7693,8 @@ bool ASTContext::areCompatibleVectorTypes(QualType FirstVec, // Treat Neon vector types and most AltiVec vector types as if they are the // equivalent GCC vector types. - const VectorType *First = FirstVec->getAs<VectorType>(); - const VectorType *Second = SecondVec->getAs<VectorType>(); + const auto *First = FirstVec->getAs<VectorType>(); + const auto *Second = SecondVec->getAs<VectorType>(); if (First->getNumElements() == Second->getNumElements() && hasSameType(First->getElementType(), Second->getElementType()) && First->getVectorKind() != VectorType::AltiVecPixel && @@ -7530,8 +7727,8 @@ ASTContext::ProtocolCompatibleWithProtocol(ObjCProtocolDecl *lProto, /// Class<pr1, ...>. bool ASTContext::ObjCQualifiedClassTypesAreCompatible(QualType lhs, QualType rhs) { - const ObjCObjectPointerType *lhsQID = lhs->getAs<ObjCObjectPointerType>(); - const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>(); + const auto *lhsQID = lhs->getAs<ObjCObjectPointerType>(); + const auto *rhsOPT = rhs->getAs<ObjCObjectPointerType>(); assert((lhsQID && rhsOPT) && "ObjCQualifiedClassTypesAreCompatible"); for (auto *lhsProto : lhsQID->quals()) { @@ -7561,7 +7758,7 @@ bool ASTContext::ObjCQualifiedIdTypesAreCompatible(QualType lhs, QualType rhs, return true; if (const ObjCObjectPointerType *lhsQID = lhs->getAsObjCQualifiedIdType()) { - const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>(); + const auto *rhsOPT = rhs->getAs<ObjCObjectPointerType>(); if (!rhsOPT) return false; @@ -7847,14 +8044,14 @@ void getIntersectionOfProtocols(ASTContext &Context, static bool canAssignObjCObjectTypes(ASTContext &ctx, QualType lhs, QualType rhs) { // Common case: two object pointers. - const ObjCObjectPointerType *lhsOPT = lhs->getAs<ObjCObjectPointerType>(); - const ObjCObjectPointerType *rhsOPT = rhs->getAs<ObjCObjectPointerType>(); + const auto *lhsOPT = lhs->getAs<ObjCObjectPointerType>(); + const auto *rhsOPT = rhs->getAs<ObjCObjectPointerType>(); if (lhsOPT && rhsOPT) return ctx.canAssignObjCInterfaces(lhsOPT, rhsOPT); // Two block pointers. - const BlockPointerType *lhsBlock = lhs->getAs<BlockPointerType>(); - const BlockPointerType *rhsBlock = rhs->getAs<BlockPointerType>(); + const auto *lhsBlock = lhs->getAs<BlockPointerType>(); + const auto *rhsBlock = rhs->getAs<BlockPointerType>(); if (lhsBlock && rhsBlock) return ctx.typesAreBlockPointerCompatible(lhs, rhs); @@ -7914,7 +8111,7 @@ QualType ASTContext::areCommonBaseCompatible( const ObjCInterfaceDecl* RDecl = RHS->getInterface(); if (!LDecl || !RDecl) - return QualType(); + return {}; // When either LHS or RHS is a kindof type, we should return a kindof type. // For example, for common base of kindof(ASub1) and kindof(ASub2), we return @@ -7939,7 +8136,7 @@ QualType ASTContext::areCommonBaseCompatible( if (!sameObjCTypeArgs(*this, LHS->getInterface(), LHS->getTypeArgs(), RHS->getTypeArgs(), /*stripKindOf=*/true)) - return QualType(); + return {}; } else if (LHS->isSpecialized() != RHS->isSpecialized()) { // If only one has type arguments, the result will not have type // arguments. @@ -7990,7 +8187,7 @@ QualType ASTContext::areCommonBaseCompatible( if (!sameObjCTypeArgs(*this, LHS->getInterface(), LHS->getTypeArgs(), RHS->getTypeArgs(), /*stripKindOf=*/true)) - return QualType(); + return {}; } else if (LHS->isSpecialized() != RHS->isSpecialized()) { // If only one has type arguments, the result will not have type // arguments. @@ -8025,7 +8222,7 @@ QualType ASTContext::areCommonBaseCompatible( RHS = RHSSuperType->castAs<ObjCObjectType>(); } - return QualType(); + return {}; } bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS, @@ -8092,8 +8289,8 @@ bool ASTContext::canAssignObjCInterfaces(const ObjCObjectType *LHS, bool ASTContext::areComparableObjCPointerTypes(QualType LHS, QualType RHS) { // get the "pointed to" types - const ObjCObjectPointerType *LHSOPT = LHS->getAs<ObjCObjectPointerType>(); - const ObjCObjectPointerType *RHSOPT = RHS->getAs<ObjCObjectPointerType>(); + const auto *LHSOPT = LHS->getAs<ObjCObjectPointerType>(); + const auto *RHSOPT = RHS->getAs<ObjCObjectPointerType>(); if (!LHSOPT || !RHSOPT) return false; @@ -8146,7 +8343,7 @@ QualType ASTContext::mergeTransparentUnionType(QualType T, QualType SubType, } } - return QualType(); + return {}; } /// mergeFunctionParameterTypes - merge two types which appear as function @@ -8173,10 +8370,10 @@ QualType ASTContext::mergeFunctionParameterTypes(QualType lhs, QualType rhs, QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, bool OfBlockPointer, bool Unqualified) { - const FunctionType *lbase = lhs->getAs<FunctionType>(); - const FunctionType *rbase = rhs->getAs<FunctionType>(); - const FunctionProtoType *lproto = dyn_cast<FunctionProtoType>(lbase); - const FunctionProtoType *rproto = dyn_cast<FunctionProtoType>(rbase); + const auto *lbase = lhs->getAs<FunctionType>(); + const auto *rbase = rhs->getAs<FunctionType>(); + const auto *lproto = dyn_cast<FunctionProtoType>(lbase); + const auto *rproto = dyn_cast<FunctionProtoType>(rbase); bool allLTypes = true; bool allRTypes = true; @@ -8193,7 +8390,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, else retType = mergeTypes(lbase->getReturnType(), rbase->getReturnType(), false, Unqualified); - if (retType.isNull()) return QualType(); + if (retType.isNull()) + return {}; if (Unqualified) retType = retType.getUnqualifiedType(); @@ -8219,18 +8417,20 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, // Compatible functions must have compatible calling conventions if (lbaseInfo.getCC() != rbaseInfo.getCC()) - return QualType(); + return {}; // Regparm is part of the calling convention. if (lbaseInfo.getHasRegParm() != rbaseInfo.getHasRegParm()) - return QualType(); + return {}; if (lbaseInfo.getRegParm() != rbaseInfo.getRegParm()) - return QualType(); + return {}; if (lbaseInfo.getProducesResult() != rbaseInfo.getProducesResult()) - return QualType(); + return {}; if (lbaseInfo.getNoCallerSavedRegs() != rbaseInfo.getNoCallerSavedRegs()) - return QualType(); + return {}; + if (lbaseInfo.getNoCfCheck() != rbaseInfo.getNoCfCheck()) + return {}; // FIXME: some uses, e.g. conditional exprs, really want this to be 'both'. bool NoReturn = lbaseInfo.getNoReturn() || rbaseInfo.getNoReturn(); @@ -8247,20 +8447,20 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, "C++ shouldn't be here"); // Compatible functions must have the same number of parameters if (lproto->getNumParams() != rproto->getNumParams()) - return QualType(); + return {}; // Variadic and non-variadic functions aren't compatible if (lproto->isVariadic() != rproto->isVariadic()) - return QualType(); + return {}; if (lproto->getTypeQuals() != rproto->getTypeQuals()) - return QualType(); + return {}; SmallVector<FunctionProtoType::ExtParameterInfo, 4> newParamInfos; bool canUseLeft, canUseRight; if (!mergeExtParameterInfo(lproto, rproto, canUseLeft, canUseRight, newParamInfos)) - return QualType(); + return {}; if (!canUseLeft) allLTypes = false; @@ -8275,7 +8475,7 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, QualType paramType = mergeFunctionParameterTypes( lParamType, rParamType, OfBlockPointer, Unqualified); if (paramType.isNull()) - return QualType(); + return {}; if (Unqualified) paramType = paramType.getUnqualifiedType(); @@ -8308,7 +8508,8 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, const FunctionProtoType *proto = lproto ? lproto : rproto; if (proto) { assert(!proto->hasExceptionSpec() && "C++ shouldn't be here"); - if (proto->isVariadic()) return QualType(); + if (proto->isVariadic()) + return {}; // Check that the types are compatible with the types that // would result from default argument promotions (C99 6.7.5.3p15). // The only types actually affected are promotable integer @@ -8319,15 +8520,15 @@ QualType ASTContext::mergeFunctionTypes(QualType lhs, QualType rhs, // Look at the converted type of enum types, since that is the type used // to pass enum values. - if (const EnumType *Enum = paramTy->getAs<EnumType>()) { + if (const auto *Enum = paramTy->getAs<EnumType>()) { paramTy = Enum->getDecl()->getIntegerType(); if (paramTy.isNull()) - return QualType(); + return {}; } if (paramTy->isPromotableIntegerType() || getCanonicalType(paramTy).getUnqualifiedType() == FloatTy) - return QualType(); + return {}; } if (allLTypes) return lhs; @@ -8351,7 +8552,8 @@ static QualType mergeEnumWithInteger(ASTContext &Context, const EnumType *ET, // Compatibility is based on the underlying type, not the promotion // type. QualType underlyingType = ET->getDecl()->getIntegerType(); - if (underlyingType.isNull()) return QualType(); + if (underlyingType.isNull()) + return {}; if (Context.hasSameType(underlyingType, other)) return other; @@ -8361,7 +8563,7 @@ static QualType mergeEnumWithInteger(ASTContext &Context, const EnumType *ET, Context.getTypeSize(underlyingType) == Context.getTypeSize(other)) return other; - return QualType(); + return {}; } QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, @@ -8397,7 +8599,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, LQuals.getAddressSpace() != RQuals.getAddressSpace() || LQuals.getObjCLifetime() != RQuals.getObjCLifetime() || LQuals.hasUnaligned() != RQuals.hasUnaligned()) - return QualType(); + return {}; // Exactly one GC qualifier difference is allowed: __strong is // okay if the other type has no GC qualifier but is an Objective @@ -8409,7 +8611,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, assert((GC_L != GC_R) && "unequal qualifier sets had only equal elements"); if (GC_L == Qualifiers::Weak || GC_R == Qualifiers::Weak) - return QualType(); + return {}; if (GC_L == Qualifiers::Strong && RHSCan->isObjCObjectPointerType()) { return mergeTypes(LHS, getObjCGCQualType(RHS, Qualifiers::Strong)); @@ -8417,7 +8619,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, if (GC_R == Qualifiers::Strong && LHSCan->isObjCObjectPointerType()) { return mergeTypes(getObjCGCQualType(LHS, Qualifiers::Strong), RHS); } - return QualType(); + return {}; } // Okay, qualifiers are equal. @@ -8448,7 +8650,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, if (LHSClass != RHSClass) { // 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>()) { + if (const auto *ETy = LHS->getAs<EnumType>()) { return mergeEnumWithInteger(*this, ETy, RHS, false); } if (const EnumType* ETy = RHS->getAs<EnumType>()) { @@ -8462,7 +8664,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, return RHS; } - return QualType(); + return {}; } // The canonical type classes match. @@ -8500,7 +8702,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, } QualType ResultType = mergeTypes(LHSPointee, RHSPointee, false, Unqualified); - if (ResultType.isNull()) return QualType(); + if (ResultType.isNull()) + return {}; if (getCanonicalType(LHSPointee) == getCanonicalType(ResultType)) return LHS; if (getCanonicalType(RHSPointee) == getCanonicalType(ResultType)) @@ -8522,7 +8725,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, // Blocks can't be an expression in a ternary operator (OpenCL v2.0 // 6.12.5) thus the following check is asymmetric. if (!LHSPteeQual.isAddressSpaceSupersetOf(RHSPteeQual)) - return QualType(); + return {}; LHSPteeQual.removeAddressSpace(); RHSPteeQual.removeAddressSpace(); LHSPointee = @@ -8532,7 +8735,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, } QualType ResultType = mergeTypes(LHSPointee, RHSPointee, OfBlockPointer, Unqualified); - if (ResultType.isNull()) return QualType(); + if (ResultType.isNull()) + return {}; if (getCanonicalType(LHSPointee) == getCanonicalType(ResultType)) return LHS; if (getCanonicalType(RHSPointee) == getCanonicalType(ResultType)) @@ -8550,7 +8754,8 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, } QualType ResultType = mergeTypes(LHSValue, RHSValue, false, Unqualified); - if (ResultType.isNull()) return QualType(); + if (ResultType.isNull()) + return {}; if (getCanonicalType(LHSValue) == getCanonicalType(ResultType)) return LHS; if (getCanonicalType(RHSValue) == getCanonicalType(ResultType)) @@ -8562,7 +8767,7 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, const ConstantArrayType* LCAT = getAsConstantArrayType(LHS); const ConstantArrayType* RCAT = getAsConstantArrayType(RHS); if (LCAT && RCAT && RCAT->getSize() != LCAT->getSize()) - return QualType(); + return {}; QualType LHSElem = getAsArrayType(LHS)->getElementType(); QualType RHSElem = getAsArrayType(RHS)->getElementType(); @@ -8572,7 +8777,40 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, } QualType ResultType = mergeTypes(LHSElem, RHSElem, false, Unqualified); - if (ResultType.isNull()) return QualType(); + if (ResultType.isNull()) + return {}; + + const VariableArrayType* LVAT = getAsVariableArrayType(LHS); + const VariableArrayType* RVAT = getAsVariableArrayType(RHS); + + // If either side is a variable array, and both are complete, check whether + // the current dimension is definite. + if (LVAT || RVAT) { + auto SizeFetch = [this](const VariableArrayType* VAT, + const ConstantArrayType* CAT) + -> std::pair<bool,llvm::APInt> { + if (VAT) { + llvm::APSInt TheInt; + Expr *E = VAT->getSizeExpr(); + if (E && E->isIntegerConstantExpr(TheInt, *this)) + return std::make_pair(true, TheInt); + else + return std::make_pair(false, TheInt); + } else if (CAT) { + return std::make_pair(true, CAT->getSize()); + } else { + return std::make_pair(false, llvm::APInt()); + } + }; + + bool HaveLSize, HaveRSize; + llvm::APInt LSize, RSize; + std::tie(HaveLSize, LSize) = SizeFetch(LVAT, LCAT); + std::tie(HaveRSize, RSize) = SizeFetch(RVAT, RCAT); + if (HaveLSize && HaveRSize && !llvm::APInt::isSameValue(LSize, RSize)) + return {}; // Definite, but unequal, array dimension + } + if (LCAT && getCanonicalType(LHSElem) == getCanonicalType(ResultType)) return LHS; if (RCAT && getCanonicalType(RHSElem) == getCanonicalType(ResultType)) @@ -8581,8 +8819,6 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, ArrayType::ArraySizeModifier(), 0); if (RCAT) return getConstantArrayType(ResultType, RCAT->getSize(), ArrayType::ArraySizeModifier(), 0); - const VariableArrayType* LVAT = getAsVariableArrayType(LHS); - const VariableArrayType* RVAT = getAsVariableArrayType(RHS); if (LVAT && getCanonicalType(LHSElem) == getCanonicalType(ResultType)) return LHS; if (RVAT && getCanonicalType(RHSElem) == getCanonicalType(ResultType)) @@ -8608,29 +8844,29 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, return mergeFunctionTypes(LHS, RHS, OfBlockPointer, Unqualified); case Type::Record: case Type::Enum: - return QualType(); + return {}; case Type::Builtin: // Only exactly equal builtin types are compatible, which is tested above. - return QualType(); + return {}; case Type::Complex: // Distinct complex types are incompatible. - return QualType(); + return {}; case Type::Vector: // FIXME: The merged type should be an ExtVector! if (areCompatVectorTypes(LHSCan->getAs<VectorType>(), RHSCan->getAs<VectorType>())) return LHS; - return QualType(); + return {}; case Type::ObjCObject: { // Check if the types are assignment compatible. // FIXME: This should be type compatibility, e.g. whether // "LHS x; RHS x;" at global scope is legal. - const ObjCObjectType* LHSIface = LHS->getAs<ObjCObjectType>(); - const ObjCObjectType* RHSIface = RHS->getAs<ObjCObjectType>(); + const auto *LHSIface = LHS->getAs<ObjCObjectType>(); + const auto *RHSIface = RHS->getAs<ObjCObjectType>(); if (canAssignObjCInterfaces(LHSIface, RHSIface)) return LHS; - return QualType(); + return {}; } case Type::ObjCObjectPointer: if (OfBlockPointer) { @@ -8639,17 +8875,17 @@ QualType ASTContext::mergeTypes(QualType LHS, QualType RHS, RHS->getAs<ObjCObjectPointerType>(), BlockReturnType)) return LHS; - return QualType(); + return {}; } if (canAssignObjCInterfaces(LHS->getAs<ObjCObjectPointerType>(), RHS->getAs<ObjCObjectPointerType>())) return LHS; - return QualType(); + return {}; case Type::Pipe: assert(LHS != RHS && "Equivalent pipe types should have already been handled!"); - return QualType(); + return {}; } llvm_unreachable("Invalid Type::Class!"); @@ -8717,7 +8953,7 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { return LHS; if (RHSCan->isFunctionType()) { if (!LHSCan->isFunctionType()) - return QualType(); + return {}; QualType OldReturnType = cast<FunctionType>(RHSCan.getTypePtr())->getReturnType(); QualType NewReturnType = @@ -8725,12 +8961,12 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { QualType ResReturnType = mergeObjCGCQualifiers(NewReturnType, OldReturnType); if (ResReturnType.isNull()) - return QualType(); + return {}; if (ResReturnType == NewReturnType || ResReturnType == OldReturnType) { // id foo(); ... __strong id foo(); or: __strong id foo(); ... id foo(); // In either case, use OldReturnType to build the new function type. - const FunctionType *F = LHS->getAs<FunctionType>(); - if (const FunctionProtoType *FPT = cast<FunctionProtoType>(F)) { + const auto *F = LHS->getAs<FunctionType>(); + if (const auto *FPT = cast<FunctionProtoType>(F)) { FunctionProtoType::ExtProtoInfo EPI = FPT->getExtProtoInfo(); EPI.ExtInfo = getFunctionExtInfo(LHS); QualType ResultType = @@ -8738,7 +8974,7 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { return ResultType; } } - return QualType(); + return {}; } // If the qualifiers are different, the types can still be merged. @@ -8748,7 +8984,7 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { // If any of these qualifiers are different, we have a type mismatch. if (LQuals.getCVRQualifiers() != RQuals.getCVRQualifiers() || LQuals.getAddressSpace() != RQuals.getAddressSpace()) - return QualType(); + return {}; // Exactly one GC qualifier difference is allowed: __strong is // okay if the other type has no GC qualifier but is an Objective @@ -8760,13 +8996,13 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { assert((GC_L != GC_R) && "unequal qualifier sets had only equal elements"); if (GC_L == Qualifiers::Weak || GC_R == Qualifiers::Weak) - return QualType(); + return {}; if (GC_L == Qualifiers::Strong) return LHS; if (GC_R == Qualifiers::Strong) return RHS; - return QualType(); + return {}; } if (LHSCan->isObjCObjectPointerType() && RHSCan->isObjCObjectPointerType()) { @@ -8778,7 +9014,7 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { if (ResQT == RHSBaseQT) return RHS; } - return QualType(); + return {}; } //===----------------------------------------------------------------------===// @@ -8786,7 +9022,7 @@ QualType ASTContext::mergeObjCGCQualifiers(QualType LHS, QualType RHS) { //===----------------------------------------------------------------------===// unsigned ASTContext::getIntWidth(QualType T) const { - if (const EnumType *ET = T->getAs<EnumType>()) + if (const auto *ET = T->getAs<EnumType>()) T = ET->getDecl()->getIntegerType(); if (T->isBooleanType()) return 1; @@ -8795,19 +9031,20 @@ unsigned ASTContext::getIntWidth(QualType T) const { } QualType ASTContext::getCorrespondingUnsignedType(QualType T) const { - assert(T->hasSignedIntegerRepresentation() && "Unexpected type"); + assert((T->hasSignedIntegerRepresentation() || T->isSignedFixedPointType()) && + "Unexpected type"); // Turn <4 x signed int> -> <4 x unsigned int> - if (const VectorType *VTy = T->getAs<VectorType>()) + if (const auto *VTy = T->getAs<VectorType>()) return getVectorType(getCorrespondingUnsignedType(VTy->getElementType()), VTy->getNumElements(), VTy->getVectorKind()); // For enums, we return the unsigned version of the base type. - if (const EnumType *ETy = T->getAs<EnumType>()) + if (const auto *ETy = T->getAs<EnumType>()) T = ETy->getDecl()->getIntegerType(); - const BuiltinType *BTy = T->getAs<BuiltinType>(); - assert(BTy && "Unexpected signed integer type"); + const auto *BTy = T->getAs<BuiltinType>(); + assert(BTy && "Unexpected signed integer or fixed point type"); switch (BTy->getKind()) { case BuiltinType::Char_S: case BuiltinType::SChar: @@ -8822,8 +9059,33 @@ QualType ASTContext::getCorrespondingUnsignedType(QualType T) const { return UnsignedLongLongTy; case BuiltinType::Int128: return UnsignedInt128Ty; + + case BuiltinType::ShortAccum: + return UnsignedShortAccumTy; + case BuiltinType::Accum: + return UnsignedAccumTy; + case BuiltinType::LongAccum: + return UnsignedLongAccumTy; + case BuiltinType::SatShortAccum: + return SatUnsignedShortAccumTy; + case BuiltinType::SatAccum: + return SatUnsignedAccumTy; + case BuiltinType::SatLongAccum: + return SatUnsignedLongAccumTy; + case BuiltinType::ShortFract: + return UnsignedShortFractTy; + case BuiltinType::Fract: + return UnsignedFractTy; + case BuiltinType::LongFract: + return UnsignedLongFractTy; + case BuiltinType::SatShortFract: + return SatUnsignedShortFractTy; + case BuiltinType::SatFract: + return SatUnsignedFractTy; + case BuiltinType::SatLongFract: + return SatUnsignedLongFractTy; default: - llvm_unreachable("Unexpected signed integer type"); + llvm_unreachable("Unexpected signed integer or fixed point type"); } } @@ -8931,10 +9193,12 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, Type = Context.FloatTy; break; case 'd': - assert(HowLong < 2 && !Signed && !Unsigned && + assert(HowLong < 3 && !Signed && !Unsigned && "Bad modifiers used with 'd'!"); - if (HowLong) + if (HowLong == 1) Type = Context.LongDoubleTy; + else if (HowLong == 2) + Type = Context.Float128Ty; else Type = Context.DoubleTy; break; @@ -9050,7 +9314,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, Type = Context.getFILEType(); if (Type.isNull()) { Error = ASTContext::GE_Missing_stdio; - return QualType(); + return {}; } break; case 'J': @@ -9061,7 +9325,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, if (Type.isNull()) { Error = ASTContext::GE_Missing_setjmp; - return QualType(); + return {}; } break; case 'K': @@ -9070,7 +9334,7 @@ static QualType DecodeTypeFromStr(const char *&Str, const ASTContext &Context, if (Type.isNull()) { Error = ASTContext::GE_Missing_ucontext; - return QualType(); + return {}; } break; case 'p': @@ -9132,14 +9396,14 @@ QualType ASTContext::GetBuiltinType(unsigned Id, QualType ResType = DecodeTypeFromStr(TypeStr, *this, Error, RequiresICE, true); if (Error != GE_None) - return QualType(); + return {}; assert(!RequiresICE && "Result of intrinsic cannot be required to be an ICE"); while (TypeStr[0] && TypeStr[0] != '.') { QualType Ty = DecodeTypeFromStr(TypeStr, *this, Error, RequiresICE, true); if (Error != GE_None) - return QualType(); + return {}; // If this argument is required to be an IntegerConstantExpression and the // caller cares, fill in the bitmask we return. @@ -9154,7 +9418,7 @@ QualType ASTContext::GetBuiltinType(unsigned Id, } if (Id == Builtin::BI__GetExceptionInfo) - return QualType(); + return {}; assert((TypeStr[0] != '.' || TypeStr[1] == 0) && "'.' should only occur at end of builtin type list!"); @@ -9185,7 +9449,7 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context, // Non-user-provided functions get emitted as weak definitions with every // use, no matter whether they've been explicitly instantiated etc. - if (auto *MD = dyn_cast<CXXMethodDecl>(FD)) + if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) if (!MD->isUserProvided()) return GVA_DiscardableODR; @@ -9240,6 +9504,21 @@ static GVALinkage basicGVALinkageForFunction(const ASTContext &Context, return GVA_DiscardableODR; } +static bool isDeclareTargetToDeclaration(const Decl *VD) { + for (const Decl *D : VD->redecls()) { + if (!D->hasAttrs()) + continue; + if (const auto *Attr = D->getAttr<OMPDeclareTargetDeclAttr>()) + return Attr->getMapType() == OMPDeclareTargetDeclAttr::MT_To; + } + if (const auto *V = dyn_cast<VarDecl>(VD)) { + if (const VarDecl *TD = V->getTemplateInstantiationPattern()) + return isDeclareTargetToDeclaration(TD); + } + + return false; +} + static GVALinkage adjustGVALinkageForAttributes(const ASTContext &Context, const Decl *D, GVALinkage L) { // See http://msdn.microsoft.com/en-us/library/xa0d9ste.aspx @@ -9256,6 +9535,12 @@ static GVALinkage adjustGVALinkageForAttributes(const ASTContext &Context, // visible externally so they can be launched from host. if (L == GVA_DiscardableODR || L == GVA_Internal) return GVA_StrongODR; + } else if (Context.getLangOpts().OpenMP && Context.getLangOpts().OpenMPIsDevice && + isDeclareTargetToDeclaration(D)) { + // Static variables must be visible externally so they can be mapped from + // host. + if (L == GVA_Internal) + return GVA_StrongODR; } return L; } @@ -9375,7 +9660,7 @@ GVALinkage ASTContext::GetGVALinkageForVariable(const VarDecl *VD) { } bool ASTContext::DeclMustBeEmitted(const Decl *D) { - if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { + if (const auto *VD = dyn_cast<VarDecl>(D)) { if (!VD->isFileVarDecl()) return false; // Global named register variables (GNU extension) are never emitted. @@ -9384,14 +9669,13 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { if (VD->getDescribedVarTemplate() || isa<VarTemplatePartialSpecializationDecl>(VD)) return false; - } else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + } else if (const auto *FD = dyn_cast<FunctionDecl>(D)) { // We never need to emit an uninstantiated function template. if (FD->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate) return false; } else if (isa<PragmaCommentDecl>(D)) return true; - else if (isa<OMPThreadPrivateDecl>(D) || - D->hasAttr<OMPDeclareTargetDeclAttr>()) + else if (isa<OMPThreadPrivateDecl>(D)) return true; else if (isa<PragmaDetectMismatchDecl>(D)) return true; @@ -9404,6 +9688,29 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { else return false; + if (D->isFromASTFile() && !LangOpts.BuildingPCHWithObjectFile) { + assert(getExternalSource() && "It's from an AST file; must have a source."); + // On Windows, PCH files are built together with an object file. If this + // declaration comes from such a PCH and DeclMustBeEmitted would return + // true, it would have returned true and the decl would have been emitted + // into that object file, so it doesn't need to be emitted here. + // Note that decls are still emitted if they're referenced, as usual; + // DeclMustBeEmitted is used to decide whether a decl must be emitted even + // if it's not referenced. + // + // Explicit template instantiation definitions are tricky. If there was an + // explicit template instantiation decl in the PCH before, it will look like + // the definition comes from there, even if that was just the declaration. + // (Explicit instantiation defs of variable templates always get emitted.) + bool IsExpInstDef = + isa<FunctionDecl>(D) && + cast<FunctionDecl>(D)->getTemplateSpecializationKind() == + TSK_ExplicitInstantiationDefinition; + + if (getExternalSource()->DeclIsFromPCHWithObjectFile(D) && !IsExpInstDef) + return false; + } + // If this is a member of a class template, we do not need to emit it. if (D->getDeclContext()->isDependentContext()) return false; @@ -9416,7 +9723,7 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { if (D->hasAttr<AliasAttr>() || D->hasAttr<UsedAttr>()) return true; - if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { + if (const auto *FD = dyn_cast<FunctionDecl>(D)) { // Forward declarations aren't required. if (!FD->doesThisDeclarationHaveABody()) return FD->doesDeclarationForceExternallyVisibleDefinition(); @@ -9424,11 +9731,11 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { // Constructors and destructors are required. if (FD->hasAttr<ConstructorAttr>() || FD->hasAttr<DestructorAttr>()) 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)) { + if (const auto *MD = dyn_cast<CXXMethodDecl>(FD)) { const CXXRecordDecl *RD = MD->getParent(); if (MD->isOutOfLine() && RD->isDynamicClass()) { const CXXMethodDecl *KeyFunc = getCurrentKeyFunction(RD); @@ -9445,8 +9752,8 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { // Implicit template instantiations can also be deferred in C++. return !isDiscardableGVALinkage(Linkage); } - - const VarDecl *VD = cast<VarDecl>(D); + + const auto *VD = cast<VarDecl>(D); assert(VD->isFileVarDecl() && "Expected file scoped var"); if (VD->isThisDeclarationADefinition() == VarDecl::DeclarationOnly && @@ -9474,15 +9781,41 @@ bool ASTContext::DeclMustBeEmitted(const Decl *D) { // Likewise, variables with tuple-like bindings are required if their // bindings have side-effects. - if (auto *DD = dyn_cast<DecompositionDecl>(VD)) - for (auto *BD : DD->bindings()) - if (auto *BindingVD = BD->getHoldingVar()) + if (const auto *DD = dyn_cast<DecompositionDecl>(VD)) + for (const auto *BD : DD->bindings()) + if (const auto *BindingVD = BD->getHoldingVar()) if (DeclMustBeEmitted(BindingVD)) return true; + // If the decl is marked as `declare target`, it should be emitted. + for (const auto *Decl : D->redecls()) { + if (!Decl->hasAttrs()) + continue; + if (const auto *Attr = Decl->getAttr<OMPDeclareTargetDeclAttr>()) + if (Attr->getMapType() != OMPDeclareTargetDeclAttr::MT_Link) + return true; + } + return false; } +void ASTContext::forEachMultiversionedFunctionVersion( + const FunctionDecl *FD, + llvm::function_ref<void(const FunctionDecl *)> Pred) const { + assert(FD->isMultiVersion() && "Only valid for multiversioned functions"); + llvm::SmallDenseSet<const FunctionDecl*, 4> SeenDecls; + FD = FD->getCanonicalDecl(); + for (auto *CurDecl : + FD->getDeclContext()->getRedeclContext()->lookup(FD->getDeclName())) { + FunctionDecl *CurFD = CurDecl->getAsFunction()->getCanonicalDecl(); + if (CurFD && hasSameType(CurFD->getType(), FD->getType()) && + std::end(SeenDecls) == llvm::find(SeenDecls, CurFD)) { + SeenDecls.insert(CurFD); + Pred(CurFD); + } + } +} + CallingConv ASTContext::getDefaultCallingConvention(bool IsVariadic, bool IsCXXMethod) const { // Pass through to the C++ ABI object @@ -9595,7 +9928,7 @@ QualType ASTContext::getRealTypeForBitwidth(unsigned DestWidth) const { case TargetInfo::Float128: return Float128Ty; case TargetInfo::NoFloat: - return QualType(); + return {}; } llvm_unreachable("Unhandled TargetInfo::RealType value"); @@ -9739,7 +10072,7 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) { } /// @} - /// \brief A \c RecursiveASTVisitor that builds a map from nodes to their + /// A \c RecursiveASTVisitor that builds a map from nodes to their /// parents as defined by the \c RecursiveASTVisitor. /// /// Note that the relationship described here is purely in terms of AST @@ -9749,7 +10082,7 @@ createDynTypedNode(const NestedNameSpecifierLoc &Node) { /// FIXME: Currently only builds up the map using \c Stmt and \c Decl nodes. class ParentMapASTVisitor : public RecursiveASTVisitor<ParentMapASTVisitor> { public: - /// \brief Builds and returns the translation unit's parent map. + /// Builds and returns the translation unit's parent map. /// /// The caller takes ownership of the returned \c ParentMap. static std::pair<ASTContext::ParentMapPointers *, @@ -9874,7 +10207,8 @@ static ASTContext::DynTypedNodeList getDynNodeFromMap(const NodeTy &Node, if (I == Map.end()) { return llvm::ArrayRef<ast_type_traits::DynTypedNode>(); } - if (auto *V = I->second.template dyn_cast<ASTContext::ParentVector *>()) { + if (const auto *V = + I->second.template dyn_cast<ASTContext::ParentVector *>()) { return llvm::makeArrayRef(*V); } return getSingleDynTypedNodeFromParentMap(I->second); @@ -9942,6 +10276,42 @@ unsigned ASTContext::getTargetAddressSpace(LangAS AS) const { return (*AddrSpaceMap)[(unsigned)AS]; } +QualType ASTContext::getCorrespondingSaturatedType(QualType Ty) const { + assert(Ty->isFixedPointType()); + + if (Ty->isSaturatedFixedPointType()) return Ty; + + const auto &BT = Ty->getAs<BuiltinType>(); + switch (BT->getKind()) { + default: + llvm_unreachable("Not a fixed point type!"); + case BuiltinType::ShortAccum: + return SatShortAccumTy; + case BuiltinType::Accum: + return SatAccumTy; + case BuiltinType::LongAccum: + return SatLongAccumTy; + case BuiltinType::UShortAccum: + return SatUnsignedShortAccumTy; + case BuiltinType::UAccum: + return SatUnsignedAccumTy; + case BuiltinType::ULongAccum: + return SatUnsignedLongAccumTy; + case BuiltinType::ShortFract: + return SatShortFractTy; + case BuiltinType::Fract: + return SatFractTy; + case BuiltinType::LongFract: + return SatLongFractTy; + case BuiltinType::UShortFract: + return SatUnsignedShortFractTy; + case BuiltinType::UFract: + return SatUnsignedFractTy; + case BuiltinType::ULongFract: + return SatUnsignedLongFractTy; + } +} + // Explicitly instantiate this in case a Redeclarable<T> is used from a TU that // doesn't include ASTContext.h template @@ -9950,3 +10320,92 @@ clang::LazyGenerationalUpdatePtr< clang::LazyGenerationalUpdatePtr< const Decl *, Decl *, &ExternalASTSource::CompleteRedeclChain>::makeValue( const clang::ASTContext &Ctx, Decl *Value); + +unsigned char ASTContext::getFixedPointScale(QualType Ty) const { + assert(Ty->isFixedPointType()); + + const auto *BT = Ty->getAs<BuiltinType>(); + const TargetInfo &Target = getTargetInfo(); + switch (BT->getKind()) { + default: + llvm_unreachable("Not a fixed point type!"); + case BuiltinType::ShortAccum: + case BuiltinType::SatShortAccum: + return Target.getShortAccumScale(); + case BuiltinType::Accum: + case BuiltinType::SatAccum: + return Target.getAccumScale(); + case BuiltinType::LongAccum: + case BuiltinType::SatLongAccum: + return Target.getLongAccumScale(); + case BuiltinType::UShortAccum: + case BuiltinType::SatUShortAccum: + return Target.getUnsignedShortAccumScale(); + case BuiltinType::UAccum: + case BuiltinType::SatUAccum: + return Target.getUnsignedAccumScale(); + case BuiltinType::ULongAccum: + case BuiltinType::SatULongAccum: + return Target.getUnsignedLongAccumScale(); + case BuiltinType::ShortFract: + case BuiltinType::SatShortFract: + return Target.getShortFractScale(); + case BuiltinType::Fract: + case BuiltinType::SatFract: + return Target.getFractScale(); + case BuiltinType::LongFract: + case BuiltinType::SatLongFract: + return Target.getLongFractScale(); + case BuiltinType::UShortFract: + case BuiltinType::SatUShortFract: + return Target.getUnsignedShortFractScale(); + case BuiltinType::UFract: + case BuiltinType::SatUFract: + return Target.getUnsignedFractScale(); + case BuiltinType::ULongFract: + case BuiltinType::SatULongFract: + return Target.getUnsignedLongFractScale(); + } +} + +unsigned char ASTContext::getFixedPointIBits(QualType Ty) const { + assert(Ty->isFixedPointType()); + + const auto *BT = Ty->getAs<BuiltinType>(); + const TargetInfo &Target = getTargetInfo(); + switch (BT->getKind()) { + default: + llvm_unreachable("Not a fixed point type!"); + case BuiltinType::ShortAccum: + case BuiltinType::SatShortAccum: + return Target.getShortAccumIBits(); + case BuiltinType::Accum: + case BuiltinType::SatAccum: + return Target.getAccumIBits(); + case BuiltinType::LongAccum: + case BuiltinType::SatLongAccum: + return Target.getLongAccumIBits(); + case BuiltinType::UShortAccum: + case BuiltinType::SatUShortAccum: + return Target.getUnsignedShortAccumIBits(); + case BuiltinType::UAccum: + case BuiltinType::SatUAccum: + return Target.getUnsignedAccumIBits(); + case BuiltinType::ULongAccum: + case BuiltinType::SatULongAccum: + return Target.getUnsignedLongAccumIBits(); + case BuiltinType::ShortFract: + case BuiltinType::SatShortFract: + case BuiltinType::Fract: + case BuiltinType::SatFract: + case BuiltinType::LongFract: + case BuiltinType::SatLongFract: + case BuiltinType::UShortFract: + case BuiltinType::SatUShortFract: + case BuiltinType::UFract: + case BuiltinType::SatUFract: + case BuiltinType::ULongFract: + case BuiltinType::SatULongFract: + return 0; + } +} |