diff options
Diffstat (limited to 'contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp')
-rw-r--r-- | contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp | 1920 |
1 files changed, 1010 insertions, 910 deletions
diff --git a/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp b/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp index 18ab4666a7d8..154acdfbe032 100644 --- a/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp +++ b/contrib/llvm-project/clang/lib/Serialization/ASTReaderDecl.cpp @@ -13,7 +13,9 @@ #include "ASTCommon.h" #include "ASTReaderInternals.h" +#include "clang/AST/ASTConcept.h" #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTStructuralEquivalence.h" #include "clang/AST/Attr.h" #include "clang/AST/AttrIterator.h" #include "clang/AST/Decl.h" @@ -36,6 +38,7 @@ #include "clang/AST/Type.h" #include "clang/AST/UnresolvedSet.h" #include "clang/Basic/AttrKinds.h" +#include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/ExceptionSpecificationType.h" #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/LLVM.h" @@ -46,6 +49,7 @@ #include "clang/Basic/PragmaKinds.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/Specifiers.h" +#include "clang/Basic/Stack.h" #include "clang/Sema/IdentifierResolver.h" #include "clang/Serialization/ASTBitCodes.h" #include "clang/Serialization/ASTRecordReader.h" @@ -81,18 +85,16 @@ namespace clang { ASTReader &Reader; ASTRecordReader &Record; ASTReader::RecordLocation Loc; - const DeclID ThisDeclID; + const GlobalDeclID ThisDeclID; const SourceLocation ThisDeclLoc; using RecordData = ASTReader::RecordData; TypeID DeferredTypeID = 0; - unsigned AnonymousDeclNumber; - GlobalDeclID NamedDeclForTagDecl = 0; + unsigned AnonymousDeclNumber = 0; + GlobalDeclID NamedDeclForTagDecl = GlobalDeclID(); IdentifierInfo *TypedefNameForLinkage = nullptr; - bool HasPendingBody = false; - ///A flag to carry the information for a decl from the entity is /// used. We use it to delay the marking of the canonical decl as used until /// the entire declaration is deserialized and merged. @@ -123,15 +125,13 @@ namespace clang { return Record.readTypeSourceInfo(); } - serialization::DeclID readDeclID() { - return Record.readDeclID(); - } + GlobalDeclID readDeclID() { return Record.readDeclID(); } std::string readString() { return Record.readString(); } - void readDeclIDList(SmallVectorImpl<DeclID> &IDs) { + void readDeclIDList(SmallVectorImpl<GlobalDeclID> &IDs) { for (unsigned I = 0, Size = Record.readInt(); I != Size; ++I) IDs.push_back(readDeclID()); } @@ -156,9 +156,12 @@ namespace clang { return Record.getSubmodule(readSubmoduleID()); } - void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update); + void ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update, + Decl *LambdaContext = nullptr, + unsigned IndexInLambdaContext = 0); void ReadCXXDefinitionData(struct CXXRecordDecl::DefinitionData &Data, - const CXXRecordDecl *D); + const CXXRecordDecl *D, Decl *LambdaContext, + unsigned IndexInLambdaContext); void MergeDefinitionData(CXXRecordDecl *D, struct CXXRecordDecl::DefinitionData &&NewDD); void ReadObjCDefinitionData(struct ObjCInterfaceDecl::DefinitionData &Data); @@ -176,6 +179,13 @@ namespace clang { static void setAnonymousDeclForMerging(ASTReader &Reader, DeclContext *DC, unsigned Index, NamedDecl *D); + /// Commit to a primary definition of the class RD, which is known to be + /// a definition of the class. We might not have read the definition data + /// for it yet. If we haven't then allocate placeholder definition data + /// now too. + static CXXRecordDecl *getOrFakePrimaryClassDefinition(ASTReader &Reader, + CXXRecordDecl *RD); + /// Results from loading a RedeclarableDecl. class RedeclarableResult { Decl *MergeWith; @@ -247,14 +257,14 @@ namespace clang { public: ASTDeclReader(ASTReader &Reader, ASTRecordReader &Record, - ASTReader::RecordLocation Loc, - DeclID thisDeclID, SourceLocation ThisDeclLoc) + ASTReader::RecordLocation Loc, GlobalDeclID thisDeclID, + SourceLocation ThisDeclLoc) : Reader(Reader), Record(Record), Loc(Loc), ThisDeclID(thisDeclID), ThisDeclLoc(ThisDeclLoc) {} - template <typename T> static - void AddLazySpecializations(T *D, - SmallVectorImpl<serialization::DeclID>& IDs) { + template <typename T> + static void AddLazySpecializations(T *D, + SmallVectorImpl<GlobalDeclID> &IDs) { if (IDs.empty()) return; @@ -264,13 +274,14 @@ namespace clang { auto *&LazySpecializations = D->getCommonPtr()->LazySpecializations; if (auto &Old = LazySpecializations) { - IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0]); + IDs.insert(IDs.end(), Old + 1, Old + 1 + Old[0].getRawValue()); llvm::sort(IDs); IDs.erase(std::unique(IDs.begin(), IDs.end()), IDs.end()); } - auto *Result = new (C) serialization::DeclID[1 + IDs.size()]; - *Result = IDs.size(); + auto *Result = new (C) GlobalDeclID[1 + IDs.size()]; + *Result = GlobalDeclID(IDs.size()); + std::copy(IDs.begin(), IDs.end(), Result + 1); LazySpecializations = Result; @@ -301,13 +312,10 @@ namespace clang { static void markIncompleteDeclChainImpl(Redeclarable<DeclT> *D); static void markIncompleteDeclChainImpl(...); - /// Determine whether this declaration has a pending body. - bool hasPendingBody() const { return HasPendingBody; } - void ReadFunctionDefinition(FunctionDecl *FD); void Visit(Decl *D); - void UpdateDecl(Decl *D, SmallVectorImpl<serialization::DeclID> &); + void UpdateDecl(Decl *D, SmallVectorImpl<GlobalDeclID> &); static void setNextObjCCategory(ObjCCategoryDecl *Cat, ObjCCategoryDecl *Next) { @@ -321,6 +329,7 @@ namespace clang { void VisitNamedDecl(NamedDecl *ND); void VisitLabelDecl(LabelDecl *LD); void VisitNamespaceDecl(NamespaceDecl *D); + void VisitHLSLBufferDecl(HLSLBufferDecl *D); void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); void VisitTypeDecl(TypeDecl *TD); @@ -328,10 +337,11 @@ namespace clang { void VisitTypedefDecl(TypedefDecl *TD); void VisitTypeAliasDecl(TypeAliasDecl *TD); void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); + void VisitUnresolvedUsingIfExistsDecl(UnresolvedUsingIfExistsDecl *D); RedeclarableResult VisitTagDecl(TagDecl *TD); void VisitEnumDecl(EnumDecl *ED); RedeclarableResult VisitRecordDeclImpl(RecordDecl *RD); - void VisitRecordDecl(RecordDecl *RD) { VisitRecordDeclImpl(RD); } + void VisitRecordDecl(RecordDecl *RD); RedeclarableResult VisitCXXRecordDeclImpl(CXXRecordDecl *D); void VisitCXXRecordDecl(CXXRecordDecl *D) { VisitCXXRecordDeclImpl(D); } RedeclarableResult VisitClassTemplateSpecializationDeclImpl( @@ -343,9 +353,7 @@ namespace clang { } void VisitClassTemplatePartialSpecializationDecl( - ClassTemplatePartialSpecializationDecl *D); - void VisitClassScopeFunctionSpecializationDecl( - ClassScopeFunctionSpecializationDecl *D); + ClassTemplatePartialSpecializationDecl *D); RedeclarableResult VisitVarTemplateSpecializationDeclImpl(VarTemplateSpecializationDecl *D); @@ -369,17 +377,21 @@ namespace clang { void VisitFieldDecl(FieldDecl *FD); void VisitMSPropertyDecl(MSPropertyDecl *FD); void VisitMSGuidDecl(MSGuidDecl *D); + void VisitUnnamedGlobalConstantDecl(UnnamedGlobalConstantDecl *D); void VisitTemplateParamObjectDecl(TemplateParamObjectDecl *D); void VisitIndirectFieldDecl(IndirectFieldDecl *FD); RedeclarableResult VisitVarDeclImpl(VarDecl *D); + void ReadVarDeclInit(VarDecl *VD); void VisitVarDecl(VarDecl *VD) { VisitVarDeclImpl(VD); } void VisitImplicitParamDecl(ImplicitParamDecl *PD); void VisitParmVarDecl(ParmVarDecl *PD); void VisitDecompositionDecl(DecompositionDecl *DD); void VisitBindingDecl(BindingDecl *BD); void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); - DeclID VisitTemplateDecl(TemplateDecl *D); + void VisitTemplateDecl(TemplateDecl *D); void VisitConceptDecl(ConceptDecl *D); + void VisitImplicitConceptSpecializationDecl( + ImplicitConceptSpecializationDecl *D); void VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D); RedeclarableResult VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); void VisitClassTemplateDecl(ClassTemplateDecl *D); @@ -389,12 +401,14 @@ namespace clang { void VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D); void VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D); void VisitUsingDecl(UsingDecl *D); + void VisitUsingEnumDecl(UsingEnumDecl *D); void VisitUsingPackDecl(UsingPackDecl *D); void VisitUsingShadowDecl(UsingShadowDecl *D); void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D); void VisitLinkageSpecDecl(LinkageSpecDecl *D); void VisitExportDecl(ExportDecl *D); void VisitFileScopeAsmDecl(FileScopeAsmDecl *AD); + void VisitTopLevelStmtDecl(TopLevelStmtDecl *D); void VisitImportDecl(ImportDecl *D); void VisitAccessSpecDecl(AccessSpecDecl *D); void VisitFriendDecl(FriendDecl *D); @@ -410,14 +424,18 @@ namespace clang { template<typename T> RedeclarableResult VisitRedeclarable(Redeclarable<T> *D); - template<typename T> - void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl, - DeclID TemplatePatternID = 0); + template <typename T> + void mergeRedeclarable(Redeclarable<T> *D, RedeclarableResult &Redecl); - template<typename T> + void mergeLambda(CXXRecordDecl *D, RedeclarableResult &Redecl, + Decl *Context, unsigned Number); + + void mergeRedeclarableTemplate(RedeclarableTemplateDecl *D, + RedeclarableResult &Redecl); + + template <typename T> void mergeRedeclarable(Redeclarable<T> *D, T *Existing, - RedeclarableResult &Redecl, - DeclID TemplatePatternID = 0); + RedeclarableResult &Redecl); template<typename T> void mergeMergeable(Mergeable<T> *D); @@ -426,7 +444,7 @@ namespace clang { void mergeTemplatePattern(RedeclarableTemplateDecl *D, RedeclarableTemplateDecl *Existing, - DeclID DsID, bool IsKeyDecl); + bool IsKeyDecl); ObjCTypeParamList *ReadObjCTypeParamList(); @@ -459,9 +477,8 @@ namespace { /// Iterator over the redeclarations of a declaration that have already /// been merged into the same redeclaration chain. -template<typename DeclT> -class MergedRedeclIterator { - DeclT *Start; +template <typename DeclT> class MergedRedeclIterator { + DeclT *Start = nullptr; DeclT *Canonical = nullptr; DeclT *Current = nullptr; @@ -519,7 +536,6 @@ void ASTDeclReader::ReadFunctionDefinition(FunctionDecl *FD) { } // Store the offset of the body so we can lazily load it later. Reader.PendingBodies[FD] = GetCurrentCursorOffset(); - HasPendingBody = true; } void ASTDeclReader::Visit(Decl *D) { @@ -541,7 +557,7 @@ void ASTDeclReader::Visit(Decl *D) { // If this is a tag declaration with a typedef name for linkage, it's safe // to load that typedef now. - if (NamedDeclForTagDecl) + if (NamedDeclForTagDecl.isValid()) cast<TagDecl>(D)->TypedefNameDeclOrQualifier = cast<TypedefNameDecl>(Reader.GetDecl(NamedDeclForTagDecl)); } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) { @@ -549,17 +565,34 @@ void ASTDeclReader::Visit(Decl *D) { ID->TypeForDecl = Reader.GetType(DeferredTypeID).getTypePtrOrNull(); } else if (auto *FD = dyn_cast<FunctionDecl>(D)) { // FunctionDecl's body was written last after all other Stmts/Exprs. - // We only read it if FD doesn't already have a body (e.g., from another - // module). - // FIXME: Can we diagnose ODR violations somehow? if (Record.readInt()) ReadFunctionDefinition(FD); + } else if (auto *VD = dyn_cast<VarDecl>(D)) { + ReadVarDeclInit(VD); + } else if (auto *FD = dyn_cast<FieldDecl>(D)) { + if (FD->hasInClassInitializer() && Record.readInt()) { + FD->setLazyInClassInitializer(LazyDeclStmtPtr(GetCurrentCursorOffset())); + } } } void ASTDeclReader::VisitDecl(Decl *D) { + BitsUnpacker DeclBits(Record.readInt()); + auto ModuleOwnership = + (Decl::ModuleOwnershipKind)DeclBits.getNextBits(/*Width=*/3); + D->setReferenced(DeclBits.getNextBit()); + D->Used = DeclBits.getNextBit(); + IsDeclMarkedUsed |= D->Used; + D->setAccess((AccessSpecifier)DeclBits.getNextBits(/*Width=*/2)); + D->setImplicit(DeclBits.getNextBit()); + bool HasStandaloneLexicalDC = DeclBits.getNextBit(); + bool HasAttrs = DeclBits.getNextBit(); + D->setTopLevelDeclInObjCContainer(DeclBits.getNextBit()); + D->InvalidDecl = DeclBits.getNextBit(); + D->FromASTFile = true; + if (D->isTemplateParameter() || D->isTemplateParameterPack() || - isa<ParmVarDecl>(D) || isa<ObjCTypeParamDecl>(D)) { + isa<ParmVarDecl, ObjCTypeParamDecl>(D)) { // We don't want to deserialize the DeclContext of a template // parameter or of a parameter of a function template immediately. These // entities might be used in the formulation of its DeclContext (for @@ -567,8 +600,9 @@ void ASTDeclReader::VisitDecl(Decl *D) { // return type of the function). Use the translation unit DeclContext as a // placeholder. GlobalDeclID SemaDCIDForTemplateParmDecl = readDeclID(); - GlobalDeclID LexicalDCIDForTemplateParmDecl = readDeclID(); - if (!LexicalDCIDForTemplateParmDecl) + GlobalDeclID LexicalDCIDForTemplateParmDecl = + HasStandaloneLexicalDC ? readDeclID() : GlobalDeclID(); + if (LexicalDCIDForTemplateParmDecl.isInvalid()) LexicalDCIDForTemplateParmDecl = SemaDCIDForTemplateParmDecl; Reader.addPendingDeclContextInfo(D, SemaDCIDForTemplateParmDecl, @@ -576,40 +610,50 @@ void ASTDeclReader::VisitDecl(Decl *D) { D->setDeclContext(Reader.getContext().getTranslationUnitDecl()); } else { auto *SemaDC = readDeclAs<DeclContext>(); - auto *LexicalDC = readDeclAs<DeclContext>(); + auto *LexicalDC = + HasStandaloneLexicalDC ? readDeclAs<DeclContext>() : nullptr; if (!LexicalDC) LexicalDC = SemaDC; - DeclContext *MergedSemaDC = Reader.MergedDeclContexts.lookup(SemaDC); + // If the context is a class, we might not have actually merged it yet, in + // the case where the definition comes from an update record. + DeclContext *MergedSemaDC; + if (auto *RD = dyn_cast<CXXRecordDecl>(SemaDC)) + MergedSemaDC = getOrFakePrimaryClassDefinition(Reader, RD); + else + MergedSemaDC = Reader.MergedDeclContexts.lookup(SemaDC); // Avoid calling setLexicalDeclContext() directly because it uses // Decl::getASTContext() internally which is unsafe during derialization. D->setDeclContextsImpl(MergedSemaDC ? MergedSemaDC : SemaDC, LexicalDC, Reader.getContext()); } D->setLocation(ThisDeclLoc); - D->InvalidDecl = Record.readInt(); - if (Record.readInt()) { // hasAttrs + + if (HasAttrs) { AttrVec Attrs; Record.readAttributes(Attrs); // Avoid calling setAttrs() directly because it uses Decl::getASTContext() // internally which is unsafe during derialization. D->setAttrsImpl(Attrs, Reader.getContext()); } - D->setImplicit(Record.readInt()); - D->Used = Record.readInt(); - IsDeclMarkedUsed |= D->Used; - D->setReferenced(Record.readInt()); - D->setTopLevelDeclInObjCContainer(Record.readInt()); - D->setAccess((AccessSpecifier)Record.readInt()); - D->FromASTFile = true; - bool ModulePrivate = Record.readInt(); // Determine whether this declaration is part of a (sub)module. If so, it // may not yet be visible. + bool ModulePrivate = + (ModuleOwnership == Decl::ModuleOwnershipKind::ModulePrivate); if (unsigned SubmoduleID = readSubmoduleID()) { + switch (ModuleOwnership) { + case Decl::ModuleOwnershipKind::Visible: + ModuleOwnership = Decl::ModuleOwnershipKind::VisibleWhenImported; + break; + case Decl::ModuleOwnershipKind::Unowned: + case Decl::ModuleOwnershipKind::VisibleWhenImported: + case Decl::ModuleOwnershipKind::ReachableWhenImported: + case Decl::ModuleOwnershipKind::ModulePrivate: + break; + } + + D->setModuleOwnershipKind(ModuleOwnership); // Store the owning submodule ID in the declaration. - D->setModuleOwnershipKind( - ModulePrivate ? Decl::ModuleOwnershipKind::ModulePrivate - : Decl::ModuleOwnershipKind::VisibleWhenImported); D->setOwningModuleID(SubmoduleID); if (ModulePrivate) { @@ -707,15 +751,17 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitTagDecl(TagDecl *TD) { VisitTypeDecl(TD); TD->IdentifierNamespace = Record.readInt(); - TD->setTagKind((TagDecl::TagKind)Record.readInt()); - if (!isa<CXXRecordDecl>(TD)) - TD->setCompleteDefinition(Record.readInt()); - TD->setEmbeddedInDeclarator(Record.readInt()); - TD->setFreeStanding(Record.readInt()); - TD->setCompleteDefinitionRequired(Record.readInt()); + + BitsUnpacker TagDeclBits(Record.readInt()); + TD->setTagKind( + static_cast<TagTypeKind>(TagDeclBits.getNextBits(/*Width=*/3))); + TD->setCompleteDefinition(TagDeclBits.getNextBit()); + TD->setEmbeddedInDeclarator(TagDeclBits.getNextBit()); + TD->setFreeStanding(TagDeclBits.getNextBit()); + TD->setCompleteDefinitionRequired(TagDeclBits.getNextBit()); TD->setBraceRange(readSourceRange()); - switch (Record.readInt()) { + switch (TagDeclBits.getNextBits(/*Width=*/2)) { case 0: break; case 1: { // ExtInfo @@ -744,20 +790,20 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { else ED->setIntegerType(Record.readType()); ED->setPromotionType(Record.readType()); - ED->setNumPositiveBits(Record.readInt()); - ED->setNumNegativeBits(Record.readInt()); - ED->setScoped(Record.readInt()); - ED->setScopedUsingClassTag(Record.readInt()); - ED->setFixed(Record.readInt()); + + BitsUnpacker EnumDeclBits(Record.readInt()); + ED->setNumPositiveBits(EnumDeclBits.getNextBits(/*Width=*/8)); + ED->setNumNegativeBits(EnumDeclBits.getNextBits(/*Width=*/8)); + ED->setScoped(EnumDeclBits.getNextBit()); + ED->setScopedUsingClassTag(EnumDeclBits.getNextBit()); + ED->setFixed(EnumDeclBits.getNextBit()); ED->setHasODRHash(true); ED->ODRHash = Record.readInt(); // If this is a definition subject to the ODR, and we already have a // definition, merge this one into it. - if (ED->isCompleteDefinition() && - Reader.getContext().getLangOpts().Modules && - Reader.getContext().getLangOpts().CPlusPlus) { + if (ED->isCompleteDefinition() && Reader.getContext().getLangOpts().Modules) { EnumDecl *&OldDef = Reader.EnumDefinitions[ED->getCanonicalDecl()]; if (!OldDef) { // This is the first time we've seen an imported definition. Look for a @@ -771,9 +817,12 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { } if (OldDef) { Reader.MergedDeclContexts.insert(std::make_pair(ED, OldDef)); - ED->setCompleteDefinition(false); + ED->demoteThisDefinitionToDeclaration(); Reader.mergeDefinitionVisibility(OldDef, ED); - if (OldDef->getODRHash() != ED->getODRHash()) + // We don't want to check the ODR hash value for declarations from global + // module fragment. + if (!shouldSkipCheckingODR(ED) && !shouldSkipCheckingODR(OldDef) && + OldDef->getODRHash() != ED->getODRHash()) Reader.PendingEnumOdrMergeFailures[OldDef].push_back(ED); } else { OldDef = ED; @@ -791,27 +840,62 @@ void ASTDeclReader::VisitEnumDecl(EnumDecl *ED) { ASTDeclReader::RedeclarableResult ASTDeclReader::VisitRecordDeclImpl(RecordDecl *RD) { RedeclarableResult Redecl = VisitTagDecl(RD); - RD->setHasFlexibleArrayMember(Record.readInt()); - RD->setAnonymousStructOrUnion(Record.readInt()); - RD->setHasObjectMember(Record.readInt()); - RD->setHasVolatileMember(Record.readInt()); - RD->setNonTrivialToPrimitiveDefaultInitialize(Record.readInt()); - RD->setNonTrivialToPrimitiveCopy(Record.readInt()); - RD->setNonTrivialToPrimitiveDestroy(Record.readInt()); - RD->setHasNonTrivialToPrimitiveDefaultInitializeCUnion(Record.readInt()); - RD->setHasNonTrivialToPrimitiveDestructCUnion(Record.readInt()); - RD->setHasNonTrivialToPrimitiveCopyCUnion(Record.readInt()); - RD->setParamDestroyedInCallee(Record.readInt()); - RD->setArgPassingRestrictions((RecordDecl::ArgPassingKind)Record.readInt()); + + BitsUnpacker RecordDeclBits(Record.readInt()); + RD->setHasFlexibleArrayMember(RecordDeclBits.getNextBit()); + RD->setAnonymousStructOrUnion(RecordDeclBits.getNextBit()); + RD->setHasObjectMember(RecordDeclBits.getNextBit()); + RD->setHasVolatileMember(RecordDeclBits.getNextBit()); + RD->setNonTrivialToPrimitiveDefaultInitialize(RecordDeclBits.getNextBit()); + RD->setNonTrivialToPrimitiveCopy(RecordDeclBits.getNextBit()); + RD->setNonTrivialToPrimitiveDestroy(RecordDeclBits.getNextBit()); + RD->setHasNonTrivialToPrimitiveDefaultInitializeCUnion( + RecordDeclBits.getNextBit()); + RD->setHasNonTrivialToPrimitiveDestructCUnion(RecordDeclBits.getNextBit()); + RD->setHasNonTrivialToPrimitiveCopyCUnion(RecordDeclBits.getNextBit()); + RD->setParamDestroyedInCallee(RecordDeclBits.getNextBit()); + RD->setArgPassingRestrictions( + (RecordArgPassingKind)RecordDeclBits.getNextBits(/*Width=*/2)); return Redecl; } +void ASTDeclReader::VisitRecordDecl(RecordDecl *RD) { + VisitRecordDeclImpl(RD); + RD->setODRHash(Record.readInt()); + + // Maintain the invariant of a redeclaration chain containing only + // a single definition. + if (RD->isCompleteDefinition()) { + RecordDecl *Canon = static_cast<RecordDecl *>(RD->getCanonicalDecl()); + RecordDecl *&OldDef = Reader.RecordDefinitions[Canon]; + if (!OldDef) { + // This is the first time we've seen an imported definition. Look for a + // local definition before deciding that we are the first definition. + for (auto *D : merged_redecls(Canon)) { + if (!D->isFromASTFile() && D->isCompleteDefinition()) { + OldDef = D; + break; + } + } + } + if (OldDef) { + Reader.MergedDeclContexts.insert(std::make_pair(RD, OldDef)); + RD->demoteThisDefinitionToDeclaration(); + Reader.mergeDefinitionVisibility(OldDef, RD); + if (OldDef->getODRHash() != RD->getODRHash()) + Reader.PendingRecordOdrMergeFailures[OldDef].push_back(RD); + } else { + OldDef = RD; + } + } +} + void ASTDeclReader::VisitValueDecl(ValueDecl *VD) { VisitNamedDecl(VD); - // For function declarations, defer reading the type in case the function has - // a deduced return type that references an entity declared within the - // function. - if (isa<FunctionDecl>(VD)) + // For function or variable declarations, defer reading the type in case the + // declaration has a deduced type that references an entity declared within + // the function definition or variable initializer. + if (isa<FunctionDecl, VarDecl>(VD)) DeferredTypeID = Record.getGlobalTypeID(Record.readInt()); else VD->setType(Record.readType()); @@ -821,7 +905,7 @@ void ASTDeclReader::VisitEnumConstantDecl(EnumConstantDecl *ECD) { VisitValueDecl(ECD); if (Record.readInt()) ECD->setInitExpr(Record.readExpr()); - ECD->setInitVal(Record.readAPSInt()); + ECD->setInitVal(Reader.getContext(), Record.readAPSInt()); mergeMergeable(ECD); } @@ -842,84 +926,27 @@ void ASTDeclReader::VisitDeclaratorDecl(DeclaratorDecl *DD) { void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { RedeclarableResult Redecl = VisitRedeclarable(FD); - VisitDeclaratorDecl(FD); - - // Attach a type to this function. Use the real type if possible, but fall - // back to the type as written if it involves a deduced return type. - if (FD->getTypeSourceInfo() && - FD->getTypeSourceInfo()->getType()->castAs<FunctionType>() - ->getReturnType()->getContainedAutoType()) { - // We'll set up the real type in Visit, once we've finished loading the - // function. - FD->setType(FD->getTypeSourceInfo()->getType()); - Reader.PendingFunctionTypes.push_back({FD, DeferredTypeID}); - } else { - FD->setType(Reader.GetType(DeferredTypeID)); - } - DeferredTypeID = 0; - - FD->DNLoc = Record.readDeclarationNameLoc(FD->getDeclName()); - FD->IdentifierNamespace = Record.readInt(); - - // FunctionDecl's body is handled last at ASTDeclReader::Visit, - // after everything else is read. - - FD->setStorageClass(static_cast<StorageClass>(Record.readInt())); - FD->setInlineSpecified(Record.readInt()); - FD->setImplicitlyInline(Record.readInt()); - FD->setVirtualAsWritten(Record.readInt()); - // We defer calling `FunctionDecl::setPure()` here as for methods of - // `CXXTemplateSpecializationDecl`s, we may not have connected up the - // definition (which is required for `setPure`). - const bool Pure = Record.readInt(); - FD->setHasInheritedPrototype(Record.readInt()); - FD->setHasWrittenPrototype(Record.readInt()); - FD->setDeletedAsWritten(Record.readInt()); - FD->setTrivial(Record.readInt()); - FD->setTrivialForCall(Record.readInt()); - FD->setDefaulted(Record.readInt()); - FD->setExplicitlyDefaulted(Record.readInt()); - FD->setHasImplicitReturnZero(Record.readInt()); - FD->setConstexprKind(static_cast<ConstexprSpecKind>(Record.readInt())); - FD->setUsesSEHTry(Record.readInt()); - FD->setHasSkippedBody(Record.readInt()); - FD->setIsMultiVersion(Record.readInt()); - FD->setLateTemplateParsed(Record.readInt()); - - FD->setCachedLinkage(static_cast<Linkage>(Record.readInt())); - FD->EndRangeLoc = readSourceLocation(); - - FD->ODRHash = Record.readInt(); - FD->setHasODRHash(true); - if (FD->isDefaulted()) { - if (unsigned NumLookups = Record.readInt()) { - SmallVector<DeclAccessPair, 8> Lookups; - for (unsigned I = 0; I != NumLookups; ++I) { - NamedDecl *ND = Record.readDeclAs<NamedDecl>(); - AccessSpecifier AS = (AccessSpecifier)Record.readInt(); - Lookups.push_back(DeclAccessPair::make(ND, AS)); - } - FD->setDefaultedFunctionInfo(FunctionDecl::DefaultedFunctionInfo::Create( - Reader.getContext(), Lookups)); - } - } + FunctionDecl *Existing = nullptr; switch ((FunctionDecl::TemplatedKind)Record.readInt()) { case FunctionDecl::TK_NonTemplate: - mergeRedeclarable(FD, Redecl); break; - case FunctionDecl::TK_FunctionTemplate: - // Merged when we merge the template. - FD->setDescribedFunctionTemplate(readDeclAs<FunctionTemplateDecl>()); + case FunctionDecl::TK_DependentNonTemplate: + FD->setInstantiatedFromDecl(readDeclAs<FunctionDecl>()); + break; + case FunctionDecl::TK_FunctionTemplate: { + auto *Template = readDeclAs<FunctionTemplateDecl>(); + Template->init(FD); + FD->setDescribedFunctionTemplate(Template); break; + } case FunctionDecl::TK_MemberSpecialization: { auto *InstFD = readDeclAs<FunctionDecl>(); auto TSK = (TemplateSpecializationKind)Record.readInt(); SourceLocation POI = readSourceLocation(); FD->setInstantiationOfMemberFunction(Reader.getContext(), InstFD, TSK); FD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); - mergeRedeclarable(FD, Redecl); break; } case FunctionDecl::TK_FunctionTemplateSpecialization: { @@ -931,27 +958,16 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true); // Template args as written. - SmallVector<TemplateArgumentLoc, 8> TemplArgLocs; - SourceLocation LAngleLoc, RAngleLoc; - bool HasTemplateArgumentsAsWritten = Record.readInt(); - if (HasTemplateArgumentsAsWritten) { - unsigned NumTemplateArgLocs = Record.readInt(); - TemplArgLocs.reserve(NumTemplateArgLocs); - for (unsigned i = 0; i != NumTemplateArgLocs; ++i) - TemplArgLocs.push_back(Record.readTemplateArgumentLoc()); - - LAngleLoc = readSourceLocation(); - RAngleLoc = readSourceLocation(); - } + TemplateArgumentListInfo TemplArgsWritten; + bool HasTemplateArgumentsAsWritten = Record.readBool(); + if (HasTemplateArgumentsAsWritten) + Record.readTemplateArgumentListInfo(TemplArgsWritten); SourceLocation POI = readSourceLocation(); ASTContext &C = Reader.getContext(); - TemplateArgumentList *TemplArgList - = TemplateArgumentList::CreateCopy(C, TemplArgs); - TemplateArgumentListInfo TemplArgsInfo(LAngleLoc, RAngleLoc); - for (unsigned i = 0, e = TemplArgLocs.size(); i != e; ++i) - TemplArgsInfo.addArgument(TemplArgLocs[i]); + TemplateArgumentList *TemplArgList = + TemplateArgumentList::CreateCopy(C, TemplArgs); MemberSpecializationInfo *MSInfo = nullptr; if (Record.readInt()) { @@ -966,7 +982,7 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { FunctionTemplateSpecializationInfo *FTInfo = FunctionTemplateSpecializationInfo::Create( C, FD, Template, TSK, TemplArgList, - HasTemplateArgumentsAsWritten ? &TemplArgsInfo : nullptr, POI, + HasTemplateArgumentsAsWritten ? &TemplArgsWritten : nullptr, POI, MSInfo); FD->TemplateOrSpecialization = FTInfo; @@ -990,37 +1006,141 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) { else { assert(Reader.getContext().getLangOpts().Modules && "already deserialized this template specialization"); - mergeRedeclarable(FD, ExistingInfo->getFunction(), Redecl); + Existing = ExistingInfo->getFunction(); } } break; } case FunctionDecl::TK_DependentFunctionTemplateSpecialization: { // Templates. - UnresolvedSet<8> TemplDecls; - unsigned NumTemplates = Record.readInt(); - while (NumTemplates--) - TemplDecls.addDecl(readDeclAs<NamedDecl>()); + UnresolvedSet<8> Candidates; + unsigned NumCandidates = Record.readInt(); + while (NumCandidates--) + Candidates.addDecl(readDeclAs<NamedDecl>()); // Templates args. - TemplateArgumentListInfo TemplArgs; - unsigned NumArgs = Record.readInt(); - while (NumArgs--) - TemplArgs.addArgument(Record.readTemplateArgumentLoc()); - TemplArgs.setLAngleLoc(readSourceLocation()); - TemplArgs.setRAngleLoc(readSourceLocation()); - - FD->setDependentTemplateSpecialization(Reader.getContext(), - TemplDecls, TemplArgs); + TemplateArgumentListInfo TemplArgsWritten; + bool HasTemplateArgumentsAsWritten = Record.readBool(); + if (HasTemplateArgumentsAsWritten) + Record.readTemplateArgumentListInfo(TemplArgsWritten); + + FD->setDependentTemplateSpecialization( + Reader.getContext(), Candidates, + HasTemplateArgumentsAsWritten ? &TemplArgsWritten : nullptr); // These are not merged; we don't need to merge redeclarations of dependent // template friends. break; } } + VisitDeclaratorDecl(FD); + + // Attach a type to this function. Use the real type if possible, but fall + // back to the type as written if it involves a deduced return type. + if (FD->getTypeSourceInfo() && FD->getTypeSourceInfo() + ->getType() + ->castAs<FunctionType>() + ->getReturnType() + ->getContainedAutoType()) { + // We'll set up the real type in Visit, once we've finished loading the + // function. + FD->setType(FD->getTypeSourceInfo()->getType()); + Reader.PendingDeducedFunctionTypes.push_back({FD, DeferredTypeID}); + } else { + FD->setType(Reader.GetType(DeferredTypeID)); + } + DeferredTypeID = 0; + + FD->DNLoc = Record.readDeclarationNameLoc(FD->getDeclName()); + FD->IdentifierNamespace = Record.readInt(); + + // FunctionDecl's body is handled last at ASTDeclReader::Visit, + // after everything else is read. + BitsUnpacker FunctionDeclBits(Record.readInt()); + + FD->setCachedLinkage((Linkage)FunctionDeclBits.getNextBits(/*Width=*/3)); + FD->setStorageClass((StorageClass)FunctionDeclBits.getNextBits(/*Width=*/3)); + FD->setInlineSpecified(FunctionDeclBits.getNextBit()); + FD->setImplicitlyInline(FunctionDeclBits.getNextBit()); + FD->setHasSkippedBody(FunctionDeclBits.getNextBit()); + FD->setVirtualAsWritten(FunctionDeclBits.getNextBit()); + // We defer calling `FunctionDecl::setPure()` here as for methods of + // `CXXTemplateSpecializationDecl`s, we may not have connected up the + // definition (which is required for `setPure`). + const bool Pure = FunctionDeclBits.getNextBit(); + FD->setHasInheritedPrototype(FunctionDeclBits.getNextBit()); + FD->setHasWrittenPrototype(FunctionDeclBits.getNextBit()); + FD->setDeletedAsWritten(FunctionDeclBits.getNextBit()); + FD->setTrivial(FunctionDeclBits.getNextBit()); + FD->setTrivialForCall(FunctionDeclBits.getNextBit()); + FD->setDefaulted(FunctionDeclBits.getNextBit()); + FD->setExplicitlyDefaulted(FunctionDeclBits.getNextBit()); + FD->setIneligibleOrNotSelected(FunctionDeclBits.getNextBit()); + FD->setConstexprKind( + (ConstexprSpecKind)FunctionDeclBits.getNextBits(/*Width=*/2)); + FD->setHasImplicitReturnZero(FunctionDeclBits.getNextBit()); + FD->setIsMultiVersion(FunctionDeclBits.getNextBit()); + FD->setLateTemplateParsed(FunctionDeclBits.getNextBit()); + FD->setFriendConstraintRefersToEnclosingTemplate( + FunctionDeclBits.getNextBit()); + FD->setUsesSEHTry(FunctionDeclBits.getNextBit()); + + FD->EndRangeLoc = readSourceLocation(); + if (FD->isExplicitlyDefaulted()) + FD->setDefaultLoc(readSourceLocation()); + + FD->ODRHash = Record.readInt(); + FD->setHasODRHash(true); + + if (FD->isDefaulted() || FD->isDeletedAsWritten()) { + // If 'Info' is nonzero, we need to read an DefaultedOrDeletedInfo; if, + // additionally, the second bit is also set, we also need to read + // a DeletedMessage for the DefaultedOrDeletedInfo. + if (auto Info = Record.readInt()) { + bool HasMessage = Info & 2; + StringLiteral *DeletedMessage = + HasMessage ? cast<StringLiteral>(Record.readExpr()) : nullptr; + + unsigned NumLookups = Record.readInt(); + SmallVector<DeclAccessPair, 8> Lookups; + for (unsigned I = 0; I != NumLookups; ++I) { + NamedDecl *ND = Record.readDeclAs<NamedDecl>(); + AccessSpecifier AS = (AccessSpecifier)Record.readInt(); + Lookups.push_back(DeclAccessPair::make(ND, AS)); + } + + FD->setDefaultedOrDeletedInfo( + FunctionDecl::DefaultedOrDeletedFunctionInfo::Create( + Reader.getContext(), Lookups, DeletedMessage)); + } + } + + if (Existing) + mergeRedeclarable(FD, Existing, Redecl); + else if (auto Kind = FD->getTemplatedKind(); + Kind == FunctionDecl::TK_FunctionTemplate || + Kind == FunctionDecl::TK_FunctionTemplateSpecialization) { + // Function Templates have their FunctionTemplateDecls merged instead of + // their FunctionDecls. + auto merge = [this, &Redecl, FD](auto &&F) { + auto *Existing = cast_or_null<FunctionDecl>(Redecl.getKnownMergeTarget()); + RedeclarableResult NewRedecl(Existing ? F(Existing) : nullptr, + Redecl.getFirstID(), Redecl.isKeyDecl()); + mergeRedeclarableTemplate(F(FD), NewRedecl); + }; + if (Kind == FunctionDecl::TK_FunctionTemplate) + merge( + [](FunctionDecl *FD) { return FD->getDescribedFunctionTemplate(); }); + else + merge([](FunctionDecl *FD) { + return FD->getTemplateSpecializationInfo()->getTemplate(); + }); + } else + mergeRedeclarable(FD, Redecl); + // Defer calling `setPure` until merging above has guaranteed we've set // `DefinitionData` (as this will need to access it). - FD->setPure(Pure); + FD->setIsPureVirtual(Pure); // Read in the parameters. unsigned NumParams = Record.readInt(); @@ -1037,7 +1157,6 @@ void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { // Load the body on-demand. Most clients won't care, because method // definitions rarely show up in headers. Reader.PendingBodies[MD] = GetCurrentCursorOffset(); - HasPendingBody = true; } MD->setSelfDecl(readDeclAs<ImplicitParamDecl>()); MD->setCmdDecl(readDeclAs<ImplicitParamDecl>()); @@ -1055,7 +1174,8 @@ void ASTDeclReader::VisitObjCMethodDecl(ObjCMethodDecl *MD) { Reader.getContext().setObjCMethodRedeclaration(MD, readDeclAs<ObjCMethodDecl>()); - MD->setDeclImplementation((ObjCMethodDecl::ImplementationControl)Record.readInt()); + MD->setDeclImplementation( + static_cast<ObjCImplementationControl>(Record.readInt())); MD->setObjCDeclQualifier((Decl::ObjCDeclQualifier)Record.readInt()); MD->setRelatedResultType(Record.readInt()); MD->setReturnType(Record.readType()); @@ -1121,6 +1241,8 @@ void ASTDeclReader::ReadObjCDefinitionData( Data.EndLoc = readSourceLocation(); Data.HasDesignatedInitializers = Record.readInt(); + Data.ODRHash = Record.readInt(); + Data.HasODRHash = true; // Read the directly referenced protocols and their SourceLocations. unsigned NumProtocols = Record.readInt(); @@ -1147,7 +1269,17 @@ void ASTDeclReader::ReadObjCDefinitionData( void ASTDeclReader::MergeDefinitionData(ObjCInterfaceDecl *D, struct ObjCInterfaceDecl::DefinitionData &&NewDD) { - // FIXME: odr checking? + struct ObjCInterfaceDecl::DefinitionData &DD = D->data(); + if (DD.Definition == NewDD.Definition) + return; + + Reader.MergedDeclContexts.insert( + std::make_pair(NewDD.Definition, DD.Definition)); + Reader.mergeDefinitionVisibility(DD.Definition, NewDD.Definition); + + if (D->getODRHash() != NewDD.ODRHash) + Reader.PendingObjCInterfaceOdrMergeFailures[DD.Definition].push_back( + {NewDD.Definition, &NewDD}); } void ASTDeclReader::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ID) { @@ -1194,6 +1326,39 @@ void ASTDeclReader::VisitObjCIvarDecl(ObjCIvarDecl *IVD) { IVD->setNextIvar(nullptr); bool synth = Record.readInt(); IVD->setSynthesize(synth); + + // Check ivar redeclaration. + if (IVD->isInvalidDecl()) + return; + // Don't check ObjCInterfaceDecl as interfaces are named and mismatches can be + // detected in VisitObjCInterfaceDecl. Here we are looking for redeclarations + // in extensions. + if (isa<ObjCInterfaceDecl>(IVD->getDeclContext())) + return; + ObjCInterfaceDecl *CanonIntf = + IVD->getContainingInterface()->getCanonicalDecl(); + IdentifierInfo *II = IVD->getIdentifier(); + ObjCIvarDecl *PrevIvar = CanonIntf->lookupInstanceVariable(II); + if (PrevIvar && PrevIvar != IVD) { + auto *ParentExt = dyn_cast<ObjCCategoryDecl>(IVD->getDeclContext()); + auto *PrevParentExt = + dyn_cast<ObjCCategoryDecl>(PrevIvar->getDeclContext()); + if (ParentExt && PrevParentExt) { + // Postpone diagnostic as we should merge identical extensions from + // different modules. + Reader + .PendingObjCExtensionIvarRedeclarations[std::make_pair(ParentExt, + PrevParentExt)] + .push_back(std::make_pair(IVD, PrevIvar)); + } else if (ParentExt || PrevParentExt) { + // Duplicate ivars in extension + implementation are never compatible. + // Compatibility of implementation + implementation should be handled in + // VisitObjCImplementationDecl. + Reader.Diag(IVD->getLocation(), diag::err_duplicate_ivar_declaration) + << II; + Reader.Diag(PrevIvar->getLocation(), diag::note_previous_definition); + } + } } void ASTDeclReader::ReadObjCDefinitionData( @@ -1209,11 +1374,23 @@ void ASTDeclReader::ReadObjCDefinitionData( ProtoLocs.push_back(readSourceLocation()); Data.ReferencedProtocols.set(ProtoRefs.data(), NumProtoRefs, ProtoLocs.data(), Reader.getContext()); + Data.ODRHash = Record.readInt(); + Data.HasODRHash = true; } -void ASTDeclReader::MergeDefinitionData(ObjCProtocolDecl *D, - struct ObjCProtocolDecl::DefinitionData &&NewDD) { - // FIXME: odr checking? +void ASTDeclReader::MergeDefinitionData( + ObjCProtocolDecl *D, struct ObjCProtocolDecl::DefinitionData &&NewDD) { + struct ObjCProtocolDecl::DefinitionData &DD = D->data(); + if (DD.Definition == NewDD.Definition) + return; + + Reader.MergedDeclContexts.insert( + std::make_pair(NewDD.Definition, DD.Definition)); + Reader.mergeDefinitionVisibility(DD.Definition, NewDD.Definition); + + if (D->getODRHash() != NewDD.ODRHash) + Reader.PendingObjCProtocolOdrMergeFailures[DD.Definition].push_back( + {NewDD.Definition, &NewDD}); } void ASTDeclReader::VisitObjCProtocolDecl(ObjCProtocolDecl *PD) { @@ -1348,15 +1525,13 @@ void ASTDeclReader::VisitFieldDecl(FieldDecl *FD) { VisitDeclaratorDecl(FD); FD->Mutable = Record.readInt(); - if (auto ISK = static_cast<FieldDecl::InitStorageKind>(Record.readInt())) { - FD->InitStorage.setInt(ISK); - FD->InitStorage.setPointer(ISK == FieldDecl::ISK_CapturedVLAType - ? Record.readType().getAsOpaquePtr() - : Record.readExpr()); - } - - if (auto *BW = Record.readExpr()) - FD->setBitWidth(BW); + unsigned Bits = Record.readInt(); + FD->StorageKind = Bits >> 1; + if (FD->StorageKind == FieldDecl::ISK_CapturedVLAType) + FD->CapturedVLAType = + cast<VariableArrayType>(Record.readType().getTypePtr()); + else if (Bits & 1) + FD->setBitWidth(Record.readExpr()); if (!FD->getDeclName()) { if (auto *Tmpl = readDeclAs<FieldDecl>()) @@ -1384,6 +1559,17 @@ void ASTDeclReader::VisitMSGuidDecl(MSGuidDecl *D) { Reader.getContext().setPrimaryMergedDecl(D, Existing->getCanonicalDecl()); } +void ASTDeclReader::VisitUnnamedGlobalConstantDecl( + UnnamedGlobalConstantDecl *D) { + VisitValueDecl(D); + D->Value = Record.readAPValue(); + + // Add this to the AST context's lookup structure, and merge if needed. + if (UnnamedGlobalConstantDecl *Existing = + Reader.getContext().UnnamedGlobalConstantDecls.GetOrInsertNode(D)) + Reader.getContext().setPrimaryMergedDecl(D, Existing->getCanonicalDecl()); +} + void ASTDeclReader::VisitTemplateParamObjectDecl(TemplateParamObjectDecl *D) { VisitValueDecl(D); D->Value = Record.readAPValue(); @@ -1412,54 +1598,64 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { RedeclarableResult Redecl = VisitRedeclarable(VD); VisitDeclaratorDecl(VD); - VD->VarDeclBits.SClass = (StorageClass)Record.readInt(); - VD->VarDeclBits.TSCSpec = Record.readInt(); - VD->VarDeclBits.InitStyle = Record.readInt(); - VD->VarDeclBits.ARCPseudoStrong = Record.readInt(); + BitsUnpacker VarDeclBits(Record.readInt()); + auto VarLinkage = Linkage(VarDeclBits.getNextBits(/*Width=*/3)); + bool DefGeneratedInModule = VarDeclBits.getNextBit(); + VD->VarDeclBits.SClass = (StorageClass)VarDeclBits.getNextBits(/*Width=*/3); + VD->VarDeclBits.TSCSpec = VarDeclBits.getNextBits(/*Width=*/2); + VD->VarDeclBits.InitStyle = VarDeclBits.getNextBits(/*Width=*/2); + VD->VarDeclBits.ARCPseudoStrong = VarDeclBits.getNextBit(); + bool HasDeducedType = false; if (!isa<ParmVarDecl>(VD)) { VD->NonParmVarDeclBits.IsThisDeclarationADemotedDefinition = - Record.readInt(); - VD->NonParmVarDeclBits.ExceptionVar = Record.readInt(); - VD->NonParmVarDeclBits.NRVOVariable = Record.readInt(); - VD->NonParmVarDeclBits.CXXForRangeDecl = Record.readInt(); - VD->NonParmVarDeclBits.ObjCForDecl = Record.readInt(); - VD->NonParmVarDeclBits.IsInline = Record.readInt(); - VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt(); - VD->NonParmVarDeclBits.IsConstexpr = Record.readInt(); - VD->NonParmVarDeclBits.IsInitCapture = Record.readInt(); - VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = Record.readInt(); - VD->NonParmVarDeclBits.ImplicitParamKind = Record.readInt(); - VD->NonParmVarDeclBits.EscapingByref = Record.readInt(); - } - auto VarLinkage = Linkage(Record.readInt()); + VarDeclBits.getNextBit(); + VD->NonParmVarDeclBits.ExceptionVar = VarDeclBits.getNextBit(); + VD->NonParmVarDeclBits.NRVOVariable = VarDeclBits.getNextBit(); + VD->NonParmVarDeclBits.CXXForRangeDecl = VarDeclBits.getNextBit(); + + VD->NonParmVarDeclBits.IsInline = VarDeclBits.getNextBit(); + VD->NonParmVarDeclBits.IsInlineSpecified = VarDeclBits.getNextBit(); + VD->NonParmVarDeclBits.IsConstexpr = VarDeclBits.getNextBit(); + VD->NonParmVarDeclBits.IsInitCapture = VarDeclBits.getNextBit(); + VD->NonParmVarDeclBits.PreviousDeclInSameBlockScope = + VarDeclBits.getNextBit(); + + VD->NonParmVarDeclBits.EscapingByref = VarDeclBits.getNextBit(); + HasDeducedType = VarDeclBits.getNextBit(); + VD->NonParmVarDeclBits.ImplicitParamKind = + VarDeclBits.getNextBits(/*Width*/ 3); + + VD->NonParmVarDeclBits.ObjCForDecl = VarDeclBits.getNextBit(); + } + + // If this variable has a deduced type, defer reading that type until we are + // done deserializing this variable, because the type might refer back to the + // variable. + if (HasDeducedType) + Reader.PendingDeducedVarTypes.push_back({VD, DeferredTypeID}); + else + VD->setType(Reader.GetType(DeferredTypeID)); + DeferredTypeID = 0; + VD->setCachedLinkage(VarLinkage); // Reconstruct the one piece of the IdentifierNamespace that we need. - if (VD->getStorageClass() == SC_Extern && VarLinkage != NoLinkage && + if (VD->getStorageClass() == SC_Extern && VarLinkage != Linkage::None && VD->getLexicalDeclContext()->isFunctionOrMethod()) VD->setLocalExternDecl(); - if (uint64_t Val = Record.readInt()) { - VD->setInit(Record.readExpr()); - if (Val != 1) { - EvaluatedStmt *Eval = VD->ensureEvaluatedStmt(); - Eval->HasConstantInitialization = (Val & 2) != 0; - Eval->HasConstantDestruction = (Val & 4) != 0; - } + if (DefGeneratedInModule) { + Reader.DefinitionSource[VD] = + Loc.F->Kind == ModuleKind::MK_MainFile || + Reader.getContext().getLangOpts().BuildingPCHWithObjectFile; } - if (VD->hasAttr<BlocksAttr>() && VD->getType()->getAsCXXRecordDecl()) { + if (VD->hasAttr<BlocksAttr>()) { Expr *CopyExpr = Record.readExpr(); if (CopyExpr) Reader.getContext().setBlockVarCopyInit(VD, CopyExpr, Record.readInt()); } - if (VD->getStorageDuration() == SD_Static && Record.readInt()) { - Reader.DefinitionSource[VD] = - Loc.F->Kind == ModuleKind::MK_MainFile || - Reader.getContext().getLangOpts().BuildingPCHWithObjectFile; - } - enum VarKind { VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization }; @@ -1488,16 +1684,37 @@ ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarDeclImpl(VarDecl *VD) { return Redecl; } +void ASTDeclReader::ReadVarDeclInit(VarDecl *VD) { + if (uint64_t Val = Record.readInt()) { + EvaluatedStmt *Eval = VD->ensureEvaluatedStmt(); + Eval->HasConstantInitialization = (Val & 2) != 0; + Eval->HasConstantDestruction = (Val & 4) != 0; + Eval->WasEvaluated = (Val & 8) != 0; + if (Eval->WasEvaluated) { + Eval->Evaluated = Record.readAPValue(); + if (Eval->Evaluated.needsCleanup()) + Reader.getContext().addDestruction(&Eval->Evaluated); + } + + // Store the offset of the initializer. Don't deserialize it yet: it might + // not be needed, and might refer back to the variable, for example if it + // contains a lambda. + Eval->Value = GetCurrentCursorOffset(); + } +} + void ASTDeclReader::VisitImplicitParamDecl(ImplicitParamDecl *PD) { VisitVarDecl(PD); } void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) { VisitVarDecl(PD); - unsigned isObjCMethodParam = Record.readInt(); - unsigned scopeDepth = Record.readInt(); + unsigned scopeIndex = Record.readInt(); - unsigned declQualifier = Record.readInt(); + BitsUnpacker ParmVarDeclBits(Record.readInt()); + unsigned isObjCMethodParam = ParmVarDeclBits.getNextBit(); + unsigned scopeDepth = ParmVarDeclBits.getNextBits(/*Width=*/7); + unsigned declQualifier = ParmVarDeclBits.getNextBits(/*Width=*/7); if (isObjCMethodParam) { assert(scopeDepth == 0); PD->setObjCMethodScopeInfo(scopeIndex); @@ -1505,11 +1722,15 @@ void ASTDeclReader::VisitParmVarDecl(ParmVarDecl *PD) { } else { PD->setScopeInfo(scopeDepth, scopeIndex); } - PD->ParmVarDeclBits.IsKNRPromoted = Record.readInt(); - PD->ParmVarDeclBits.HasInheritedDefaultArg = Record.readInt(); - if (Record.readInt()) // hasUninstantiatedDefaultArg. + PD->ParmVarDeclBits.IsKNRPromoted = ParmVarDeclBits.getNextBit(); + + PD->ParmVarDeclBits.HasInheritedDefaultArg = ParmVarDeclBits.getNextBit(); + if (ParmVarDeclBits.getNextBit()) // hasUninstantiatedDefaultArg. PD->setUninstantiatedDefaultArg(Record.readExpr()); + if (ParmVarDeclBits.getNextBit()) // Valid explicit object parameter + PD->ExplicitObjectParameterIntroducerLoc = Record.readSourceLocation(); + // FIXME: If this is a redeclaration of a function from another module, handle // inheritance of default arguments. } @@ -1534,6 +1755,11 @@ void ASTDeclReader::VisitFileScopeAsmDecl(FileScopeAsmDecl *AD) { AD->setRParenLoc(readSourceLocation()); } +void ASTDeclReader::VisitTopLevelStmtDecl(TopLevelStmtDecl *D) { + VisitDecl(D); + D->Statement = Record.readStmt(); +} + void ASTDeclReader::VisitBlockDecl(BlockDecl *BD) { VisitDecl(BD); BD->setBody(cast_or_null<CompoundStmt>(Record.readStmt())); @@ -1582,7 +1808,7 @@ void ASTDeclReader::VisitCapturedDecl(CapturedDecl *CD) { void ASTDeclReader::VisitLinkageSpecDecl(LinkageSpecDecl *D) { VisitDecl(D); - D->setLanguage((LinkageSpecDecl::LanguageIDs)Record.readInt()); + D->setLanguage(static_cast<LinkageSpecLanguageIDs>(Record.readInt())); D->setExternLoc(readSourceLocation()); D->setRBraceLoc(readSourceLocation()); } @@ -1600,7 +1826,10 @@ void ASTDeclReader::VisitLabelDecl(LabelDecl *D) { void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { RedeclarableResult Redecl = VisitRedeclarable(D); VisitNamedDecl(D); - D->setInline(Record.readInt()); + + BitsUnpacker NamespaceDeclBits(Record.readInt()); + D->setInline(NamespaceDeclBits.getNextBit()); + D->setNested(NamespaceDeclBits.getNextBit()); D->LocStart = readSourceLocation(); D->RBraceLoc = readSourceLocation(); @@ -1608,18 +1837,13 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { // this namespace; loading it might load a later declaration of the // same namespace, and we have an invariant that older declarations // get merged before newer ones try to merge. - GlobalDeclID AnonNamespace = 0; - if (Redecl.getFirstID() == ThisDeclID) { + GlobalDeclID AnonNamespace; + if (Redecl.getFirstID() == ThisDeclID) AnonNamespace = readDeclID(); - } else { - // Link this namespace back to the first declaration, which has already - // been deserialized. - D->AnonOrFirstNamespaceAndInline.setPointer(D->getFirstDecl()); - } mergeRedeclarable(D, Redecl); - if (AnonNamespace) { + if (AnonNamespace.isValid()) { // Each module has its own anonymous namespace, which is disjoint from // any other module's anonymous namespaces, so don't attach the anonymous // namespace at all. @@ -1629,6 +1853,15 @@ void ASTDeclReader::VisitNamespaceDecl(NamespaceDecl *D) { } } +void ASTDeclReader::VisitHLSLBufferDecl(HLSLBufferDecl *D) { + VisitNamedDecl(D); + VisitDeclContext(D); + D->IsCBuffer = Record.readBool(); + D->KwLoc = readSourceLocation(); + D->LBraceLoc = readSourceLocation(); + D->RBraceLoc = readSourceLocation(); +} + void ASTDeclReader::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { RedeclarableResult Redecl = VisitRedeclarable(D); VisitNamedDecl(D); @@ -1651,6 +1884,17 @@ void ASTDeclReader::VisitUsingDecl(UsingDecl *D) { mergeMergeable(D); } +void ASTDeclReader::VisitUsingEnumDecl(UsingEnumDecl *D) { + VisitNamedDecl(D); + D->setUsingLoc(readSourceLocation()); + D->setEnumLoc(readSourceLocation()); + D->setEnumType(Record.readTypeSourceInfo()); + D->FirstUsingShadow.setPointer(readDeclAs<UsingShadowDecl>()); + if (auto *Pattern = readDeclAs<UsingEnumDecl>()) + Reader.getContext().setInstantiatedFromUsingEnumDecl(D, Pattern); + mergeMergeable(D); +} + void ASTDeclReader::VisitUsingPackDecl(UsingPackDecl *D) { VisitNamedDecl(D); D->InstantiatedFrom = readDeclAs<NamedDecl>(); @@ -1707,68 +1951,99 @@ void ASTDeclReader::VisitUnresolvedUsingTypenameDecl( mergeMergeable(D); } +void ASTDeclReader::VisitUnresolvedUsingIfExistsDecl( + UnresolvedUsingIfExistsDecl *D) { + VisitNamedDecl(D); +} + void ASTDeclReader::ReadCXXDefinitionData( - struct CXXRecordDecl::DefinitionData &Data, const CXXRecordDecl *D) { - #define FIELD(Name, Width, Merge) \ - Data.Name = Record.readInt(); - #include "clang/AST/CXXRecordDeclDefinitionBits.def" + struct CXXRecordDecl::DefinitionData &Data, const CXXRecordDecl *D, + Decl *LambdaContext, unsigned IndexInLambdaContext) { + + BitsUnpacker CXXRecordDeclBits = Record.readInt(); + +#define FIELD(Name, Width, Merge) \ + if (!CXXRecordDeclBits.canGetNextNBits(Width)) \ + CXXRecordDeclBits.updateValue(Record.readInt()); \ + Data.Name = CXXRecordDeclBits.getNextBits(Width); + +#include "clang/AST/CXXRecordDeclDefinitionBits.def" +#undef FIELD // Note: the caller has deserialized the IsLambda bit already. Data.ODRHash = Record.readInt(); Data.HasODRHash = true; if (Record.readInt()) { - Reader.DefinitionSource[D] = + Reader.DefinitionSource[D] = Loc.F->Kind == ModuleKind::MK_MainFile || Reader.getContext().getLangOpts().BuildingPCHWithObjectFile; } - Data.NumBases = Record.readInt(); - if (Data.NumBases) - Data.Bases = ReadGlobalOffset(); - Data.NumVBases = Record.readInt(); - if (Data.NumVBases) - Data.VBases = ReadGlobalOffset(); - Record.readUnresolvedSet(Data.Conversions); Data.ComputedVisibleConversions = Record.readInt(); if (Data.ComputedVisibleConversions) Record.readUnresolvedSet(Data.VisibleConversions); assert(Data.Definition && "Data.Definition should be already set!"); - Data.FirstFriend = readDeclID(); - if (Data.IsLambda) { + if (!Data.IsLambda) { + assert(!LambdaContext && !IndexInLambdaContext && + "given lambda context for non-lambda"); + + Data.NumBases = Record.readInt(); + if (Data.NumBases) + Data.Bases = ReadGlobalOffset(); + + Data.NumVBases = Record.readInt(); + if (Data.NumVBases) + Data.VBases = ReadGlobalOffset(); + + Data.FirstFriend = readDeclID().getRawValue(); + } else { using Capture = LambdaCapture; auto &Lambda = static_cast<CXXRecordDecl::LambdaDefinitionData &>(Data); - Lambda.Dependent = Record.readInt(); - Lambda.IsGenericLambda = Record.readInt(); - Lambda.CaptureDefault = Record.readInt(); - Lambda.NumCaptures = Record.readInt(); + + BitsUnpacker LambdaBits(Record.readInt()); + Lambda.DependencyKind = LambdaBits.getNextBits(/*Width=*/2); + Lambda.IsGenericLambda = LambdaBits.getNextBit(); + Lambda.CaptureDefault = LambdaBits.getNextBits(/*Width=*/2); + Lambda.NumCaptures = LambdaBits.getNextBits(/*Width=*/15); + Lambda.HasKnownInternalLinkage = LambdaBits.getNextBit(); + Lambda.NumExplicitCaptures = Record.readInt(); - Lambda.HasKnownInternalLinkage = Record.readInt(); Lambda.ManglingNumber = Record.readInt(); - D->setDeviceLambdaManglingNumber(Record.readInt()); - Lambda.ContextDecl = readDeclID(); - Lambda.Captures = (Capture *)Reader.getContext().Allocate( - sizeof(Capture) * Lambda.NumCaptures); - Capture *ToCapture = Lambda.Captures; + if (unsigned DeviceManglingNumber = Record.readInt()) + Reader.getContext().DeviceLambdaManglingNumbers[D] = DeviceManglingNumber; + Lambda.IndexInContext = IndexInLambdaContext; + Lambda.ContextDecl = LambdaContext; + Capture *ToCapture = nullptr; + if (Lambda.NumCaptures) { + ToCapture = (Capture *)Reader.getContext().Allocate(sizeof(Capture) * + Lambda.NumCaptures); + Lambda.AddCaptureList(Reader.getContext(), ToCapture); + } Lambda.MethodTyInfo = readTypeSourceInfo(); for (unsigned I = 0, N = Lambda.NumCaptures; I != N; ++I) { SourceLocation Loc = readSourceLocation(); - bool IsImplicit = Record.readInt(); - auto Kind = static_cast<LambdaCaptureKind>(Record.readInt()); + BitsUnpacker CaptureBits(Record.readInt()); + bool IsImplicit = CaptureBits.getNextBit(); + auto Kind = + static_cast<LambdaCaptureKind>(CaptureBits.getNextBits(/*Width=*/3)); switch (Kind) { case LCK_StarThis: case LCK_This: case LCK_VLAType: - *ToCapture++ = Capture(Loc, IsImplicit, Kind, nullptr,SourceLocation()); + new (ToCapture) + Capture(Loc, IsImplicit, Kind, nullptr, SourceLocation()); + ToCapture++; break; case LCK_ByCopy: case LCK_ByRef: - auto *Var = readDeclAs<VarDecl>(); + auto *Var = readDeclAs<ValueDecl>(); SourceLocation EllipsisLoc = readSourceLocation(); - *ToCapture++ = Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc); + new (ToCapture) Capture(Loc, IsImplicit, Kind, Var, EllipsisLoc); + ToCapture++; break; } } @@ -1788,7 +2063,7 @@ void ASTDeclReader::MergeDefinitionData( Reader.PendingDefinitions.erase(MergeDD.Definition); MergeDD.Definition->setCompleteDefinition(false); Reader.mergeDefinitionVisibility(DD.Definition, MergeDD.Definition); - assert(Reader.Lookups.find(MergeDD.Definition) == Reader.Lookups.end() && + assert(!Reader.Lookups.contains(MergeDD.Definition) && "already loaded pending lookups for merged definition"); } @@ -1836,10 +2111,32 @@ void ASTDeclReader::MergeDefinitionData( // lazily load it. if (DD.IsLambda) { - // FIXME: ODR-checking for merging lambdas (this happens, for instance, - // when they occur within the body of a function template specialization). + auto &Lambda1 = static_cast<CXXRecordDecl::LambdaDefinitionData &>(DD); + auto &Lambda2 = static_cast<CXXRecordDecl::LambdaDefinitionData &>(MergeDD); + DetectedOdrViolation |= Lambda1.DependencyKind != Lambda2.DependencyKind; + DetectedOdrViolation |= Lambda1.IsGenericLambda != Lambda2.IsGenericLambda; + DetectedOdrViolation |= Lambda1.CaptureDefault != Lambda2.CaptureDefault; + DetectedOdrViolation |= Lambda1.NumCaptures != Lambda2.NumCaptures; + DetectedOdrViolation |= + Lambda1.NumExplicitCaptures != Lambda2.NumExplicitCaptures; + DetectedOdrViolation |= + Lambda1.HasKnownInternalLinkage != Lambda2.HasKnownInternalLinkage; + DetectedOdrViolation |= Lambda1.ManglingNumber != Lambda2.ManglingNumber; + + if (Lambda1.NumCaptures && Lambda1.NumCaptures == Lambda2.NumCaptures) { + for (unsigned I = 0, N = Lambda1.NumCaptures; I != N; ++I) { + LambdaCapture &Cap1 = Lambda1.Captures.front()[I]; + LambdaCapture &Cap2 = Lambda2.Captures.front()[I]; + DetectedOdrViolation |= Cap1.getCaptureKind() != Cap2.getCaptureKind(); + } + Lambda1.AddCaptureList(Reader.getContext(), Lambda2.Captures.front()); + } } + // We don't want to check ODR for decls in the global module fragment. + if (shouldSkipCheckingODR(MergeDD.Definition) || shouldSkipCheckingODR(D)) + return; + if (D->getODRHash() != MergeDD.ODRHash) { DetectedOdrViolation = true; } @@ -1849,16 +2146,20 @@ void ASTDeclReader::MergeDefinitionData( {MergeDD.Definition, &MergeDD}); } -void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) { +void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update, + Decl *LambdaContext, + unsigned IndexInLambdaContext) { struct CXXRecordDecl::DefinitionData *DD; ASTContext &C = Reader.getContext(); // Determine whether this is a lambda closure type, so that we can // allocate the appropriate DefinitionData structure. bool IsLambda = Record.readInt(); + assert(!(IsLambda && Update) && + "lambda definition should not be added by update record"); if (IsLambda) - DD = new (C) CXXRecordDecl::LambdaDefinitionData(D, nullptr, false, false, - LCD_None); + DD = new (C) CXXRecordDecl::LambdaDefinitionData( + D, nullptr, CXXRecordDecl::LDK_Unknown, false, LCD_None); else DD = new (C) struct CXXRecordDecl::DefinitionData(D); @@ -1869,7 +2170,7 @@ void ASTDeclReader::ReadCXXRecordDefinition(CXXRecordDecl *D, bool Update) { if (!Canon->DefinitionData) Canon->DefinitionData = DD; D->DefinitionData = Canon->DefinitionData; - ReadCXXDefinitionData(*DD, D); + ReadCXXDefinitionData(*DD, D, LambdaContext, IndexInLambdaContext); // We might already have a different definition for this record. This can // happen either because we're reading an update record, or because we've @@ -1896,8 +2197,15 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { ASTContext &C = Reader.getContext(); enum CXXRecKind { - CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization + CXXRecNotTemplate = 0, + CXXRecTemplate, + CXXRecMemberSpecialization, + CXXLambda }; + + Decl *LambdaContext = nullptr; + unsigned IndexInLambdaContext = 0; + switch ((CXXRecKind)Record.readInt()) { case CXXRecNotTemplate: // Merged when we merge the folding set entry in the primary template. @@ -1929,11 +2237,19 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { mergeRedeclarable(D, Redecl); break; } + case CXXLambda: { + LambdaContext = readDecl(); + if (LambdaContext) + IndexInLambdaContext = Record.readInt(); + mergeLambda(D, Redecl, LambdaContext, IndexInLambdaContext); + break; + } } bool WasDefinition = Record.readInt(); if (WasDefinition) - ReadCXXRecordDefinition(D, /*Update*/false); + ReadCXXRecordDefinition(D, /*Update=*/false, LambdaContext, + IndexInLambdaContext); else // Propagate DefinitionData pointer from the canonical declaration. D->DefinitionData = D->getCanonicalDecl()->DefinitionData; @@ -1941,12 +2257,12 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { // Lazily load the key function to avoid deserializing every method so we can // compute it. if (WasDefinition) { - DeclID KeyFn = readDeclID(); - if (KeyFn && D->isCompleteDefinition()) + GlobalDeclID KeyFn = readDeclID(); + if (KeyFn.isValid() && D->isCompleteDefinition()) // FIXME: This is wrong for the ARM ABI, where some other module may have // made this function no longer be a key function. We need an update // record or similar for that case. - C.KeyFunctions[D] = KeyFn; + C.KeyFunctions[D] = KeyFn.getRawValue(); } return Redecl; @@ -1954,8 +2270,10 @@ ASTDeclReader::VisitCXXRecordDeclImpl(CXXRecordDecl *D) { void ASTDeclReader::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { D->setExplicitSpecifier(Record.readExplicitSpec()); + D->Ctor = readDeclAs<CXXConstructorDecl>(); VisitFunctionDecl(D); - D->setIsCopyDeductionCandidate(Record.readInt()); + D->setDeductionCandidateKind( + static_cast<DeductionCandidate>(Record.readInt())); } void ASTDeclReader::VisitCXXMethodDecl(CXXMethodDecl *D) { @@ -2033,7 +2351,7 @@ void ASTDeclReader::VisitFriendDecl(FriendDecl *D) { for (unsigned i = 0; i != D->NumTPLists; ++i) D->getTrailingObjects<TemplateParameterList *>()[i] = Record.readTemplateParameterList(); - D->NextFriend = readDeclID(); + D->NextFriend = readDeclID().getRawValue(); D->UnsupportedFriend = (Record.readInt() != 0); D->FriendLoc = readSourceLocation(); } @@ -2042,7 +2360,7 @@ void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) { VisitDecl(D); unsigned NumParams = Record.readInt(); D->NumParams = NumParams; - D->Params = new TemplateParameterList*[NumParams]; + D->Params = new (Reader.getContext()) TemplateParameterList *[NumParams]; for (unsigned i = 0; i != NumParams; ++i) D->Params[i] = Record.readTemplateParameterList(); if (Record.readInt()) // HasFriendDecl @@ -2052,15 +2370,12 @@ void ASTDeclReader::VisitFriendTemplateDecl(FriendTemplateDecl *D) { D->FriendLoc = readSourceLocation(); } -DeclID ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { +void ASTDeclReader::VisitTemplateDecl(TemplateDecl *D) { VisitNamedDecl(D); - DeclID PatternID = readDeclID(); - auto *TemplatedDecl = cast_or_null<NamedDecl>(Reader.GetDecl(PatternID)); - TemplateParameterList *TemplateParams = Record.readTemplateParameterList(); - D->init(TemplatedDecl, TemplateParams); - - return PatternID; + assert(!D->TemplateParams && "TemplateParams already set!"); + D->TemplateParams = Record.readTemplateParameterList(); + D->init(readDeclAs<NamedDecl>()); } void ASTDeclReader::VisitConceptDecl(ConceptDecl *D) { @@ -2069,6 +2384,17 @@ void ASTDeclReader::VisitConceptDecl(ConceptDecl *D) { mergeMergeable(D); } +void ASTDeclReader::VisitImplicitConceptSpecializationDecl( + ImplicitConceptSpecializationDecl *D) { + // The size of the template list was read during creation of the Decl, so we + // don't have to re-read it here. + VisitDecl(D); + llvm::SmallVector<TemplateArgument, 4> Args; + for (unsigned I = 0; I < D->NumTemplateArgs; ++I) + Args.push_back(Record.readTemplateArgument(/*Canonicalize=*/true)); + D->setTemplateArguments(Args); +} + void ASTDeclReader::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) { } @@ -2097,26 +2423,20 @@ ASTDeclReader::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { } } - DeclID PatternID = VisitTemplateDecl(D); + VisitTemplateDecl(D); D->IdentifierNamespace = Record.readInt(); - mergeRedeclarable(D, Redecl, PatternID); - - // If we merged the template with a prior declaration chain, merge the common - // pointer. - // FIXME: Actually merge here, don't just overwrite. - D->Common = D->getCanonicalDecl()->Common; - return Redecl; } void ASTDeclReader::VisitClassTemplateDecl(ClassTemplateDecl *D) { RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); + mergeRedeclarableTemplate(D, Redecl); if (ThisDeclID == Redecl.getFirstID()) { // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of // the specializations. - SmallVector<serialization::DeclID, 32> SpecIDs; + SmallVector<GlobalDeclID, 32> SpecIDs; readDeclIDList(SpecIDs); ASTDeclReader::AddLazySpecializations(D, SpecIDs); } @@ -2139,11 +2459,12 @@ void ASTDeclReader::VisitBuiltinTemplateDecl(BuiltinTemplateDecl *D) { /// VarTemplateDecl beyond TemplateDecl... void ASTDeclReader::VisitVarTemplateDecl(VarTemplateDecl *D) { RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); + mergeRedeclarableTemplate(D, Redecl); if (ThisDeclID == Redecl.getFirstID()) { // This VarTemplateDecl owns a CommonPtr; read it to keep track of all of // the specializations. - SmallVector<serialization::DeclID, 32> SpecIDs; + SmallVector<GlobalDeclID, 32> SpecIDs; readDeclIDList(SpecIDs); ASTDeclReader::AddLazySpecializations(D, SpecIDs); } @@ -2209,16 +2530,17 @@ ASTDeclReader::VisitClassTemplateSpecializationDeclImpl( } } - // Explicit info. - if (TypeSourceInfo *TyInfo = readTypeSourceInfo()) { - auto *ExplicitInfo = - new (C) ClassTemplateSpecializationDecl::ExplicitSpecializationInfo; - ExplicitInfo->TypeAsWritten = TyInfo; - ExplicitInfo->ExternLoc = readSourceLocation(); + // extern/template keyword locations for explicit instantiations + if (Record.readBool()) { + auto *ExplicitInfo = new (C) ExplicitInstantiationInfo; + ExplicitInfo->ExternKeywordLoc = readSourceLocation(); ExplicitInfo->TemplateKeywordLoc = readSourceLocation(); D->ExplicitInfo = ExplicitInfo; } + if (Record.readBool()) + D->setTemplateArgsAsWritten(Record.readASTTemplateArgumentListInfo()); + return Redecl; } @@ -2228,7 +2550,6 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl( // need them for profiling TemplateParameterList *Params = Record.readTemplateParameterList(); D->TemplateParams = Params; - D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); RedeclarableResult Redecl = VisitClassTemplateSpecializationDeclImpl(D); @@ -2240,20 +2561,12 @@ void ASTDeclReader::VisitClassTemplatePartialSpecializationDecl( } } -void ASTDeclReader::VisitClassScopeFunctionSpecializationDecl( - ClassScopeFunctionSpecializationDecl *D) { - VisitDecl(D); - D->Specialization = readDeclAs<CXXMethodDecl>(); - if (Record.readInt()) - D->TemplateArgs = Record.readASTTemplateArgumentListInfo(); -} - void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); if (ThisDeclID == Redecl.getFirstID()) { // This FunctionTemplateDecl owns a CommonPtr; read it. - SmallVector<serialization::DeclID, 32> SpecIDs; + SmallVector<GlobalDeclID, 32> SpecIDs; readDeclIDList(SpecIDs); ASTDeclReader::AddLazySpecializations(D, SpecIDs); } @@ -2267,8 +2580,6 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { ASTDeclReader::RedeclarableResult ASTDeclReader::VisitVarTemplateSpecializationDeclImpl( VarTemplateSpecializationDecl *D) { - RedeclarableResult Redecl = VisitVarDeclImpl(D); - ASTContext &C = Reader.getContext(); if (Decl *InstD = readDecl()) { if (auto *VTD = dyn_cast<VarTemplateDecl>(InstD)) { @@ -2288,16 +2599,17 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl( } } - // Explicit info. - if (TypeSourceInfo *TyInfo = readTypeSourceInfo()) { - auto *ExplicitInfo = - new (C) VarTemplateSpecializationDecl::ExplicitSpecializationInfo; - ExplicitInfo->TypeAsWritten = TyInfo; - ExplicitInfo->ExternLoc = readSourceLocation(); + // extern/template keyword locations for explicit instantiations + if (Record.readBool()) { + auto *ExplicitInfo = new (C) ExplicitInstantiationInfo; + ExplicitInfo->ExternKeywordLoc = readSourceLocation(); ExplicitInfo->TemplateKeywordLoc = readSourceLocation(); D->ExplicitInfo = ExplicitInfo; } + if (Record.readBool()) + D->setTemplateArgsAsWritten(Record.readASTTemplateArgumentListInfo()); + SmallVector<TemplateArgument, 8> TemplArgs; Record.readTemplateArgumentList(TemplArgs, /*Canonicalize*/ true); D->TemplateArgs = TemplateArgumentList::CreateCopy(C, TemplArgs); @@ -2305,17 +2617,23 @@ ASTDeclReader::VisitVarTemplateSpecializationDeclImpl( D->SpecializationKind = (TemplateSpecializationKind)Record.readInt(); D->IsCompleteDefinition = Record.readInt(); + RedeclarableResult Redecl = VisitVarDeclImpl(D); + bool writtenAsCanonicalDecl = Record.readInt(); if (writtenAsCanonicalDecl) { auto *CanonPattern = readDeclAs<VarTemplateDecl>(); if (D->isCanonicalDecl()) { // It's kept in the folding set. - // FIXME: If it's already present, merge it. + VarTemplateSpecializationDecl *CanonSpec; if (auto *Partial = dyn_cast<VarTemplatePartialSpecializationDecl>(D)) { - CanonPattern->getCommonPtr()->PartialSpecializations - .GetOrInsertNode(Partial); + CanonSpec = CanonPattern->getCommonPtr() + ->PartialSpecializations.GetOrInsertNode(Partial); } else { - CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D); + CanonSpec = + CanonPattern->getCommonPtr()->Specializations.GetOrInsertNode(D); } + // If we already have a matching specialization, merge it. + if (CanonSpec != D) + mergeRedeclarable<VarDecl>(D, CanonSpec, Redecl); } } @@ -2331,7 +2649,6 @@ void ASTDeclReader::VisitVarTemplatePartialSpecializationDecl( VarTemplatePartialSpecializationDecl *D) { TemplateParameterList *Params = Record.readTemplateParameterList(); D->TemplateParams = Params; - D->ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); RedeclarableResult Redecl = VisitVarTemplateSpecializationDeclImpl(D); @@ -2348,22 +2665,21 @@ void ASTDeclReader::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { D->setDeclaredWithTypename(Record.readInt()); - if (Record.readBool()) { - NestedNameSpecifierLoc NNS = Record.readNestedNameSpecifierLoc(); - DeclarationNameInfo DN = Record.readDeclarationNameInfo(); - ConceptDecl *NamedConcept = Record.readDeclAs<ConceptDecl>(); - const ASTTemplateArgumentListInfo *ArgsAsWritten = nullptr; + const bool TypeConstraintInitialized = Record.readBool(); + if (TypeConstraintInitialized && D->hasTypeConstraint()) { + ConceptReference *CR = nullptr; if (Record.readBool()) - ArgsAsWritten = Record.readASTTemplateArgumentListInfo(); + CR = Record.readConceptReference(); Expr *ImmediatelyDeclaredConstraint = Record.readExpr(); - D->setTypeConstraint(NNS, DN, /*FoundDecl=*/nullptr, NamedConcept, - ArgsAsWritten, ImmediatelyDeclaredConstraint); + + D->setTypeConstraint(CR, ImmediatelyDeclaredConstraint); if ((D->ExpandedParameterPack = Record.readInt())) D->NumExpanded = Record.readInt(); } if (Record.readInt()) - D->setDefaultArgument(readTypeSourceInfo()); + D->setDefaultArgument(Reader.getContext(), + Record.readTemplateArgumentLoc()); } void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { @@ -2384,12 +2700,14 @@ void ASTDeclReader::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { // Rest of NonTypeTemplateParmDecl. D->ParameterPack = Record.readInt(); if (Record.readInt()) - D->setDefaultArgument(Record.readExpr()); + D->setDefaultArgument(Reader.getContext(), + Record.readTemplateArgumentLoc()); } } void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { VisitTemplateDecl(D); + D->setDeclaredWithTypename(Record.readBool()); // TemplateParmPosition. D->setDepth(Record.readInt()); D->setPosition(Record.readInt()); @@ -2408,7 +2726,8 @@ void ASTDeclReader::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { } void ASTDeclReader::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { - VisitRedeclarableTemplateDecl(D); + RedeclarableResult Redecl = VisitRedeclarableTemplateDecl(D); + mergeRedeclarableTemplate(D, Redecl); } void ASTDeclReader::VisitStaticAssertDecl(StaticAssertDecl *D) { @@ -2446,7 +2765,7 @@ ASTDeclReader::VisitDeclContext(DeclContext *DC) { template <typename T> ASTDeclReader::RedeclarableResult ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { - DeclID FirstDeclID = readDeclID(); + GlobalDeclID FirstDeclID = readDeclID(); Decl *MergeWith = nullptr; bool IsKeyDecl = ThisDeclID == FirstDeclID; @@ -2454,9 +2773,9 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { uint64_t RedeclOffset = 0; - // 0 indicates that this declaration was the only declaration of its entity, - // and is used for space optimization. - if (FirstDeclID == 0) { + // invalid FirstDeclID indicates that this declaration was the only + // declaration of its entity, and is used for space optimization. + if (FirstDeclID.isInvalid()) { FirstDeclID = ThisDeclID; IsKeyDecl = true; IsFirstLocalDecl = true; @@ -2505,10 +2824,9 @@ ASTDeclReader::VisitRedeclarable(Redeclarable<T> *D) { /// Attempts to merge the given declaration (D) with another declaration /// of the same entity. -template<typename T> +template <typename T> void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, - RedeclarableResult &Redecl, - DeclID TemplatePatternID) { + RedeclarableResult &Redecl) { // If modules are not available, there is no reason to perform this merge. if (!Reader.getContext().getLangOpts().Modules) return; @@ -2521,10 +2839,54 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, if (auto *Existing = Redecl.getKnownMergeTarget()) // We already know of an existing declaration we should merge with. - mergeRedeclarable(D, cast<T>(Existing), Redecl, TemplatePatternID); + mergeRedeclarable(D, cast<T>(Existing), Redecl); else if (FindExistingResult ExistingRes = findExisting(D)) if (T *Existing = ExistingRes) - mergeRedeclarable(D, Existing, Redecl, TemplatePatternID); + mergeRedeclarable(D, Existing, Redecl); +} + +/// Attempt to merge D with a previous declaration of the same lambda, which is +/// found by its index within its context declaration, if it has one. +/// +/// We can't look up lambdas in their enclosing lexical or semantic context in +/// general, because for lambdas in variables, both of those might be a +/// namespace or the translation unit. +void ASTDeclReader::mergeLambda(CXXRecordDecl *D, RedeclarableResult &Redecl, + Decl *Context, unsigned IndexInContext) { + // If we don't have a mangling context, treat this like any other + // declaration. + if (!Context) + return mergeRedeclarable(D, Redecl); + + // If modules are not available, there is no reason to perform this merge. + if (!Reader.getContext().getLangOpts().Modules) + return; + + // If we're not the canonical declaration, we don't need to merge. + if (!D->isFirstDecl()) + return; + + if (auto *Existing = Redecl.getKnownMergeTarget()) + // We already know of an existing declaration we should merge with. + mergeRedeclarable(D, cast<TagDecl>(Existing), Redecl); + + // Look up this lambda to see if we've seen it before. If so, merge with the + // one we already loaded. + NamedDecl *&Slot = Reader.LambdaDeclarationsForMerging[{ + Context->getCanonicalDecl(), IndexInContext}]; + if (Slot) + mergeRedeclarable(D, cast<TagDecl>(Slot), Redecl); + else + Slot = D; +} + +void ASTDeclReader::mergeRedeclarableTemplate(RedeclarableTemplateDecl *D, + RedeclarableResult &Redecl) { + mergeRedeclarable(D, Redecl); + // If we merged the template with a prior declaration chain, merge the + // common pointer. + // FIXME: Actually merge here, don't just overwrite. + D->Common = D->getCanonicalDecl()->Common; } /// "Cast" to type T, asserting if we don't have an implicit conversion. @@ -2539,12 +2901,12 @@ template<typename T> static T assert_cast(...) { /// declarations. void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D, RedeclarableTemplateDecl *Existing, - DeclID DsID, bool IsKeyDecl) { + bool IsKeyDecl) { auto *DPattern = D->getTemplatedDecl(); auto *ExistingPattern = Existing->getTemplatedDecl(); - RedeclarableResult Result(/*MergeWith*/ ExistingPattern, - DPattern->getCanonicalDecl()->getGlobalID(), - IsKeyDecl); + RedeclarableResult Result( + /*MergeWith*/ ExistingPattern, + DPattern->getCanonicalDecl()->getGlobalID(), IsKeyDecl); if (auto *DClass = dyn_cast<CXXRecordDecl>(DPattern)) { // Merge with any existing definition. @@ -2579,17 +2941,13 @@ void ASTDeclReader::mergeTemplatePattern(RedeclarableTemplateDecl *D, /// Attempts to merge the given declaration (D) with another declaration /// of the same entity. -template<typename T> +template <typename T> void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing, - RedeclarableResult &Redecl, - DeclID TemplatePatternID) { + RedeclarableResult &Redecl) { auto *D = static_cast<T *>(DBase); T *ExistingCanon = Existing->getCanonicalDecl(); T *DCanon = D->getCanonicalDecl(); if (ExistingCanon != DCanon) { - assert(DCanon->getGlobalID() == Redecl.getFirstID() && - "already merged this declaration"); - // Have our redeclaration link point back at the canonical declaration // of the existing declaration, so that this declaration has the // appropriate canonical declaration. @@ -2598,18 +2956,11 @@ void ASTDeclReader::mergeRedeclarable(Redeclarable<T> *DBase, T *Existing, ExistingCanon->Used |= D->Used; D->Used = false; - // When we merge a namespace, update its pointer to the first namespace. - // We cannot have loaded any redeclarations of this declaration yet, so - // there's nothing else that needs to be updated. - if (auto *Namespace = dyn_cast<NamespaceDecl>(D)) - Namespace->AnonOrFirstNamespaceAndInline.setPointer( - assert_cast<NamespaceDecl*>(ExistingCanon)); - // When we merge a template, merge its pattern. if (auto *DTemplate = dyn_cast<RedeclarableTemplateDecl>(D)) mergeTemplatePattern( - DTemplate, assert_cast<RedeclarableTemplateDecl*>(ExistingCanon), - TemplatePatternID, Redecl.isKeyDecl()); + DTemplate, assert_cast<RedeclarableTemplateDecl *>(ExistingCanon), + Redecl.isKeyDecl()); // If this declaration is a key declaration, make a note of that. if (Redecl.isKeyDecl()) @@ -2626,7 +2977,7 @@ static bool allowODRLikeMergeInC(NamedDecl *ND) { if (!ND) return false; // TODO: implement merge for other necessary decls. - if (isa<EnumConstantDecl>(ND)) + if (isa<EnumConstantDecl, FieldDecl, IndirectFieldDecl>(ND)) return true; return false; } @@ -2701,16 +3052,16 @@ void ASTDeclReader::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { Expr *Priv = Record.readExpr(); D->setInitializerData(Orig, Priv); Expr *Init = Record.readExpr(); - auto IK = static_cast<OMPDeclareReductionDecl::InitKind>(Record.readInt()); + auto IK = static_cast<OMPDeclareReductionInitKind>(Record.readInt()); D->setInitializer(Init, IK); - D->PrevDeclInScope = readDeclID(); + D->PrevDeclInScope = readDeclID().getRawValue(); } void ASTDeclReader::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) { Record.readOMPChildren(D->Data); VisitValueDecl(D); D->VarName = Record.readDeclarationName(); - D->PrevDeclInScope = readDeclID(); + D->PrevDeclInScope = readDeclID().getRawValue(); } void ASTDeclReader::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) { @@ -2732,6 +3083,8 @@ public: return Reader.readInt(); } + bool readBool() { return Reader.readBool(); } + SourceRange readSourceRange() { return Reader.readSourceRange(); } @@ -2742,6 +3095,8 @@ public: Expr *readExpr() { return Reader.readExpr(); } + Attr *readAttr() { return Reader.readAttr(); } + std::string readString() { return Reader.readString(); } @@ -2760,9 +3115,7 @@ public: OMPTraitInfo *readOMPTraitInfo() { return Reader.readOMPTraitInfo(); } - template <typename T> T *GetLocalDeclAs(uint32_t LocalID) { - return Reader.GetLocalDeclAs<T>(LocalID); - } + template <typename T> T *readDeclAs() { return Reader.readDeclAs<T>(); } }; } @@ -2785,10 +3138,15 @@ Attr *ASTRecordReader::readAttr() { unsigned ParsedKind = Record.readInt(); unsigned Syntax = Record.readInt(); unsigned SpellingIndex = Record.readInt(); + bool IsAlignas = (ParsedKind == AttributeCommonInfo::AT_Aligned && + Syntax == AttributeCommonInfo::AS_Keyword && + SpellingIndex == AlignedAttr::Keyword_alignas); + bool IsRegularKeywordAttribute = Record.readBool(); AttributeCommonInfo Info(AttrName, ScopeName, AttrRange, ScopeLoc, AttributeCommonInfo::Kind(ParsedKind), - AttributeCommonInfo::Syntax(Syntax), SpellingIndex); + {AttributeCommonInfo::Syntax(Syntax), SpellingIndex, + IsAlignas, IsRegularKeywordAttribute}); #include "clang/Serialization/AttrPCHRead.inc" @@ -2799,7 +3157,8 @@ Attr *ASTRecordReader::readAttr() { /// Reads attributes from the current stream position. void ASTRecordReader::readAttributes(AttrVec &Attrs) { for (unsigned I = 0, E = readInt(); I != E; ++I) - Attrs.push_back(readAttr()); + if (auto *A = readAttr()) + Attrs.push_back(A); } //===----------------------------------------------------------------------===// @@ -2823,7 +3182,7 @@ inline void ASTReader::LoadedDecl(unsigned Index, Decl *D) { /// This routine should return true for anything that might affect /// code generation, e.g., inline function definitions, Objective-C /// declarations with metadata, etc. -static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) { +bool ASTReader::isConsumerInterestedIn(Decl *D) { // An ObjCMethodDecl is never considered as "interesting" because its // implementation container always is. @@ -2832,27 +3191,22 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) { if (isPartOfPerModuleInitializer(D)) { auto *M = D->getImportedOwningModule(); if (M && M->Kind == Module::ModuleMapModule && - Ctx.DeclMustBeEmitted(D)) + getContext().DeclMustBeEmitted(D)) return false; } - if (isa<FileScopeAsmDecl>(D) || - isa<ObjCProtocolDecl>(D) || - isa<ObjCImplDecl>(D) || - isa<ImportDecl>(D) || - isa<PragmaCommentDecl>(D) || - isa<PragmaDetectMismatchDecl>(D)) + if (isa<FileScopeAsmDecl, TopLevelStmtDecl, ObjCProtocolDecl, ObjCImplDecl, + ImportDecl, PragmaCommentDecl, PragmaDetectMismatchDecl>(D)) return true; - if (isa<OMPThreadPrivateDecl>(D) || isa<OMPDeclareReductionDecl>(D) || - isa<OMPDeclareMapperDecl>(D) || isa<OMPAllocateDecl>(D) || - isa<OMPRequiresDecl>(D)) + if (isa<OMPThreadPrivateDecl, OMPDeclareReductionDecl, OMPDeclareMapperDecl, + OMPAllocateDecl, OMPRequiresDecl>(D)) return !D->getDeclContext()->isFunctionOrMethod(); if (const auto *Var = dyn_cast<VarDecl>(D)) return Var->isFileVarDecl() && (Var->isThisDeclarationADefinition() == VarDecl::Definition || OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(Var)); if (const auto *Func = dyn_cast<FunctionDecl>(D)) - return Func->doesThisDeclarationHaveABody() || HasBody; + return Func->doesThisDeclarationHaveABody() || PendingBodies.count(D); if (auto *ES = D->getASTContext().getExternalSource()) if (ES->hasExternalDefinitions(D) == ExternalASTSource::EK_Never) @@ -2862,14 +3216,13 @@ static bool isConsumerInterestedIn(ASTContext &Ctx, Decl *D, bool HasBody) { } /// Get the correct cursor and offset for loading a declaration. -ASTReader::RecordLocation -ASTReader::DeclCursorForID(DeclID ID, SourceLocation &Loc) { - GlobalDeclMapType::iterator I = GlobalDeclMap.find(ID); - assert(I != GlobalDeclMap.end() && "Corrupted global declaration map"); - ModuleFile *M = I->second; - const DeclOffset &DOffs = - M->DeclOffsets[ID - M->BaseDeclID - NUM_PREDEF_DECL_IDS]; - Loc = TranslateSourceLocation(*M, DOffs.getLocation()); +ASTReader::RecordLocation ASTReader::DeclCursorForID(GlobalDeclID ID, + SourceLocation &Loc) { + ModuleFile *M = getOwningModuleFile(ID); + assert(M); + unsigned LocalDeclIndex = ID.getLocalDeclIndex(); + const DeclOffset &DOffs = M->DeclOffsets[LocalDeclIndex]; + Loc = ReadSourceLocation(*M, DOffs.getRawLoc()); return RecordLocation(M, DOffs.getBitOffset(M->DeclsBlockStartOffset)); } @@ -2884,376 +3237,30 @@ uint64_t ASTReader::getGlobalBitOffset(ModuleFile &M, uint64_t LocalOffset) { return LocalOffset + M.GlobalBitOffset; } -static bool isSameTemplateParameterList(const ASTContext &C, - const TemplateParameterList *X, - const TemplateParameterList *Y); - -/// Determine whether two template parameters are similar enough -/// that they may be used in declarations of the same template. -static bool isSameTemplateParameter(const NamedDecl *X, - const NamedDecl *Y) { - if (X->getKind() != Y->getKind()) - return false; - - if (const auto *TX = dyn_cast<TemplateTypeParmDecl>(X)) { - const auto *TY = cast<TemplateTypeParmDecl>(Y); - if (TX->isParameterPack() != TY->isParameterPack()) - return false; - if (TX->hasTypeConstraint() != TY->hasTypeConstraint()) - return false; - const TypeConstraint *TXTC = TX->getTypeConstraint(); - const TypeConstraint *TYTC = TY->getTypeConstraint(); - if (!TXTC != !TYTC) - return false; - if (TXTC && TYTC) { - if (TXTC->getNamedConcept() != TYTC->getNamedConcept()) - return false; - if (TXTC->hasExplicitTemplateArgs() != TYTC->hasExplicitTemplateArgs()) - return false; - if (TXTC->hasExplicitTemplateArgs()) { - const auto *TXTCArgs = TXTC->getTemplateArgsAsWritten(); - const auto *TYTCArgs = TYTC->getTemplateArgsAsWritten(); - if (TXTCArgs->NumTemplateArgs != TYTCArgs->NumTemplateArgs) - return false; - llvm::FoldingSetNodeID XID, YID; - for (const auto &ArgLoc : TXTCArgs->arguments()) - ArgLoc.getArgument().Profile(XID, X->getASTContext()); - for (const auto &ArgLoc : TYTCArgs->arguments()) - ArgLoc.getArgument().Profile(YID, Y->getASTContext()); - if (XID != YID) - return false; - } - } - return true; - } - - if (const auto *TX = dyn_cast<NonTypeTemplateParmDecl>(X)) { - const auto *TY = cast<NonTypeTemplateParmDecl>(Y); - return TX->isParameterPack() == TY->isParameterPack() && - TX->getASTContext().hasSameType(TX->getType(), TY->getType()); - } - - const auto *TX = cast<TemplateTemplateParmDecl>(X); - const auto *TY = cast<TemplateTemplateParmDecl>(Y); - return TX->isParameterPack() == TY->isParameterPack() && - isSameTemplateParameterList(TX->getASTContext(), - TX->getTemplateParameters(), - TY->getTemplateParameters()); -} - -static NamespaceDecl *getNamespace(const NestedNameSpecifier *X) { - if (auto *NS = X->getAsNamespace()) - return NS; - if (auto *NAS = X->getAsNamespaceAlias()) - return NAS->getNamespace(); - return nullptr; -} - -static bool isSameQualifier(const NestedNameSpecifier *X, - const NestedNameSpecifier *Y) { - if (auto *NSX = getNamespace(X)) { - auto *NSY = getNamespace(Y); - if (!NSY || NSX->getCanonicalDecl() != NSY->getCanonicalDecl()) - return false; - } else if (X->getKind() != Y->getKind()) - return false; - - // FIXME: For namespaces and types, we're permitted to check that the entity - // is named via the same tokens. We should probably do so. - switch (X->getKind()) { - case NestedNameSpecifier::Identifier: - if (X->getAsIdentifier() != Y->getAsIdentifier()) - return false; - break; - case NestedNameSpecifier::Namespace: - case NestedNameSpecifier::NamespaceAlias: - // We've already checked that we named the same namespace. - break; - case NestedNameSpecifier::TypeSpec: - case NestedNameSpecifier::TypeSpecWithTemplate: - if (X->getAsType()->getCanonicalTypeInternal() != - Y->getAsType()->getCanonicalTypeInternal()) - return false; - break; - case NestedNameSpecifier::Global: - case NestedNameSpecifier::Super: - return true; - } - - // Recurse into earlier portion of NNS, if any. - auto *PX = X->getPrefix(); - auto *PY = Y->getPrefix(); - if (PX && PY) - return isSameQualifier(PX, PY); - return !PX && !PY; -} - -/// Determine whether two template parameter lists are similar enough -/// that they may be used in declarations of the same template. -static bool isSameTemplateParameterList(const ASTContext &C, - const TemplateParameterList *X, - const TemplateParameterList *Y) { - if (X->size() != Y->size()) - return false; - - for (unsigned I = 0, N = X->size(); I != N; ++I) - if (!isSameTemplateParameter(X->getParam(I), Y->getParam(I))) - return false; - - const Expr *XRC = X->getRequiresClause(); - const Expr *YRC = Y->getRequiresClause(); - if (!XRC != !YRC) - return false; - if (XRC) { - llvm::FoldingSetNodeID XRCID, YRCID; - XRC->Profile(XRCID, C, /*Canonical=*/true); - YRC->Profile(YRCID, C, /*Canonical=*/true); - if (XRCID != YRCID) - return false; - } - - return true; -} - -/// Determine whether the attributes we can overload on are identical for A and -/// B. Will ignore any overloadable attrs represented in the type of A and B. -static bool hasSameOverloadableAttrs(const FunctionDecl *A, - const FunctionDecl *B) { - // Note that pass_object_size attributes are represented in the function's - // ExtParameterInfo, so we don't need to check them here. - - llvm::FoldingSetNodeID Cand1ID, Cand2ID; - auto AEnableIfAttrs = A->specific_attrs<EnableIfAttr>(); - auto BEnableIfAttrs = B->specific_attrs<EnableIfAttr>(); - - for (auto Pair : zip_longest(AEnableIfAttrs, BEnableIfAttrs)) { - Optional<EnableIfAttr *> Cand1A = std::get<0>(Pair); - Optional<EnableIfAttr *> Cand2A = std::get<1>(Pair); - - // Return false if the number of enable_if attributes is different. - if (!Cand1A || !Cand2A) - return false; - - Cand1ID.clear(); - Cand2ID.clear(); - - (*Cand1A)->getCond()->Profile(Cand1ID, A->getASTContext(), true); - (*Cand2A)->getCond()->Profile(Cand2ID, B->getASTContext(), true); - - // Return false if any of the enable_if expressions of A and B are - // different. - if (Cand1ID != Cand2ID) - return false; - } - return true; -} - -/// Determine whether the two declarations refer to the same entity.pr -static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { - assert(X->getDeclName() == Y->getDeclName() && "Declaration name mismatch!"); - - if (X == Y) - return true; - - // Must be in the same context. - // - // Note that we can't use DeclContext::Equals here, because the DeclContexts - // could be two different declarations of the same function. (We will fix the - // semantic DC to refer to the primary definition after merging.) - if (!declaresSameEntity(cast<Decl>(X->getDeclContext()->getRedeclContext()), - cast<Decl>(Y->getDeclContext()->getRedeclContext()))) - return false; - - // Two typedefs refer to the same entity if they have the same underlying - // type. - if (const auto *TypedefX = dyn_cast<TypedefNameDecl>(X)) - if (const auto *TypedefY = dyn_cast<TypedefNameDecl>(Y)) - return X->getASTContext().hasSameType(TypedefX->getUnderlyingType(), - TypedefY->getUnderlyingType()); - - // Must have the same kind. - if (X->getKind() != Y->getKind()) - return false; - - // Objective-C classes and protocols with the same name always match. - if (isa<ObjCInterfaceDecl>(X) || isa<ObjCProtocolDecl>(X)) - return true; - - if (isa<ClassTemplateSpecializationDecl>(X)) { - // No need to handle these here: we merge them when adding them to the - // template. - return false; - } - - // Compatible tags match. - if (const auto *TagX = dyn_cast<TagDecl>(X)) { - const auto *TagY = cast<TagDecl>(Y); - return (TagX->getTagKind() == TagY->getTagKind()) || - ((TagX->getTagKind() == TTK_Struct || TagX->getTagKind() == TTK_Class || - TagX->getTagKind() == TTK_Interface) && - (TagY->getTagKind() == TTK_Struct || TagY->getTagKind() == TTK_Class || - TagY->getTagKind() == TTK_Interface)); - } - - // Functions with the same type and linkage match. - // FIXME: This needs to cope with merging of prototyped/non-prototyped - // functions, etc. - if (const auto *FuncX = dyn_cast<FunctionDecl>(X)) { - const auto *FuncY = cast<FunctionDecl>(Y); - if (const auto *CtorX = dyn_cast<CXXConstructorDecl>(X)) { - const auto *CtorY = cast<CXXConstructorDecl>(Y); - if (CtorX->getInheritedConstructor() && - !isSameEntity(CtorX->getInheritedConstructor().getConstructor(), - CtorY->getInheritedConstructor().getConstructor())) - return false; - } - - if (FuncX->isMultiVersion() != FuncY->isMultiVersion()) - return false; - - // Multiversioned functions with different feature strings are represented - // as separate declarations. - if (FuncX->isMultiVersion()) { - const auto *TAX = FuncX->getAttr<TargetAttr>(); - const auto *TAY = FuncY->getAttr<TargetAttr>(); - assert(TAX && TAY && "Multiversion Function without target attribute"); - - if (TAX->getFeaturesStr() != TAY->getFeaturesStr()) - return false; - } - - ASTContext &C = FuncX->getASTContext(); - - const Expr *XRC = FuncX->getTrailingRequiresClause(); - const Expr *YRC = FuncY->getTrailingRequiresClause(); - if (!XRC != !YRC) - return false; - if (XRC) { - llvm::FoldingSetNodeID XRCID, YRCID; - XRC->Profile(XRCID, C, /*Canonical=*/true); - YRC->Profile(YRCID, C, /*Canonical=*/true); - if (XRCID != YRCID) - return false; - } - - auto GetTypeAsWritten = [](const FunctionDecl *FD) { - // Map to the first declaration that we've already merged into this one. - // The TSI of redeclarations might not match (due to calling conventions - // being inherited onto the type but not the TSI), but the TSI type of - // the first declaration of the function should match across modules. - FD = FD->getCanonicalDecl(); - return FD->getTypeSourceInfo() ? FD->getTypeSourceInfo()->getType() - : FD->getType(); - }; - QualType XT = GetTypeAsWritten(FuncX), YT = GetTypeAsWritten(FuncY); - if (!C.hasSameType(XT, YT)) { - // We can get functions with different types on the redecl chain in C++17 - // if they have differing exception specifications and at least one of - // the excpetion specs is unresolved. - auto *XFPT = XT->getAs<FunctionProtoType>(); - auto *YFPT = YT->getAs<FunctionProtoType>(); - if (C.getLangOpts().CPlusPlus17 && XFPT && YFPT && - (isUnresolvedExceptionSpec(XFPT->getExceptionSpecType()) || - isUnresolvedExceptionSpec(YFPT->getExceptionSpecType())) && - C.hasSameFunctionTypeIgnoringExceptionSpec(XT, YT)) - return true; - return false; - } - - return FuncX->getLinkageInternal() == FuncY->getLinkageInternal() && - hasSameOverloadableAttrs(FuncX, FuncY); - } - - // Variables with the same type and linkage match. - if (const auto *VarX = dyn_cast<VarDecl>(X)) { - const auto *VarY = cast<VarDecl>(Y); - if (VarX->getLinkageInternal() == VarY->getLinkageInternal()) { - ASTContext &C = VarX->getASTContext(); - if (C.hasSameType(VarX->getType(), VarY->getType())) - return true; - - // We can get decls with different types on the redecl chain. Eg. - // template <typename T> struct S { static T Var[]; }; // #1 - // template <typename T> T S<T>::Var[sizeof(T)]; // #2 - // Only? happens when completing an incomplete array type. In this case - // when comparing #1 and #2 we should go through their element type. - const ArrayType *VarXTy = C.getAsArrayType(VarX->getType()); - const ArrayType *VarYTy = C.getAsArrayType(VarY->getType()); - if (!VarXTy || !VarYTy) - return false; - if (VarXTy->isIncompleteArrayType() || VarYTy->isIncompleteArrayType()) - return C.hasSameType(VarXTy->getElementType(), VarYTy->getElementType()); - } - return false; - } - - // Namespaces with the same name and inlinedness match. - if (const auto *NamespaceX = dyn_cast<NamespaceDecl>(X)) { - const auto *NamespaceY = cast<NamespaceDecl>(Y); - return NamespaceX->isInline() == NamespaceY->isInline(); - } - - // Identical template names and kinds match if their template parameter lists - // and patterns match. - if (const auto *TemplateX = dyn_cast<TemplateDecl>(X)) { - const auto *TemplateY = cast<TemplateDecl>(Y); - return isSameEntity(TemplateX->getTemplatedDecl(), - TemplateY->getTemplatedDecl()) && - isSameTemplateParameterList(TemplateX->getASTContext(), - TemplateX->getTemplateParameters(), - TemplateY->getTemplateParameters()); - } - - // Fields with the same name and the same type match. - if (const auto *FDX = dyn_cast<FieldDecl>(X)) { - const auto *FDY = cast<FieldDecl>(Y); - // FIXME: Also check the bitwidth is odr-equivalent, if any. - return X->getASTContext().hasSameType(FDX->getType(), FDY->getType()); - } - - // Indirect fields with the same target field match. - if (const auto *IFDX = dyn_cast<IndirectFieldDecl>(X)) { - const auto *IFDY = cast<IndirectFieldDecl>(Y); - return IFDX->getAnonField()->getCanonicalDecl() == - IFDY->getAnonField()->getCanonicalDecl(); - } +CXXRecordDecl * +ASTDeclReader::getOrFakePrimaryClassDefinition(ASTReader &Reader, + CXXRecordDecl *RD) { + // Try to dig out the definition. + auto *DD = RD->DefinitionData; + if (!DD) + DD = RD->getCanonicalDecl()->DefinitionData; - // Enumerators with the same name match. - if (isa<EnumConstantDecl>(X)) - // FIXME: Also check the value is odr-equivalent. - return true; + // If there's no definition yet, then DC's definition is added by an update + // record, but we've not yet loaded that update record. In this case, we + // commit to DC being the canonical definition now, and will fix this when + // we load the update record. + if (!DD) { + DD = new (Reader.getContext()) struct CXXRecordDecl::DefinitionData(RD); + RD->setCompleteDefinition(true); + RD->DefinitionData = DD; + RD->getCanonicalDecl()->DefinitionData = DD; - // Using shadow declarations with the same target match. - if (const auto *USX = dyn_cast<UsingShadowDecl>(X)) { - const auto *USY = cast<UsingShadowDecl>(Y); - return USX->getTargetDecl() == USY->getTargetDecl(); - } - - // Using declarations with the same qualifier match. (We already know that - // the name matches.) - if (const auto *UX = dyn_cast<UsingDecl>(X)) { - const auto *UY = cast<UsingDecl>(Y); - return isSameQualifier(UX->getQualifier(), UY->getQualifier()) && - UX->hasTypename() == UY->hasTypename() && - UX->isAccessDeclaration() == UY->isAccessDeclaration(); - } - if (const auto *UX = dyn_cast<UnresolvedUsingValueDecl>(X)) { - const auto *UY = cast<UnresolvedUsingValueDecl>(Y); - return isSameQualifier(UX->getQualifier(), UY->getQualifier()) && - UX->isAccessDeclaration() == UY->isAccessDeclaration(); - } - if (const auto *UX = dyn_cast<UnresolvedUsingTypenameDecl>(X)) - return isSameQualifier( - UX->getQualifier(), - cast<UnresolvedUsingTypenameDecl>(Y)->getQualifier()); - - // Namespace alias definitions with the same target match. - if (const auto *NAX = dyn_cast<NamespaceAliasDecl>(X)) { - const auto *NAY = cast<NamespaceAliasDecl>(Y); - return NAX->getNamespace()->Equals(NAY->getNamespace()); + // Track that we did this horrible thing so that we can fix it later. + Reader.PendingFakeDefinitionData.insert( + std::make_pair(DD, ASTReader::PendingFakeDefinitionKind::Fake)); } - return false; + return DD->Definition; } /// Find the context in which we should search for previous declarations when @@ -3261,40 +3268,24 @@ static bool isSameEntity(NamedDecl *X, NamedDecl *Y) { DeclContext *ASTDeclReader::getPrimaryContextForMerging(ASTReader &Reader, DeclContext *DC) { if (auto *ND = dyn_cast<NamespaceDecl>(DC)) - return ND->getOriginalNamespace(); - - if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) { - // Try to dig out the definition. - auto *DD = RD->DefinitionData; - if (!DD) - DD = RD->getCanonicalDecl()->DefinitionData; - - // If there's no definition yet, then DC's definition is added by an update - // record, but we've not yet loaded that update record. In this case, we - // commit to DC being the canonical definition now, and will fix this when - // we load the update record. - if (!DD) { - DD = new (Reader.getContext()) struct CXXRecordDecl::DefinitionData(RD); - RD->setCompleteDefinition(true); - RD->DefinitionData = DD; - RD->getCanonicalDecl()->DefinitionData = DD; - - // Track that we did this horrible thing so that we can fix it later. - Reader.PendingFakeDefinitionData.insert( - std::make_pair(DD, ASTReader::PendingFakeDefinitionKind::Fake)); - } + return ND->getFirstDecl(); - return DD->Definition; - } + if (auto *RD = dyn_cast<CXXRecordDecl>(DC)) + return getOrFakePrimaryClassDefinition(Reader, RD); + + if (auto *RD = dyn_cast<RecordDecl>(DC)) + return RD->getDefinition(); if (auto *ED = dyn_cast<EnumDecl>(DC)) - return ED->getASTContext().getLangOpts().CPlusPlus? ED->getDefinition() - : nullptr; + return ED->getDefinition(); + + if (auto *OID = dyn_cast<ObjCInterfaceDecl>(DC)) + return OID->getDefinition(); - // We can see the TU here only if we have no Sema object. In that case, - // there's no TU scope to look in, so using the DC alone is sufficient. + // We can see the TU here only if we have no Sema object. It is possible + // we're in clang-repl so we still need to get the primary context. if (auto *TU = dyn_cast<TranslationUnitDecl>(DC)) - return TU; + return TU->getPrimaryContext(); return nullptr; } @@ -3358,6 +3349,8 @@ ASTDeclReader::getPrimaryDCForAnonymousDecl(DeclContext *LexicalDC) { if (auto *RD = dyn_cast<CXXRecordDecl>(LexicalDC)) { auto *DD = RD->getCanonicalDecl()->DefinitionData; return DD ? DD->Definition : nullptr; + } else if (auto *OID = dyn_cast<ObjCInterfaceDecl>(LexicalDC)) { + return OID->getCanonicalDecl()->getDefinition(); } // For anything else, walk its merged redeclarations looking for a definition. @@ -3370,6 +3363,9 @@ ASTDeclReader::getPrimaryDCForAnonymousDecl(DeclContext *LexicalDC) { if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) if (MD->isThisDeclarationADefinition()) return MD; + if (auto *RD = dyn_cast<RecordDecl>(D)) + if (RD->isThisDeclarationADefinition()) + return RD; } // No merged definition yet. @@ -3428,12 +3424,13 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { return Result; } + ASTContext &C = Reader.getContext(); DeclContext *DC = D->getDeclContext()->getRedeclContext(); if (TypedefNameForLinkage) { auto It = Reader.ImportedTypedefNamesForLinkage.find( std::make_pair(DC, TypedefNameForLinkage)); if (It != Reader.ImportedTypedefNamesForLinkage.end()) - if (isSameEntity(It->second, D)) + if (C.isSameEntity(It->second, D)) return FindExistingResult(Reader, D, It->second, AnonymousDeclNumber, TypedefNameForLinkage); // Go on to check in other places in case an existing typedef name @@ -3445,7 +3442,7 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { // in its context by number. if (auto *Existing = getAnonymousDeclForMerging( Reader, D->getLexicalDeclContext(), AnonymousDeclNumber)) - if (isSameEntity(Existing, D)) + if (C.isSameEntity(Existing, D)) return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber, TypedefNameForLinkage); } else if (DC->isTranslationUnit() && @@ -3477,7 +3474,7 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { IEnd = IdResolver.end(); I != IEnd; ++I) { if (NamedDecl *Existing = getDeclForMerging(*I, TypedefNameForLinkage)) - if (isSameEntity(Existing, D)) + if (C.isSameEntity(Existing, D)) return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber, TypedefNameForLinkage); } @@ -3485,7 +3482,7 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { DeclContext::lookup_result R = MergeDC->noload_lookup(Name); for (DeclContext::lookup_iterator I = R.begin(), E = R.end(); I != E; ++I) { if (NamedDecl *Existing = getDeclForMerging(*I, TypedefNameForLinkage)) - if (isSameEntity(Existing, D)) + if (C.isSameEntity(Existing, D)) return FindExistingResult(Reader, D, Existing, AnonymousDeclNumber, TypedefNameForLinkage); } @@ -3497,11 +3494,14 @@ ASTDeclReader::FindExistingResult ASTDeclReader::findExisting(NamedDecl *D) { // If this declaration is from a merged context, make a note that we need to // check that the canonical definition of that context contains the decl. // + // Note that we don't perform ODR checks for decls from the global module + // fragment. + // // FIXME: We should do something similar if we merge two definitions of the // same template specialization into the same CXXRecordDecl. auto MergedDCIt = Reader.MergedDeclContexts.find(D->getLexicalDeclContext()); if (MergedDCIt != Reader.MergedDeclContexts.end() && - MergedDCIt->second == D->getDeclContext()) + !shouldSkipCheckingODR(D) && MergedDCIt->second == D->getDeclContext()) Reader.PendingOdrMergeChecks.push_back(D); return FindExistingResult(Reader, D, /*Existing=*/nullptr, @@ -3545,6 +3545,13 @@ void ASTDeclReader::mergeInheritableAttributes(ASTReader &Reader, Decl *D, NewAttr->setInherited(true); D->addAttr(NewAttr); } + + const auto *AA = Previous->getAttr<AvailabilityAttr>(); + if (AA && !D->hasAttr<AvailabilityAttr>()) { + NewAttr = AA->clone(Context); + NewAttr->setInherited(true); + D->addAttr(NewAttr); + } } template<typename DeclT> @@ -3678,6 +3685,54 @@ static void inheritDefaultTemplateArguments(ASTContext &Context, } } +// [basic.link]/p10: +// If two declarations of an entity are attached to different modules, +// the program is ill-formed; +static void checkMultipleDefinitionInNamedModules(ASTReader &Reader, Decl *D, + Decl *Previous) { + Module *M = Previous->getOwningModule(); + + // We only care about the case in named modules. + if (!M || !M->isNamedModule()) + return; + + // If it is previous implcitly introduced, it is not meaningful to + // diagnose it. + if (Previous->isImplicit()) + return; + + // FIXME: Get rid of the enumeration of decl types once we have an appropriate + // abstract for decls of an entity. e.g., the namespace decl and using decl + // doesn't introduce an entity. + if (!isa<VarDecl, FunctionDecl, TagDecl, RedeclarableTemplateDecl>(Previous)) + return; + + // Skip implicit instantiations since it may give false positive diagnostic + // messages. + // FIXME: Maybe this shows the implicit instantiations may have incorrect + // module owner ships. But given we've finished the compilation of a module, + // how can we add new entities to that module? + if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(Previous); + VTSD && !VTSD->isExplicitSpecialization()) + return; + if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Previous); + CTSD && !CTSD->isExplicitSpecialization()) + return; + if (auto *Func = dyn_cast<FunctionDecl>(Previous)) + if (auto *FTSI = Func->getTemplateSpecializationInfo(); + FTSI && !FTSI->isExplicitSpecialization()) + return; + + // It is fine if they are in the same module. + if (Reader.getContext().isInSameModule(M, D->getOwningModule())) + return; + + Reader.Diag(Previous->getLocation(), + diag::err_multiple_decl_in_different_modules) + << cast<NamedDecl>(Previous) << M->Name; + Reader.Diag(D->getLocation(), diag::note_also_found); +} + void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D, Decl *Previous, Decl *Canon) { assert(D && Previous); @@ -3691,6 +3746,8 @@ void ASTDeclReader::attachPreviousDecl(ASTReader &Reader, Decl *D, #include "clang/AST/DeclNodes.inc" } + checkMultipleDefinitionInNamedModules(Reader, D, Previous); + // If the declaration was visible in one module, a redeclaration of it in // another module remains visible even if it wouldn't be visible by itself. // @@ -3756,8 +3813,7 @@ void ASTReader::markIncompleteDeclChain(Decl *D) { } /// Read the declaration at the given offset from the AST file. -Decl *ASTReader::ReadDeclRecord(DeclID ID) { - unsigned Index = ID - NUM_PREDEF_DECL_IDS; +Decl *ASTReader::ReadDeclRecord(GlobalDeclID ID) { SourceLocation DeclLoc; RecordLocation Loc = DeclCursorForID(ID, DeclLoc); llvm::BitstreamCursor &DeclsCursor = Loc.F->DeclsCursor; @@ -3789,8 +3845,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { Expected<unsigned> MaybeDeclCode = Record.readRecord(DeclsCursor, Code); if (!MaybeDeclCode) llvm::report_fatal_error( - "ASTReader::readDeclRecord failed reading decl code: " + + Twine("ASTReader::readDeclRecord failed reading decl code: ") + toString(MaybeDeclCode.takeError())); + switch ((DeclCode)MaybeDeclCode.get()) { case DECL_CONTEXT_LEXICAL: case DECL_CONTEXT_VISIBLE: @@ -3837,6 +3894,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_USING_SHADOW: D = UsingShadowDecl::CreateDeserialized(Context, ID); break; + case DECL_USING_ENUM: + D = UsingEnumDecl::CreateDeserialized(Context, ID); + break; case DECL_CONSTRUCTOR_USING_SHADOW: D = ConstructorUsingShadowDecl::CreateDeserialized(Context, ID); break; @@ -3849,6 +3909,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_UNRESOLVED_USING_TYPENAME: D = UnresolvedUsingTypenameDecl::CreateDeserialized(Context, ID); break; + case DECL_UNRESOLVED_USING_IF_EXISTS: + D = UnresolvedUsingIfExistsDecl::CreateDeserialized(Context, ID); + break; case DECL_CXX_RECORD: D = CXXRecordDecl::CreateDeserialized(Context, ID); break; @@ -3894,9 +3957,6 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION: D = VarTemplatePartialSpecializationDecl::CreateDeserialized(Context, ID); break; - case DECL_CLASS_SCOPE_FUNCTION_SPECIALIZATION: - D = ClassScopeFunctionSpecializationDecl::CreateDeserialized(Context, ID); - break; case DECL_FUNCTION_TEMPLATE: D = FunctionTemplateDecl::CreateDeserialized(Context, ID); break; @@ -3914,9 +3974,8 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { } case DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK: { bool HasTypeConstraint = Record.readInt(); - D = NonTypeTemplateParmDecl::CreateDeserialized(Context, ID, - Record.readInt(), - HasTypeConstraint); + D = NonTypeTemplateParmDecl::CreateDeserialized( + Context, ID, Record.readInt(), HasTypeConstraint); break; } case DECL_TEMPLATE_TEMPLATE_PARM: @@ -3995,6 +4054,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_FILE_SCOPE_ASM: D = FileScopeAsmDecl::CreateDeserialized(Context, ID); break; + case DECL_TOP_LEVEL_STMT_DECL: + D = TopLevelStmtDecl::CreateDeserialized(Context, ID); + break; case DECL_BLOCK: D = BlockDecl::CreateDeserialized(Context, ID); break; @@ -4004,6 +4066,9 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_MS_GUID: D = MSGuidDecl::CreateDeserialized(Context, ID); break; + case DECL_UNNAMED_GLOBAL_CONSTANT: + D = UnnamedGlobalConstantDecl::CreateDeserialized(Context, ID); + break; case DECL_TEMPLATE_PARAM_OBJECT: D = TemplateParamObjectDecl::CreateDeserialized(Context, ID); break; @@ -4069,20 +4134,39 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { case DECL_OBJC_TYPE_PARAM: D = ObjCTypeParamDecl::CreateDeserialized(Context, ID); break; + case DECL_HLSL_BUFFER: + D = HLSLBufferDecl::CreateDeserialized(Context, ID); + break; + case DECL_IMPLICIT_CONCEPT_SPECIALIZATION: + D = ImplicitConceptSpecializationDecl::CreateDeserialized(Context, ID, + Record.readInt()); + break; } assert(D && "Unknown declaration reading AST file"); - LoadedDecl(Index, D); + LoadedDecl(translateGlobalDeclIDToIndex(ID), D); // Set the DeclContext before doing any deserialization, to make sure internal // calls to Decl::getASTContext() by Decl's methods will find the // TranslationUnitDecl without crashing. D->setDeclContext(Context.getTranslationUnitDecl()); - Reader.Visit(D); + + // Reading some declarations can result in deep recursion. + clang::runWithSufficientStackSpace([&] { warnStackExhausted(DeclLoc); }, + [&] { Reader.Visit(D); }); // If this declaration is also a declaration context, get the // offsets for its tables of lexical and visible declarations. if (auto *DC = dyn_cast<DeclContext>(D)) { std::pair<uint64_t, uint64_t> Offsets = Reader.VisitDeclContext(DC); + + // Get the lexical and visible block for the delayed namespace. + // It is sufficient to judge if ID is in DelayedNamespaceOffsetMap. + // But it may be more efficient to filter the other cases. + if (!Offsets.first && !Offsets.second && isa<NamespaceDecl>(D)) + if (auto Iter = DelayedNamespaceOffsetMap.find(ID); + Iter != DelayedNamespaceOffsetMap.end()) + Offsets = Iter->second; + if (Offsets.first && ReadLexicalDeclContextStorage(*Loc.F, DeclsCursor, Offsets.first, DC)) return nullptr; @@ -4108,8 +4192,7 @@ Decl *ASTReader::ReadDeclRecord(DeclID ID) { // AST consumer might need to know about, queue it. // We don't pass it to the consumer immediately because we may be in recursive // loading, and some declarations may still be initializing. - PotentiallyInterestingDecls.push_back( - InterestingDecl(D, Reader.hasPendingBody())); + PotentiallyInterestingDecls.push_back(D); return D; } @@ -4122,8 +4205,7 @@ void ASTReader::PassInterestingDeclsToConsumer() { // Guard variable to avoid recursively redoing the process of passing // decls to consumer. - SaveAndRestore<bool> GuardPassingDeclsToConsumer(PassingDeclsToConsumer, - true); + SaveAndRestore GuardPassingDeclsToConsumer(PassingDeclsToConsumer, true); // Ensure that we've loaded all potentially-interesting declarations // that need to be eagerly loaded. @@ -4131,24 +4213,55 @@ void ASTReader::PassInterestingDeclsToConsumer() { GetDecl(ID); EagerlyDeserializedDecls.clear(); - while (!PotentiallyInterestingDecls.empty()) { - InterestingDecl D = PotentiallyInterestingDecls.front(); - PotentiallyInterestingDecls.pop_front(); - if (isConsumerInterestedIn(getContext(), D.getDecl(), D.hasPendingBody())) - PassInterestingDeclToConsumer(D.getDecl()); - } + auto ConsumingPotentialInterestingDecls = [this]() { + while (!PotentiallyInterestingDecls.empty()) { + Decl *D = PotentiallyInterestingDecls.front(); + PotentiallyInterestingDecls.pop_front(); + if (isConsumerInterestedIn(D)) + PassInterestingDeclToConsumer(D); + } + }; + std::deque<Decl *> MaybeInterestingDecls = + std::move(PotentiallyInterestingDecls); + PotentiallyInterestingDecls.clear(); + assert(PotentiallyInterestingDecls.empty()); + while (!MaybeInterestingDecls.empty()) { + Decl *D = MaybeInterestingDecls.front(); + MaybeInterestingDecls.pop_front(); + // Since we load the variable's initializers lazily, it'd be problematic + // if the initializers dependent on each other. So here we try to load the + // initializers of static variables to make sure they are passed to code + // generator by order. If we read anything interesting, we would consume + // that before emitting the current declaration. + if (auto *VD = dyn_cast<VarDecl>(D); + VD && VD->isFileVarDecl() && !VD->isExternallyVisible()) + VD->getInit(); + ConsumingPotentialInterestingDecls(); + if (isConsumerInterestedIn(D)) + PassInterestingDeclToConsumer(D); + } + + // If we add any new potential interesting decl in the last call, consume it. + ConsumingPotentialInterestingDecls(); + + for (GlobalDeclID ID : VTablesToEmit) { + auto *RD = cast<CXXRecordDecl>(GetDecl(ID)); + assert(!RD->shouldEmitInExternalSource()); + PassVTableToConsumer(RD); + } + VTablesToEmit.clear(); } void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { // The declaration may have been modified by files later in the chain. // If this is the case, read the record containing the updates from each file // and pass it to ASTDeclReader to make the modifications. - serialization::GlobalDeclID ID = Record.ID; + GlobalDeclID ID = Record.ID; Decl *D = Record.D; ProcessingUpdatesRAIIObj ProcessingUpdates(*this); DeclUpdateOffsetsMap::iterator UpdI = DeclUpdateOffsets.find(ID); - SmallVector<serialization::DeclID, 8> PendingLazySpecializationIDs; + SmallVector<GlobalDeclID, 8> PendingLazySpecializationIDs; if (UpdI != DeclUpdateOffsets.end()) { auto UpdateOffsets = std::move(UpdI->second); @@ -4158,8 +4271,7 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { // the declaration, then we know it was interesting and we skip the call // to isConsumerInterestedIn because it is unsafe to call in the // current ASTReader state. - bool WasInteresting = - Record.JustLoaded || isConsumerInterestedIn(getContext(), D, false); + bool WasInteresting = Record.JustLoaded || isConsumerInterestedIn(D); for (auto &FileAndOffset : UpdateOffsets) { ModuleFile *F = FileAndOffset.first; uint64_t Offset = FileAndOffset.second; @@ -4168,12 +4280,12 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { if (llvm::Error JumpFailed = Cursor.JumpToBit(Offset)) // FIXME don't do a fatal error. llvm::report_fatal_error( - "ASTReader::loadDeclUpdateRecords failed jumping: " + + Twine("ASTReader::loadDeclUpdateRecords failed jumping: ") + toString(std::move(JumpFailed))); Expected<unsigned> MaybeCode = Cursor.ReadCode(); if (!MaybeCode) llvm::report_fatal_error( - "ASTReader::loadDeclUpdateRecords failed reading code: " + + Twine("ASTReader::loadDeclUpdateRecords failed reading code: ") + toString(MaybeCode.takeError())); unsigned Code = MaybeCode.get(); ASTRecordReader Record(*this, *F); @@ -4182,7 +4294,7 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { "Expected DECL_UPDATES record!"); else llvm::report_fatal_error( - "ASTReader::loadDeclUpdateRecords failed reading rec code: " + + Twine("ASTReader::loadDeclUpdateRecords failed reading rec code: ") + toString(MaybeCode.takeError())); ASTDeclReader Reader(*this, Record, RecordLocation(F, Offset), ID, @@ -4191,17 +4303,15 @@ void ASTReader::loadDeclUpdateRecords(PendingUpdateRecord &Record) { // We might have made this declaration interesting. If so, remember that // we need to hand it off to the consumer. - if (!WasInteresting && - isConsumerInterestedIn(getContext(), D, Reader.hasPendingBody())) { - PotentiallyInterestingDecls.push_back( - InterestingDecl(D, Reader.hasPendingBody())); + if (!WasInteresting && isConsumerInterestedIn(D)) { + PotentiallyInterestingDecls.push_back(D); WasInteresting = true; } } } // Add the lazy specializations to the template. assert((PendingLazySpecializationIDs.empty() || isa<ClassTemplateDecl>(D) || - isa<FunctionTemplateDecl>(D) || isa<VarTemplateDecl>(D)) && + isa<FunctionTemplateDecl, VarTemplateDecl>(D)) && "Must not have pending specializations"); if (auto *CTD = dyn_cast<ClassTemplateDecl>(D)) ASTDeclReader::AddLazySpecializations(CTD, PendingLazySpecializationIDs); @@ -4249,14 +4359,14 @@ void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) { SavedStreamPosition SavedPosition(Cursor); if (llvm::Error JumpFailed = Cursor.JumpToBit(LocalOffset)) llvm::report_fatal_error( - "ASTReader::loadPendingDeclChain failed jumping: " + + Twine("ASTReader::loadPendingDeclChain failed jumping: ") + toString(std::move(JumpFailed))); RecordData Record; Expected<unsigned> MaybeCode = Cursor.ReadCode(); if (!MaybeCode) llvm::report_fatal_error( - "ASTReader::loadPendingDeclChain failed reading code: " + + Twine("ASTReader::loadPendingDeclChain failed reading code: ") + toString(MaybeCode.takeError())); unsigned Code = MaybeCode.get(); if (Expected<unsigned> MaybeRecCode = Cursor.readRecord(Code, Record)) @@ -4264,14 +4374,15 @@ void ASTReader::loadPendingDeclChain(Decl *FirstLocal, uint64_t LocalOffset) { "expected LOCAL_REDECLARATIONS record!"); else llvm::report_fatal_error( - "ASTReader::loadPendingDeclChain failed reading rec code: " + + Twine("ASTReader::loadPendingDeclChain failed reading rec code: ") + toString(MaybeCode.takeError())); // FIXME: We have several different dispatches on decl kind here; maybe // we should instead generate one loop per kind and dispatch up-front? Decl *MostRecent = FirstLocal; for (unsigned I = 0, N = Record.size(); I != N; ++I) { - auto *D = GetLocalDecl(*M, Record[N - I - 1]); + unsigned Idx = N - I - 1; + auto *D = ReadDecl(*M, Record, Idx); ASTDeclReader::attachPreviousDecl(*this, D, MostRecent, CanonDecl); MostRecent = D; } @@ -4288,7 +4399,7 @@ namespace { llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized; ObjCCategoryDecl *Tail = nullptr; llvm::DenseMap<DeclarationName, ObjCCategoryDecl *> NameCategoryMap; - serialization::GlobalDeclID InterfaceID; + GlobalDeclID InterfaceID; unsigned PreviousGeneration; void add(ObjCCategoryDecl *Cat) { @@ -4299,23 +4410,22 @@ namespace { // Check for duplicate categories. if (Cat->getDeclName()) { ObjCCategoryDecl *&Existing = NameCategoryMap[Cat->getDeclName()]; - if (Existing && - Reader.getOwningModuleFile(Existing) - != Reader.getOwningModuleFile(Cat)) { - // FIXME: We should not warn for duplicates in diamond: - // - // MT // - // / \ // - // ML MR // - // \ / // - // MB // - // - // If there are duplicates in ML/MR, there will be warning when - // creating MB *and* when importing MB. We should not warn when - // importing. - Reader.Diag(Cat->getLocation(), diag::warn_dup_category_def) - << Interface->getDeclName() << Cat->getDeclName(); - Reader.Diag(Existing->getLocation(), diag::note_previous_definition); + if (Existing && Reader.getOwningModuleFile(Existing) != + Reader.getOwningModuleFile(Cat)) { + llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls; + StructuralEquivalenceContext Ctx( + Cat->getASTContext(), Existing->getASTContext(), + NonEquivalentDecls, StructuralEquivalenceKind::Default, + /*StrictTypeSpelling =*/false, + /*Complain =*/false, + /*ErrorOnTagTypeMismatch =*/true); + if (!Ctx.IsEquivalent(Cat, Existing)) { + // Warn only if the categories with the same name are different. + Reader.Diag(Cat->getLocation(), diag::warn_dup_category_def) + << Interface->getDeclName() << Cat->getDeclName(); + Reader.Diag(Existing->getLocation(), + diag::note_previous_definition); + } } else if (!Existing) { // Record this category. Existing = Cat; @@ -4331,11 +4441,10 @@ namespace { } public: - ObjCCategoriesVisitor(ASTReader &Reader, - ObjCInterfaceDecl *Interface, - llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized, - serialization::GlobalDeclID InterfaceID, - unsigned PreviousGeneration) + ObjCCategoriesVisitor( + ASTReader &Reader, ObjCInterfaceDecl *Interface, + llvm::SmallPtrSetImpl<ObjCCategoryDecl *> &Deserialized, + GlobalDeclID InterfaceID, unsigned PreviousGeneration) : Reader(Reader), Interface(Interface), Deserialized(Deserialized), InterfaceID(InterfaceID), PreviousGeneration(PreviousGeneration) { // Populate the name -> category map with the set of known categories. @@ -4357,8 +4466,9 @@ namespace { // Map global ID of the definition down to the local ID used in this // module file. If there is no such mapping, we'll find nothing here // (or in any module it imports). - DeclID LocalID = Reader.mapGlobalIDToModuleFileGlobalID(M, InterfaceID); - if (!LocalID) + LocalDeclID LocalID = + Reader.mapGlobalIDToModuleFileGlobalID(M, InterfaceID); + if (LocalID.isInvalid()) return true; // Perform a binary search to find the local redeclarations for this @@ -4369,7 +4479,7 @@ namespace { M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap, Compare); if (Result == M.ObjCCategoriesMap + M.LocalNumObjCCategoriesInMap || - Result->DefinitionID != LocalID) { + LocalID != Result->getDefinitionID()) { // We didn't find anything. If the class definition is in this module // file, then the module files it depends on cannot have any categories, // so suppress further lookup. @@ -4381,16 +4491,14 @@ namespace { unsigned N = M.ObjCCategories[Offset]; M.ObjCCategories[Offset++] = 0; // Don't try to deserialize again for (unsigned I = 0; I != N; ++I) - add(cast_or_null<ObjCCategoryDecl>( - Reader.GetLocalDecl(M, M.ObjCCategories[Offset++]))); + add(Reader.ReadDeclAs<ObjCCategoryDecl>(M, M.ObjCCategories, Offset)); return true; } }; } // namespace -void ASTReader::loadObjCCategories(serialization::GlobalDeclID ID, - ObjCInterfaceDecl *D, +void ASTReader::loadObjCCategories(GlobalDeclID ID, ObjCInterfaceDecl *D, unsigned PreviousGeneration) { ObjCCategoriesVisitor Visitor(*this, D, CategoriesDeserialized, ID, PreviousGeneration); @@ -4418,19 +4526,16 @@ static void forAllLaterRedecls(DeclT *D, Fn F) { } } -void ASTDeclReader::UpdateDecl(Decl *D, - llvm::SmallVectorImpl<serialization::DeclID> &PendingLazySpecializationIDs) { +void ASTDeclReader::UpdateDecl( + Decl *D, + llvm::SmallVectorImpl<GlobalDeclID> &PendingLazySpecializationIDs) { while (Record.getIdx() < Record.size()) { switch ((DeclUpdateKind)Record.readInt()) { case UPD_CXX_ADDED_IMPLICIT_MEMBER: { auto *RD = cast<CXXRecordDecl>(D); - // FIXME: If we also have an update record for instantiating the - // definition of D, we need that to happen before we get here. Decl *MD = Record.readDecl(); assert(MD && "couldn't read decl from update record"); - // FIXME: We should call addHiddenDecl instead, to add the member - // to its DeclContext. - RD->addedMember(MD); + Reader.PendingAddedClassMembers.push_back({RD, MD}); break; } @@ -4458,15 +4563,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, auto *VD = cast<VarDecl>(D); VD->NonParmVarDeclBits.IsInline = Record.readInt(); VD->NonParmVarDeclBits.IsInlineSpecified = Record.readInt(); - uint64_t Val = Record.readInt(); - if (Val && !VD->getInit()) { - VD->setInit(Record.readExpr()); - if (Val != 1) { - EvaluatedStmt *Eval = VD->ensureEvaluatedStmt(); - Eval->HasConstantInitialization = (Val & 2) != 0; - Eval->HasConstantDestruction = (Val & 4) != 0; - } - } + ReadVarDeclInit(VD); break; } @@ -4475,7 +4572,9 @@ void ASTDeclReader::UpdateDecl(Decl *D, if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(D)) { VTSD->setPointOfInstantiation(POI); } else if (auto *VD = dyn_cast<VarDecl>(D)) { - VD->getMemberSpecializationInfo()->setPointOfInstantiation(POI); + MemberSpecializationInfo *MSInfo = VD->getMemberSpecializationInfo(); + assert(MSInfo && "No member specialization information"); + MSInfo->setPointOfInstantiation(POI); } else { auto *FD = cast<FunctionDecl>(D); if (auto *FTSInfo = FD->TemplateOrSpecialization @@ -4509,7 +4608,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, // Only apply the update if the field still has an uninstantiated // default member initializer. - if (FD->hasInClassInitializer() && !FD->getInClassInitializer()) { + if (FD->hasInClassInitializer() && !FD->hasNonNullInClassInitializer()) { if (DefaultInit) FD->setInClassInitializer(DefaultInit); else @@ -4550,7 +4649,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, !Reader.PendingFakeDefinitionData.count(OldDD)); RD->setParamDestroyedInCallee(Record.readInt()); RD->setArgPassingRestrictions( - (RecordDecl::ArgPassingKind)Record.readInt()); + static_cast<RecordArgPassingKind>(Record.readInt())); ReadCXXRecordDefinition(RD, /*Update*/true); // Visible update is handled separately. @@ -4587,7 +4686,7 @@ void ASTDeclReader::UpdateDecl(Decl *D, } } - RD->setTagKind((TagTypeKind)Record.readInt()); + RD->setTagKind(static_cast<TagTypeKind>(Record.readInt())); RD->setLocation(readSourceLocation()); RD->setLocStart(readSourceLocation()); RD->setBraceRange(readSourceRange()); @@ -4663,19 +4762,18 @@ void ASTDeclReader::UpdateDecl(Decl *D, break; case UPD_DECL_MARKED_OPENMP_THREADPRIVATE: - D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit( - Reader.getContext(), readSourceRange(), - AttributeCommonInfo::AS_Pragma)); + D->addAttr(OMPThreadPrivateDeclAttr::CreateImplicit(Reader.getContext(), + readSourceRange())); break; case UPD_DECL_MARKED_OPENMP_ALLOCATE: { auto AllocatorKind = static_cast<OMPAllocateDeclAttr::AllocatorTypeTy>(Record.readInt()); Expr *Allocator = Record.readExpr(); + Expr *Alignment = Record.readExpr(); SourceRange SR = readSourceRange(); D->addAttr(OMPAllocateDeclAttr::CreateImplicit( - Reader.getContext(), AllocatorKind, Allocator, SR, - AttributeCommonInfo::AS_Pragma)); + Reader.getContext(), AllocatorKind, Allocator, Alignment, SR)); break; } @@ -4691,10 +4789,12 @@ void ASTDeclReader::UpdateDecl(Decl *D, case UPD_DECL_MARKED_OPENMP_DECLARETARGET: { auto MapType = Record.readEnum<OMPDeclareTargetDeclAttr::MapTypeTy>(); auto DevType = Record.readEnum<OMPDeclareTargetDeclAttr::DevTypeTy>(); + Expr *IndirectE = Record.readExpr(); + bool Indirect = Record.readBool(); unsigned Level = Record.readInt(); D->addAttr(OMPDeclareTargetDeclAttr::CreateImplicit( - Reader.getContext(), MapType, DevType, Level, readSourceRange(), - AttributeCommonInfo::AS_Pragma)); + Reader.getContext(), MapType, DevType, IndirectE, Indirect, Level, + readSourceRange())); break; } |