|  | //===--- ASTWriterDecl.cpp - Declaration Serialization --------------------===// | 
|  | // | 
|  | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | 
|  | // See https://llvm.org/LICENSE.txt for license information. | 
|  | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | //  This file implements serialization for Declarations. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "ASTCommon.h" | 
|  | #include "clang/AST/Attr.h" | 
|  | #include "clang/AST/DeclCXX.h" | 
|  | #include "clang/AST/DeclTemplate.h" | 
|  | #include "clang/AST/DeclVisitor.h" | 
|  | #include "clang/AST/Expr.h" | 
|  | #include "clang/AST/OpenMPClause.h" | 
|  | #include "clang/AST/PrettyDeclStackTrace.h" | 
|  | #include "clang/Basic/SourceManager.h" | 
|  | #include "clang/Serialization/ASTReader.h" | 
|  | #include "clang/Serialization/ASTRecordWriter.h" | 
|  | #include "llvm/Bitstream/BitstreamWriter.h" | 
|  | #include "llvm/Support/ErrorHandling.h" | 
|  | using namespace clang; | 
|  | using namespace serialization; | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // Utility functions | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | namespace { | 
|  |  | 
|  | // Helper function that returns true if the decl passed in the argument is | 
|  | // a defintion in dependent contxt. | 
|  | template <typename DT> bool isDefinitionInDependentContext(DT *D) { | 
|  | return D->isDependentContext() && D->isThisDeclarationADefinition(); | 
|  | } | 
|  |  | 
|  | } // namespace | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // Declaration serialization | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | namespace clang { | 
|  | class ASTDeclWriter : public DeclVisitor<ASTDeclWriter, void> { | 
|  | ASTWriter &Writer; | 
|  | ASTRecordWriter Record; | 
|  |  | 
|  | serialization::DeclCode Code; | 
|  | unsigned AbbrevToUse; | 
|  |  | 
|  | bool GeneratingReducedBMI = false; | 
|  |  | 
|  | public: | 
|  | ASTDeclWriter(ASTWriter &Writer, ASTContext &Context, | 
|  | ASTWriter::RecordDataImpl &Record, bool GeneratingReducedBMI) | 
|  | : Writer(Writer), Record(Context, Writer, Record), | 
|  | Code((serialization::DeclCode)0), AbbrevToUse(0), | 
|  | GeneratingReducedBMI(GeneratingReducedBMI) {} | 
|  |  | 
|  | uint64_t Emit(Decl *D) { | 
|  | if (!Code) | 
|  | llvm::report_fatal_error(StringRef("unexpected declaration kind '") + | 
|  | D->getDeclKindName() + "'"); | 
|  | return Record.Emit(Code, AbbrevToUse); | 
|  | } | 
|  |  | 
|  | void Visit(Decl *D); | 
|  |  | 
|  | void VisitDecl(Decl *D); | 
|  | void VisitPragmaCommentDecl(PragmaCommentDecl *D); | 
|  | void VisitPragmaDetectMismatchDecl(PragmaDetectMismatchDecl *D); | 
|  | void VisitTranslationUnitDecl(TranslationUnitDecl *D); | 
|  | void VisitNamedDecl(NamedDecl *D); | 
|  | void VisitLabelDecl(LabelDecl *LD); | 
|  | void VisitNamespaceDecl(NamespaceDecl *D); | 
|  | void VisitUsingDirectiveDecl(UsingDirectiveDecl *D); | 
|  | void VisitNamespaceAliasDecl(NamespaceAliasDecl *D); | 
|  | void VisitTypeDecl(TypeDecl *D); | 
|  | void VisitTypedefNameDecl(TypedefNameDecl *D); | 
|  | void VisitTypedefDecl(TypedefDecl *D); | 
|  | void VisitTypeAliasDecl(TypeAliasDecl *D); | 
|  | void VisitUnresolvedUsingTypenameDecl(UnresolvedUsingTypenameDecl *D); | 
|  | void VisitUnresolvedUsingIfExistsDecl(UnresolvedUsingIfExistsDecl *D); | 
|  | void VisitTagDecl(TagDecl *D); | 
|  | void VisitEnumDecl(EnumDecl *D); | 
|  | void VisitRecordDecl(RecordDecl *D); | 
|  | void VisitCXXRecordDecl(CXXRecordDecl *D); | 
|  | void VisitClassTemplateSpecializationDecl( | 
|  | ClassTemplateSpecializationDecl *D); | 
|  | void VisitClassTemplatePartialSpecializationDecl( | 
|  | ClassTemplatePartialSpecializationDecl *D); | 
|  | void VisitVarTemplateSpecializationDecl(VarTemplateSpecializationDecl *D); | 
|  | void VisitVarTemplatePartialSpecializationDecl( | 
|  | VarTemplatePartialSpecializationDecl *D); | 
|  | void VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D); | 
|  | void VisitValueDecl(ValueDecl *D); | 
|  | void VisitEnumConstantDecl(EnumConstantDecl *D); | 
|  | void VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D); | 
|  | void VisitDeclaratorDecl(DeclaratorDecl *D); | 
|  | void VisitFunctionDecl(FunctionDecl *D); | 
|  | void VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D); | 
|  | void VisitCXXMethodDecl(CXXMethodDecl *D); | 
|  | void VisitCXXConstructorDecl(CXXConstructorDecl *D); | 
|  | void VisitCXXDestructorDecl(CXXDestructorDecl *D); | 
|  | void VisitCXXConversionDecl(CXXConversionDecl *D); | 
|  | void VisitFieldDecl(FieldDecl *D); | 
|  | void VisitMSPropertyDecl(MSPropertyDecl *D); | 
|  | void VisitMSGuidDecl(MSGuidDecl *D); | 
|  | void VisitUnnamedGlobalConstantDecl(UnnamedGlobalConstantDecl *D); | 
|  | void VisitTemplateParamObjectDecl(TemplateParamObjectDecl *D); | 
|  | void VisitIndirectFieldDecl(IndirectFieldDecl *D); | 
|  | void VisitVarDecl(VarDecl *D); | 
|  | void VisitImplicitParamDecl(ImplicitParamDecl *D); | 
|  | void VisitParmVarDecl(ParmVarDecl *D); | 
|  | void VisitDecompositionDecl(DecompositionDecl *D); | 
|  | void VisitBindingDecl(BindingDecl *D); | 
|  | void VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D); | 
|  | void VisitTemplateDecl(TemplateDecl *D); | 
|  | void VisitConceptDecl(ConceptDecl *D); | 
|  | void VisitImplicitConceptSpecializationDecl( | 
|  | ImplicitConceptSpecializationDecl *D); | 
|  | void VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D); | 
|  | void VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D); | 
|  | void VisitClassTemplateDecl(ClassTemplateDecl *D); | 
|  | void VisitVarTemplateDecl(VarTemplateDecl *D); | 
|  | void VisitFunctionTemplateDecl(FunctionTemplateDecl *D); | 
|  | 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 *D); | 
|  | void VisitTopLevelStmtDecl(TopLevelStmtDecl *D); | 
|  | void VisitImportDecl(ImportDecl *D); | 
|  | void VisitAccessSpecDecl(AccessSpecDecl *D); | 
|  | void VisitFriendDecl(FriendDecl *D); | 
|  | void VisitFriendTemplateDecl(FriendTemplateDecl *D); | 
|  | void VisitStaticAssertDecl(StaticAssertDecl *D); | 
|  | void VisitBlockDecl(BlockDecl *D); | 
|  | void VisitOutlinedFunctionDecl(OutlinedFunctionDecl *D); | 
|  | void VisitCapturedDecl(CapturedDecl *D); | 
|  | void VisitEmptyDecl(EmptyDecl *D); | 
|  | void VisitLifetimeExtendedTemporaryDecl(LifetimeExtendedTemporaryDecl *D); | 
|  | void VisitDeclContext(DeclContext *DC); | 
|  | template <typename T> void VisitRedeclarable(Redeclarable<T> *D); | 
|  | void VisitHLSLBufferDecl(HLSLBufferDecl *D); | 
|  |  | 
|  | // FIXME: Put in the same order is DeclNodes.td? | 
|  | void VisitObjCMethodDecl(ObjCMethodDecl *D); | 
|  | void VisitObjCTypeParamDecl(ObjCTypeParamDecl *D); | 
|  | void VisitObjCContainerDecl(ObjCContainerDecl *D); | 
|  | void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D); | 
|  | void VisitObjCIvarDecl(ObjCIvarDecl *D); | 
|  | void VisitObjCProtocolDecl(ObjCProtocolDecl *D); | 
|  | void VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D); | 
|  | void VisitObjCCategoryDecl(ObjCCategoryDecl *D); | 
|  | void VisitObjCImplDecl(ObjCImplDecl *D); | 
|  | void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D); | 
|  | void VisitObjCImplementationDecl(ObjCImplementationDecl *D); | 
|  | void VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D); | 
|  | void VisitObjCPropertyDecl(ObjCPropertyDecl *D); | 
|  | void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D); | 
|  | void VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D); | 
|  | void VisitOMPAllocateDecl(OMPAllocateDecl *D); | 
|  | void VisitOMPRequiresDecl(OMPRequiresDecl *D); | 
|  | void VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D); | 
|  | void VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D); | 
|  | void VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D); | 
|  |  | 
|  | void VisitOpenACCDeclareDecl(OpenACCDeclareDecl *D); | 
|  | void VisitOpenACCRoutineDecl(OpenACCRoutineDecl *D); | 
|  |  | 
|  | /// Add an Objective-C type parameter list to the given record. | 
|  | void AddObjCTypeParamList(ObjCTypeParamList *typeParams) { | 
|  | // Empty type parameter list. | 
|  | if (!typeParams) { | 
|  | Record.push_back(0); | 
|  | return; | 
|  | } | 
|  |  | 
|  | Record.push_back(typeParams->size()); | 
|  | for (auto *typeParam : *typeParams) { | 
|  | Record.AddDeclRef(typeParam); | 
|  | } | 
|  | Record.AddSourceLocation(typeParams->getLAngleLoc()); | 
|  | Record.AddSourceLocation(typeParams->getRAngleLoc()); | 
|  | } | 
|  |  | 
|  | /// Collect the first declaration from each module file that provides a | 
|  | /// declaration of D. | 
|  | void CollectFirstDeclFromEachModule( | 
|  | const Decl *D, bool IncludeLocal, | 
|  | llvm::MapVector<ModuleFile *, const Decl *> &Firsts) { | 
|  |  | 
|  | // FIXME: We can skip entries that we know are implied by others. | 
|  | for (const Decl *R = D->getMostRecentDecl(); R; R = R->getPreviousDecl()) { | 
|  | if (R->isFromASTFile()) | 
|  | Firsts[Writer.Chain->getOwningModuleFile(R)] = R; | 
|  | else if (IncludeLocal) | 
|  | Firsts[nullptr] = R; | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Add to the record the first declaration from each module file that | 
|  | /// provides a declaration of D. The intent is to provide a sufficient | 
|  | /// set such that reloading this set will load all current redeclarations. | 
|  | void AddFirstDeclFromEachModule(const Decl *D, bool IncludeLocal) { | 
|  | llvm::MapVector<ModuleFile *, const Decl *> Firsts; | 
|  | CollectFirstDeclFromEachModule(D, IncludeLocal, Firsts); | 
|  |  | 
|  | for (const auto &F : Firsts) | 
|  | Record.AddDeclRef(F.second); | 
|  | } | 
|  |  | 
|  | template <typename T> bool shouldSkipWritingSpecializations(T *Spec) { | 
|  | // Now we will only avoid writing specializations if we're generating | 
|  | // reduced BMI. | 
|  | if (!GeneratingReducedBMI) | 
|  | return false; | 
|  |  | 
|  | assert((isa<FunctionDecl, ClassTemplateSpecializationDecl, | 
|  | VarTemplateSpecializationDecl>(Spec))); | 
|  |  | 
|  | ArrayRef<TemplateArgument> Args; | 
|  | if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(Spec)) | 
|  | Args = CTSD->getTemplateArgs().asArray(); | 
|  | else if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(Spec)) | 
|  | Args = VTSD->getTemplateArgs().asArray(); | 
|  | else | 
|  | Args = cast<FunctionDecl>(Spec) | 
|  | ->getTemplateSpecializationArgs() | 
|  | ->asArray(); | 
|  |  | 
|  | // If there is any template argument is TULocal, we can avoid writing the | 
|  | // specialization since the consumers of reduced BMI won't get the | 
|  | // specialization anyway. | 
|  | for (const TemplateArgument &TA : Args) { | 
|  | switch (TA.getKind()) { | 
|  | case TemplateArgument::Type: { | 
|  | Linkage L = TA.getAsType()->getLinkage(); | 
|  | if (!isExternallyVisible(L)) | 
|  | return true; | 
|  | break; | 
|  | } | 
|  | case TemplateArgument::Declaration: | 
|  | if (!TA.getAsDecl()->isExternallyVisible()) | 
|  | return true; | 
|  | break; | 
|  | default: | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | /// Add to the record the first template specialization from each module | 
|  | /// file that provides a declaration of D. We store the DeclId and an | 
|  | /// ODRHash of the template arguments of D which should provide enough | 
|  | /// information to load D only if the template instantiator needs it. | 
|  | void AddFirstSpecializationDeclFromEachModule( | 
|  | const Decl *D, llvm::SmallVectorImpl<const Decl *> &SpecsInMap, | 
|  | llvm::SmallVectorImpl<const Decl *> &PartialSpecsInMap) { | 
|  | assert((isa<ClassTemplateSpecializationDecl>(D) || | 
|  | isa<VarTemplateSpecializationDecl>(D) || isa<FunctionDecl>(D)) && | 
|  | "Must not be called with other decls"); | 
|  | llvm::MapVector<ModuleFile *, const Decl *> Firsts; | 
|  | CollectFirstDeclFromEachModule(D, /*IncludeLocal*/ true, Firsts); | 
|  |  | 
|  | for (const auto &F : Firsts) { | 
|  | if (shouldSkipWritingSpecializations(F.second)) | 
|  | continue; | 
|  |  | 
|  | if (isa<ClassTemplatePartialSpecializationDecl, | 
|  | VarTemplatePartialSpecializationDecl>(F.second)) | 
|  | PartialSpecsInMap.push_back(F.second); | 
|  | else | 
|  | SpecsInMap.push_back(F.second); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Get the specialization decl from an entry in the specialization list. | 
|  | template <typename EntryType> | 
|  | typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType * | 
|  | getSpecializationDecl(EntryType &T) { | 
|  | return RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::getDecl(&T); | 
|  | } | 
|  |  | 
|  | /// Get the list of partial specializations from a template's common ptr. | 
|  | template<typename T> | 
|  | decltype(T::PartialSpecializations) &getPartialSpecializations(T *Common) { | 
|  | return Common->PartialSpecializations; | 
|  | } | 
|  | MutableArrayRef<FunctionTemplateSpecializationInfo> | 
|  | getPartialSpecializations(FunctionTemplateDecl::Common *) { | 
|  | return {}; | 
|  | } | 
|  |  | 
|  | template<typename DeclTy> | 
|  | void AddTemplateSpecializations(DeclTy *D) { | 
|  | auto *Common = D->getCommonPtr(); | 
|  |  | 
|  | // If we have any lazy specializations, and the external AST source is | 
|  | // our chained AST reader, we can just write out the DeclIDs. Otherwise, | 
|  | // we need to resolve them to actual declarations. | 
|  | if (Writer.Chain != Record.getASTContext().getExternalSource() && | 
|  | Writer.Chain && Writer.Chain->haveUnloadedSpecializations(D)) { | 
|  | D->LoadLazySpecializations(); | 
|  | assert(!Writer.Chain->haveUnloadedSpecializations(D)); | 
|  | } | 
|  |  | 
|  | // AddFirstSpecializationDeclFromEachModule might trigger deserialization, | 
|  | // invalidating *Specializations iterators. | 
|  | llvm::SmallVector<const Decl *, 16> AllSpecs; | 
|  | for (auto &Entry : Common->Specializations) | 
|  | AllSpecs.push_back(getSpecializationDecl(Entry)); | 
|  | for (auto &Entry : getPartialSpecializations(Common)) | 
|  | AllSpecs.push_back(getSpecializationDecl(Entry)); | 
|  |  | 
|  | llvm::SmallVector<const Decl *, 16> Specs; | 
|  | llvm::SmallVector<const Decl *, 16> PartialSpecs; | 
|  | for (auto *D : AllSpecs) { | 
|  | assert(D->isCanonicalDecl() && "non-canonical decl in set"); | 
|  | AddFirstSpecializationDeclFromEachModule(D, Specs, PartialSpecs); | 
|  | } | 
|  |  | 
|  | Record.AddOffset(Writer.WriteSpecializationInfoLookupTable( | 
|  | D, Specs, /*IsPartial=*/false)); | 
|  |  | 
|  | // Function Template Decl doesn't have partial decls. | 
|  | if (isa<FunctionTemplateDecl>(D)) { | 
|  | assert(PartialSpecs.empty()); | 
|  | return; | 
|  | } | 
|  |  | 
|  | Record.AddOffset(Writer.WriteSpecializationInfoLookupTable( | 
|  | D, PartialSpecs, /*IsPartial=*/true)); | 
|  | } | 
|  |  | 
|  | /// Ensure that this template specialization is associated with the specified | 
|  | /// template on reload. | 
|  | void RegisterTemplateSpecialization(const Decl *Template, | 
|  | const Decl *Specialization) { | 
|  | Template = Template->getCanonicalDecl(); | 
|  |  | 
|  | // If the canonical template is local, we'll write out this specialization | 
|  | // when we emit it. | 
|  | // FIXME: We can do the same thing if there is any local declaration of | 
|  | // the template, to avoid emitting an update record. | 
|  | if (!Template->isFromASTFile()) | 
|  | return; | 
|  |  | 
|  | // We only need to associate the first local declaration of the | 
|  | // specialization. The other declarations will get pulled in by it. | 
|  | if (Writer.getFirstLocalDecl(Specialization) != Specialization) | 
|  | return; | 
|  |  | 
|  | if (isa<ClassTemplatePartialSpecializationDecl, | 
|  | VarTemplatePartialSpecializationDecl>(Specialization)) | 
|  | Writer.PartialSpecializationsUpdates[cast<NamedDecl>(Template)] | 
|  | .push_back(cast<NamedDecl>(Specialization)); | 
|  | else | 
|  | Writer.SpecializationsUpdates[cast<NamedDecl>(Template)].push_back( | 
|  | cast<NamedDecl>(Specialization)); | 
|  | } | 
|  | }; | 
|  | } | 
|  |  | 
|  | // When building a C++20 module interface unit or a partition unit, a | 
|  | // strong definition in the module interface is provided by the | 
|  | // compilation of that unit, not by its users. (Inline variables are still | 
|  | // emitted in module users.) | 
|  | static bool shouldVarGenerateHereOnly(const VarDecl *VD) { | 
|  | if (VD->getStorageDuration() != SD_Static) | 
|  | return false; | 
|  |  | 
|  | if (VD->getDescribedVarTemplate()) | 
|  | return false; | 
|  |  | 
|  | Module *M = VD->getOwningModule(); | 
|  | if (!M) | 
|  | return false; | 
|  |  | 
|  | M = M->getTopLevelModule(); | 
|  | ASTContext &Ctx = VD->getASTContext(); | 
|  | if (!M->isInterfaceOrPartition() && | 
|  | (!VD->hasAttr<DLLExportAttr>() || | 
|  | !Ctx.getLangOpts().BuildingPCHWithObjectFile)) | 
|  | return false; | 
|  |  | 
|  | return Ctx.GetGVALinkageForVariable(VD) >= GVA_StrongExternal; | 
|  | } | 
|  |  | 
|  | static bool shouldFunctionGenerateHereOnly(const FunctionDecl *FD) { | 
|  | if (FD->isDependentContext()) | 
|  | return false; | 
|  |  | 
|  | ASTContext &Ctx = FD->getASTContext(); | 
|  | auto Linkage = Ctx.GetGVALinkageForFunction(FD); | 
|  | if (Ctx.getLangOpts().ModulesCodegen || | 
|  | (FD->hasAttr<DLLExportAttr>() && | 
|  | Ctx.getLangOpts().BuildingPCHWithObjectFile)) | 
|  | // Under -fmodules-codegen, codegen is performed for all non-internal, | 
|  | // non-always_inline functions, unless they are available elsewhere. | 
|  | if (!FD->hasAttr<AlwaysInlineAttr>() && Linkage != GVA_Internal && | 
|  | Linkage != GVA_AvailableExternally) | 
|  | return true; | 
|  |  | 
|  | Module *M = FD->getOwningModule(); | 
|  | if (!M) | 
|  | return false; | 
|  |  | 
|  | M = M->getTopLevelModule(); | 
|  | if (M->isInterfaceOrPartition()) | 
|  | if (Linkage >= GVA_StrongExternal) | 
|  | return true; | 
|  |  | 
|  | return false; | 
|  | } | 
|  |  | 
|  | bool clang::CanElideDeclDef(const Decl *D) { | 
|  | if (auto *FD = dyn_cast<FunctionDecl>(D)) { | 
|  | if (FD->isInlined() || FD->isConstexpr() || FD->isConsteval()) | 
|  | return false; | 
|  |  | 
|  | // If the function should be generated somewhere else, we shouldn't elide | 
|  | // it. | 
|  | if (!shouldFunctionGenerateHereOnly(FD)) | 
|  | return false; | 
|  | } | 
|  |  | 
|  | if (auto *VD = dyn_cast<VarDecl>(D)) { | 
|  | if (VD->getDeclContext()->isDependentContext()) | 
|  | return false; | 
|  |  | 
|  | // Constant initialized variable may not affect the ABI, but they | 
|  | // may be used in constant evaluation in the frontend, so we have | 
|  | // to remain them. | 
|  | if (VD->hasConstantInitialization() || VD->isConstexpr()) | 
|  | return false; | 
|  |  | 
|  | // If the variable should be generated somewhere else, we shouldn't elide | 
|  | // it. | 
|  | if (!shouldVarGenerateHereOnly(VD)) | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::Visit(Decl *D) { | 
|  | DeclVisitor<ASTDeclWriter>::Visit(D); | 
|  |  | 
|  | // Source locations require array (variable-length) abbreviations.  The | 
|  | // abbreviation infrastructure requires that arrays are encoded last, so | 
|  | // we handle it here in the case of those classes derived from DeclaratorDecl | 
|  | if (auto *DD = dyn_cast<DeclaratorDecl>(D)) { | 
|  | if (auto *TInfo = DD->getTypeSourceInfo()) | 
|  | Record.AddTypeLoc(TInfo->getTypeLoc()); | 
|  | } | 
|  |  | 
|  | // Handle FunctionDecl's body here and write it after all other Stmts/Exprs | 
|  | // have been written. We want it last because we will not read it back when | 
|  | // retrieving it from the AST, we'll just lazily set the offset. | 
|  | if (auto *FD = dyn_cast<FunctionDecl>(D)) { | 
|  | if (!GeneratingReducedBMI || !CanElideDeclDef(FD)) { | 
|  | Record.push_back(FD->doesThisDeclarationHaveABody()); | 
|  | if (FD->doesThisDeclarationHaveABody()) | 
|  | Record.AddFunctionDefinition(FD); | 
|  | } else | 
|  | Record.push_back(0); | 
|  | } | 
|  |  | 
|  | // Similar to FunctionDecls, handle VarDecl's initializer here and write it | 
|  | // after all other Stmts/Exprs. We will not read the initializer until after | 
|  | // we have finished recursive deserialization, because it can recursively | 
|  | // refer back to the variable. | 
|  | if (auto *VD = dyn_cast<VarDecl>(D)) { | 
|  | if (!GeneratingReducedBMI || !CanElideDeclDef(VD)) | 
|  | Record.AddVarDeclInit(VD); | 
|  | else | 
|  | Record.push_back(0); | 
|  | } | 
|  |  | 
|  | // And similarly for FieldDecls. We already serialized whether there is a | 
|  | // default member initializer. | 
|  | if (auto *FD = dyn_cast<FieldDecl>(D)) { | 
|  | if (FD->hasInClassInitializer()) { | 
|  | if (Expr *Init = FD->getInClassInitializer()) { | 
|  | Record.push_back(1); | 
|  | Record.AddStmt(Init); | 
|  | } else { | 
|  | Record.push_back(0); | 
|  | // Initializer has not been instantiated yet. | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // If this declaration is also a DeclContext, write blocks for the | 
|  | // declarations that lexically stored inside its context and those | 
|  | // declarations that are visible from its context. | 
|  | if (auto *DC = dyn_cast<DeclContext>(D)) | 
|  | VisitDeclContext(DC); | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitDecl(Decl *D) { | 
|  | BitsPacker DeclBits; | 
|  |  | 
|  | // The order matters here. It will be better to put the bit with higher | 
|  | // probability to be 0 in the end of the bits. | 
|  | // | 
|  | // Since we're using VBR6 format to store it. | 
|  | // It will be pretty effient if all the higher bits are 0. | 
|  | // For example, if we need to pack 8 bits into a value and the stored value | 
|  | // is 0xf0, the actual stored value will be 0b000111'110000, which takes 12 | 
|  | // bits actually. However, if we changed the order to be 0x0f, then we can | 
|  | // store it as 0b001111, which takes 6 bits only now. | 
|  | DeclBits.addBits((uint64_t)D->getModuleOwnershipKind(), /*BitWidth=*/3); | 
|  | DeclBits.addBit(D->isThisDeclarationReferenced()); | 
|  | DeclBits.addBit(D->isUsed(false)); | 
|  | DeclBits.addBits(D->getAccess(), /*BitWidth=*/2); | 
|  | DeclBits.addBit(D->isImplicit()); | 
|  | DeclBits.addBit(D->getDeclContext() != D->getLexicalDeclContext()); | 
|  | DeclBits.addBit(D->hasAttrs()); | 
|  | DeclBits.addBit(D->isTopLevelDeclInObjCContainer()); | 
|  | DeclBits.addBit(D->isInvalidDecl()); | 
|  | Record.push_back(DeclBits); | 
|  |  | 
|  | Record.AddDeclRef(cast_or_null<Decl>(D->getDeclContext())); | 
|  | if (D->getDeclContext() != D->getLexicalDeclContext()) | 
|  | Record.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext())); | 
|  |  | 
|  | if (D->hasAttrs()) | 
|  | Record.AddAttributes(D->getAttrs()); | 
|  |  | 
|  | Record.push_back(Writer.getSubmoduleID(D->getOwningModule())); | 
|  |  | 
|  | // If this declaration injected a name into a context different from its | 
|  | // lexical context, and that context is an imported namespace, we need to | 
|  | // update its visible declarations to include this name. | 
|  | // | 
|  | // This happens when we instantiate a class with a friend declaration or a | 
|  | // function with a local extern declaration, for instance. | 
|  | // | 
|  | // FIXME: Can we handle this in AddedVisibleDecl instead? | 
|  | if (D->isOutOfLine()) { | 
|  | auto *DC = D->getDeclContext(); | 
|  | while (auto *NS = dyn_cast<NamespaceDecl>(DC->getRedeclContext())) { | 
|  | if (!NS->isFromASTFile()) | 
|  | break; | 
|  | Writer.UpdatedDeclContexts.insert(NS->getPrimaryContext()); | 
|  | if (!NS->isInlineNamespace()) | 
|  | break; | 
|  | DC = NS->getParent(); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitPragmaCommentDecl(PragmaCommentDecl *D) { | 
|  | StringRef Arg = D->getArg(); | 
|  | Record.push_back(Arg.size()); | 
|  | VisitDecl(D); | 
|  | Record.AddSourceLocation(D->getBeginLoc()); | 
|  | Record.push_back(D->getCommentKind()); | 
|  | Record.AddString(Arg); | 
|  | Code = serialization::DECL_PRAGMA_COMMENT; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitPragmaDetectMismatchDecl( | 
|  | PragmaDetectMismatchDecl *D) { | 
|  | StringRef Name = D->getName(); | 
|  | StringRef Value = D->getValue(); | 
|  | Record.push_back(Name.size() + 1 + Value.size()); | 
|  | VisitDecl(D); | 
|  | Record.AddSourceLocation(D->getBeginLoc()); | 
|  | Record.AddString(Name); | 
|  | Record.AddString(Value); | 
|  | Code = serialization::DECL_PRAGMA_DETECT_MISMATCH; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitTranslationUnitDecl(TranslationUnitDecl *D) { | 
|  | llvm_unreachable("Translation units aren't directly serialized"); | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitNamedDecl(NamedDecl *D) { | 
|  | VisitDecl(D); | 
|  | Record.AddDeclarationName(D->getDeclName()); | 
|  | Record.push_back(needsAnonymousDeclarationNumber(D) | 
|  | ? Writer.getAnonymousDeclarationNumber(D) | 
|  | : 0); | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitTypeDecl(TypeDecl *D) { | 
|  | VisitNamedDecl(D); | 
|  | Record.AddSourceLocation(D->getBeginLoc()); | 
|  | if (!isa<TagDecl, TypedefDecl, TypeAliasDecl>(D)) | 
|  | Record.AddTypeRef(QualType(D->getTypeForDecl(), 0)); | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitTypedefNameDecl(TypedefNameDecl *D) { | 
|  | VisitRedeclarable(D); | 
|  | VisitTypeDecl(D); | 
|  | Record.AddTypeSourceInfo(D->getTypeSourceInfo()); | 
|  | Record.push_back(D->isModed()); | 
|  | if (D->isModed()) | 
|  | Record.AddTypeRef(D->getUnderlyingType()); | 
|  | Record.AddDeclRef(D->getAnonDeclWithTypedefName(false)); | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitTypedefDecl(TypedefDecl *D) { | 
|  | VisitTypedefNameDecl(D); | 
|  | if (D->getDeclContext() == D->getLexicalDeclContext() && | 
|  | !D->hasAttrs() && | 
|  | !D->isImplicit() && | 
|  | D->getFirstDecl() == D->getMostRecentDecl() && | 
|  | !D->isInvalidDecl() && | 
|  | !D->isTopLevelDeclInObjCContainer() && | 
|  | !D->isModulePrivate() && | 
|  | !needsAnonymousDeclarationNumber(D) && | 
|  | D->getDeclName().getNameKind() == DeclarationName::Identifier) | 
|  | AbbrevToUse = Writer.getDeclTypedefAbbrev(); | 
|  |  | 
|  | Code = serialization::DECL_TYPEDEF; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitTypeAliasDecl(TypeAliasDecl *D) { | 
|  | VisitTypedefNameDecl(D); | 
|  | Record.AddDeclRef(D->getDescribedAliasTemplate()); | 
|  | Code = serialization::DECL_TYPEALIAS; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitTagDecl(TagDecl *D) { | 
|  | static_assert(DeclContext::NumTagDeclBits == 23, | 
|  | "You need to update the serializer after you change the " | 
|  | "TagDeclBits"); | 
|  |  | 
|  | VisitRedeclarable(D); | 
|  | VisitTypeDecl(D); | 
|  | Record.push_back(D->getIdentifierNamespace()); | 
|  |  | 
|  | BitsPacker TagDeclBits; | 
|  | TagDeclBits.addBits(llvm::to_underlying(D->getTagKind()), /*BitWidth=*/3); | 
|  | TagDeclBits.addBit(!isa<CXXRecordDecl>(D) ? D->isCompleteDefinition() : 0); | 
|  | TagDeclBits.addBit(D->isEmbeddedInDeclarator()); | 
|  | TagDeclBits.addBit(D->isFreeStanding()); | 
|  | TagDeclBits.addBit(D->isCompleteDefinitionRequired()); | 
|  | TagDeclBits.addBits( | 
|  | D->hasExtInfo() ? 1 : (D->getTypedefNameForAnonDecl() ? 2 : 0), | 
|  | /*BitWidth=*/2); | 
|  | Record.push_back(TagDeclBits); | 
|  |  | 
|  | Record.AddSourceRange(D->getBraceRange()); | 
|  |  | 
|  | if (D->hasExtInfo()) { | 
|  | Record.AddQualifierInfo(*D->getExtInfo()); | 
|  | } else if (auto *TD = D->getTypedefNameForAnonDecl()) { | 
|  | Record.AddDeclRef(TD); | 
|  | Record.AddIdentifierRef(TD->getDeclName().getAsIdentifierInfo()); | 
|  | } | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { | 
|  | static_assert(DeclContext::NumEnumDeclBits == 43, | 
|  | "You need to update the serializer after you change the " | 
|  | "EnumDeclBits"); | 
|  |  | 
|  | VisitTagDecl(D); | 
|  | Record.AddTypeSourceInfo(D->getIntegerTypeSourceInfo()); | 
|  | if (!D->getIntegerTypeSourceInfo()) | 
|  | Record.AddTypeRef(D->getIntegerType()); | 
|  | Record.AddTypeRef(D->getPromotionType()); | 
|  |  | 
|  | BitsPacker EnumDeclBits; | 
|  | EnumDeclBits.addBits(D->getNumPositiveBits(), /*BitWidth=*/8); | 
|  | EnumDeclBits.addBits(D->getNumNegativeBits(), /*BitWidth=*/8); | 
|  | EnumDeclBits.addBit(D->isScoped()); | 
|  | EnumDeclBits.addBit(D->isScopedUsingClassTag()); | 
|  | EnumDeclBits.addBit(D->isFixed()); | 
|  | Record.push_back(EnumDeclBits); | 
|  |  | 
|  | Record.push_back(D->getODRHash()); | 
|  |  | 
|  | if (MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo()) { | 
|  | Record.AddDeclRef(MemberInfo->getInstantiatedFrom()); | 
|  | Record.push_back(MemberInfo->getTemplateSpecializationKind()); | 
|  | Record.AddSourceLocation(MemberInfo->getPointOfInstantiation()); | 
|  | } else { | 
|  | Record.AddDeclRef(nullptr); | 
|  | } | 
|  |  | 
|  | if (D->getDeclContext() == D->getLexicalDeclContext() && !D->hasAttrs() && | 
|  | !D->isInvalidDecl() && !D->isImplicit() && !D->hasExtInfo() && | 
|  | !D->getTypedefNameForAnonDecl() && | 
|  | D->getFirstDecl() == D->getMostRecentDecl() && | 
|  | !D->isTopLevelDeclInObjCContainer() && | 
|  | !CXXRecordDecl::classofKind(D->getKind()) && | 
|  | !D->getIntegerTypeSourceInfo() && !D->getMemberSpecializationInfo() && | 
|  | !needsAnonymousDeclarationNumber(D) && | 
|  | D->getDeclName().getNameKind() == DeclarationName::Identifier) | 
|  | AbbrevToUse = Writer.getDeclEnumAbbrev(); | 
|  |  | 
|  | Code = serialization::DECL_ENUM; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitRecordDecl(RecordDecl *D) { | 
|  | static_assert(DeclContext::NumRecordDeclBits == 64, | 
|  | "You need to update the serializer after you change the " | 
|  | "RecordDeclBits"); | 
|  |  | 
|  | VisitTagDecl(D); | 
|  |  | 
|  | BitsPacker RecordDeclBits; | 
|  | RecordDeclBits.addBit(D->hasFlexibleArrayMember()); | 
|  | RecordDeclBits.addBit(D->isAnonymousStructOrUnion()); | 
|  | RecordDeclBits.addBit(D->hasObjectMember()); | 
|  | RecordDeclBits.addBit(D->hasVolatileMember()); | 
|  | RecordDeclBits.addBit(D->isNonTrivialToPrimitiveDefaultInitialize()); | 
|  | RecordDeclBits.addBit(D->isNonTrivialToPrimitiveCopy()); | 
|  | RecordDeclBits.addBit(D->isNonTrivialToPrimitiveDestroy()); | 
|  | RecordDeclBits.addBit(D->hasNonTrivialToPrimitiveDefaultInitializeCUnion()); | 
|  | RecordDeclBits.addBit(D->hasNonTrivialToPrimitiveDestructCUnion()); | 
|  | RecordDeclBits.addBit(D->hasNonTrivialToPrimitiveCopyCUnion()); | 
|  | RecordDeclBits.addBit(D->hasUninitializedExplicitInitFields()); | 
|  | RecordDeclBits.addBit(D->isParamDestroyedInCallee()); | 
|  | RecordDeclBits.addBits(llvm::to_underlying(D->getArgPassingRestrictions()), 2); | 
|  | Record.push_back(RecordDeclBits); | 
|  |  | 
|  | // Only compute this for C/Objective-C, in C++ this is computed as part | 
|  | // of CXXRecordDecl. | 
|  | if (!isa<CXXRecordDecl>(D)) | 
|  | Record.push_back(D->getODRHash()); | 
|  |  | 
|  | if (D->getDeclContext() == D->getLexicalDeclContext() && !D->hasAttrs() && | 
|  | !D->isImplicit() && !D->isInvalidDecl() && !D->hasExtInfo() && | 
|  | !D->getTypedefNameForAnonDecl() && | 
|  | D->getFirstDecl() == D->getMostRecentDecl() && | 
|  | !D->isTopLevelDeclInObjCContainer() && | 
|  | !CXXRecordDecl::classofKind(D->getKind()) && | 
|  | !needsAnonymousDeclarationNumber(D) && | 
|  | D->getDeclName().getNameKind() == DeclarationName::Identifier) | 
|  | AbbrevToUse = Writer.getDeclRecordAbbrev(); | 
|  |  | 
|  | Code = serialization::DECL_RECORD; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitValueDecl(ValueDecl *D) { | 
|  | VisitNamedDecl(D); | 
|  | Record.AddTypeRef(D->getType()); | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitEnumConstantDecl(EnumConstantDecl *D) { | 
|  | VisitValueDecl(D); | 
|  | Record.push_back(D->getInitExpr()? 1 : 0); | 
|  | if (D->getInitExpr()) | 
|  | Record.AddStmt(D->getInitExpr()); | 
|  | Record.AddAPSInt(D->getInitVal()); | 
|  |  | 
|  | Code = serialization::DECL_ENUM_CONSTANT; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitDeclaratorDecl(DeclaratorDecl *D) { | 
|  | VisitValueDecl(D); | 
|  | Record.AddSourceLocation(D->getInnerLocStart()); | 
|  | Record.push_back(D->hasExtInfo()); | 
|  | if (D->hasExtInfo()) { | 
|  | DeclaratorDecl::ExtInfo *Info = D->getExtInfo(); | 
|  | Record.AddQualifierInfo(*Info); | 
|  | Record.AddStmt( | 
|  | const_cast<Expr *>(Info->TrailingRequiresClause.ConstraintExpr)); | 
|  | Record.writeUnsignedOrNone(Info->TrailingRequiresClause.ArgPackSubstIndex); | 
|  | } | 
|  | // The location information is deferred until the end of the record. | 
|  | Record.AddTypeRef(D->getTypeSourceInfo() ? D->getTypeSourceInfo()->getType() | 
|  | : QualType()); | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { | 
|  | static_assert(DeclContext::NumFunctionDeclBits == 45, | 
|  | "You need to update the serializer after you change the " | 
|  | "FunctionDeclBits"); | 
|  |  | 
|  | VisitRedeclarable(D); | 
|  |  | 
|  | Record.push_back(D->getTemplatedKind()); | 
|  | switch (D->getTemplatedKind()) { | 
|  | case FunctionDecl::TK_NonTemplate: | 
|  | break; | 
|  | case FunctionDecl::TK_DependentNonTemplate: | 
|  | Record.AddDeclRef(D->getInstantiatedFromDecl()); | 
|  | break; | 
|  | case FunctionDecl::TK_FunctionTemplate: | 
|  | Record.AddDeclRef(D->getDescribedFunctionTemplate()); | 
|  | break; | 
|  | case FunctionDecl::TK_MemberSpecialization: { | 
|  | MemberSpecializationInfo *MemberInfo = D->getMemberSpecializationInfo(); | 
|  | Record.AddDeclRef(MemberInfo->getInstantiatedFrom()); | 
|  | Record.push_back(MemberInfo->getTemplateSpecializationKind()); | 
|  | Record.AddSourceLocation(MemberInfo->getPointOfInstantiation()); | 
|  | break; | 
|  | } | 
|  | case FunctionDecl::TK_FunctionTemplateSpecialization: { | 
|  | FunctionTemplateSpecializationInfo * | 
|  | FTSInfo = D->getTemplateSpecializationInfo(); | 
|  |  | 
|  | RegisterTemplateSpecialization(FTSInfo->getTemplate(), D); | 
|  |  | 
|  | Record.AddDeclRef(FTSInfo->getTemplate()); | 
|  | Record.push_back(FTSInfo->getTemplateSpecializationKind()); | 
|  |  | 
|  | // Template arguments. | 
|  | Record.AddTemplateArgumentList(FTSInfo->TemplateArguments); | 
|  |  | 
|  | // Template args as written. | 
|  | Record.push_back(FTSInfo->TemplateArgumentsAsWritten != nullptr); | 
|  | if (FTSInfo->TemplateArgumentsAsWritten) | 
|  | Record.AddASTTemplateArgumentListInfo( | 
|  | FTSInfo->TemplateArgumentsAsWritten); | 
|  |  | 
|  | Record.AddSourceLocation(FTSInfo->getPointOfInstantiation()); | 
|  |  | 
|  | if (MemberSpecializationInfo *MemberInfo = | 
|  | FTSInfo->getMemberSpecializationInfo()) { | 
|  | Record.push_back(1); | 
|  | Record.AddDeclRef(MemberInfo->getInstantiatedFrom()); | 
|  | Record.push_back(MemberInfo->getTemplateSpecializationKind()); | 
|  | Record.AddSourceLocation(MemberInfo->getPointOfInstantiation()); | 
|  | } else { | 
|  | Record.push_back(0); | 
|  | } | 
|  |  | 
|  | if (D->isCanonicalDecl()) { | 
|  | // Write the template that contains the specializations set. We will | 
|  | // add a FunctionTemplateSpecializationInfo to it when reading. | 
|  | Record.AddDeclRef(FTSInfo->getTemplate()->getCanonicalDecl()); | 
|  | } | 
|  | break; | 
|  | } | 
|  | case FunctionDecl::TK_DependentFunctionTemplateSpecialization: { | 
|  | DependentFunctionTemplateSpecializationInfo * | 
|  | DFTSInfo = D->getDependentSpecializationInfo(); | 
|  |  | 
|  | // Candidates. | 
|  | Record.push_back(DFTSInfo->getCandidates().size()); | 
|  | for (FunctionTemplateDecl *FTD : DFTSInfo->getCandidates()) | 
|  | Record.AddDeclRef(FTD); | 
|  |  | 
|  | // Templates args. | 
|  | Record.push_back(DFTSInfo->TemplateArgumentsAsWritten != nullptr); | 
|  | if (DFTSInfo->TemplateArgumentsAsWritten) | 
|  | Record.AddASTTemplateArgumentListInfo( | 
|  | DFTSInfo->TemplateArgumentsAsWritten); | 
|  | break; | 
|  | } | 
|  | } | 
|  |  | 
|  | VisitDeclaratorDecl(D); | 
|  | Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName()); | 
|  | Record.push_back(D->getIdentifierNamespace()); | 
|  |  | 
|  | // The order matters here. It will be better to put the bit with higher | 
|  | // probability to be 0 in the end of the bits. See the comments in VisitDecl | 
|  | // for details. | 
|  | BitsPacker FunctionDeclBits; | 
|  | // FIXME: stable encoding | 
|  | FunctionDeclBits.addBits(llvm::to_underlying(D->getLinkageInternal()), 3); | 
|  | FunctionDeclBits.addBits((uint32_t)D->getStorageClass(), /*BitWidth=*/3); | 
|  | FunctionDeclBits.addBit(D->isInlineSpecified()); | 
|  | FunctionDeclBits.addBit(D->isInlined()); | 
|  | FunctionDeclBits.addBit(D->hasSkippedBody()); | 
|  | FunctionDeclBits.addBit(D->isVirtualAsWritten()); | 
|  | FunctionDeclBits.addBit(D->isPureVirtual()); | 
|  | FunctionDeclBits.addBit(D->hasInheritedPrototype()); | 
|  | FunctionDeclBits.addBit(D->hasWrittenPrototype()); | 
|  | FunctionDeclBits.addBit(D->isDeletedBit()); | 
|  | FunctionDeclBits.addBit(D->isTrivial()); | 
|  | FunctionDeclBits.addBit(D->isTrivialForCall()); | 
|  | FunctionDeclBits.addBit(D->isDefaulted()); | 
|  | FunctionDeclBits.addBit(D->isExplicitlyDefaulted()); | 
|  | FunctionDeclBits.addBit(D->isIneligibleOrNotSelected()); | 
|  | FunctionDeclBits.addBits((uint64_t)(D->getConstexprKind()), /*BitWidth=*/2); | 
|  | FunctionDeclBits.addBit(D->hasImplicitReturnZero()); | 
|  | FunctionDeclBits.addBit(D->isMultiVersion()); | 
|  | FunctionDeclBits.addBit(D->isLateTemplateParsed()); | 
|  | FunctionDeclBits.addBit(D->isInstantiatedFromMemberTemplate()); | 
|  | FunctionDeclBits.addBit(D->FriendConstraintRefersToEnclosingTemplate()); | 
|  | FunctionDeclBits.addBit(D->usesSEHTry()); | 
|  | FunctionDeclBits.addBit(D->isDestroyingOperatorDelete()); | 
|  | FunctionDeclBits.addBit(D->isTypeAwareOperatorNewOrDelete()); | 
|  | Record.push_back(FunctionDeclBits); | 
|  |  | 
|  | Record.AddSourceLocation(D->getEndLoc()); | 
|  | if (D->isExplicitlyDefaulted()) | 
|  | Record.AddSourceLocation(D->getDefaultLoc()); | 
|  |  | 
|  | Record.push_back(D->getODRHash()); | 
|  |  | 
|  | if (D->isDefaulted() || D->isDeletedAsWritten()) { | 
|  | if (auto *FDI = D->getDefalutedOrDeletedInfo()) { | 
|  | // Store both that there is an DefaultedOrDeletedInfo and whether it | 
|  | // contains a DeletedMessage. | 
|  | StringLiteral *DeletedMessage = FDI->getDeletedMessage(); | 
|  | Record.push_back(1 | (DeletedMessage ? 2 : 0)); | 
|  | if (DeletedMessage) | 
|  | Record.AddStmt(DeletedMessage); | 
|  |  | 
|  | Record.push_back(FDI->getUnqualifiedLookups().size()); | 
|  | for (DeclAccessPair P : FDI->getUnqualifiedLookups()) { | 
|  | Record.AddDeclRef(P.getDecl()); | 
|  | Record.push_back(P.getAccess()); | 
|  | } | 
|  | } else { | 
|  | Record.push_back(0); | 
|  | } | 
|  | } | 
|  |  | 
|  | if (D->getFriendObjectKind()) { | 
|  | // For a friend function defined inline within a class template, we have to | 
|  | // force the definition to be the one inside the definition of the template | 
|  | // class. Remember this relation to deserialize them together. | 
|  | if (auto *RD = dyn_cast<CXXRecordDecl>(D->getLexicalParent()); | 
|  | RD && isDefinitionInDependentContext(RD)) { | 
|  | Writer.RelatedDeclsMap[Writer.GetDeclRef(RD)].push_back( | 
|  | Writer.GetDeclRef(D)); | 
|  | } | 
|  | } | 
|  |  | 
|  | Record.push_back(D->param_size()); | 
|  | for (auto *P : D->parameters()) | 
|  | Record.AddDeclRef(P); | 
|  | Code = serialization::DECL_FUNCTION; | 
|  | } | 
|  |  | 
|  | static void addExplicitSpecifier(ExplicitSpecifier ES, | 
|  | ASTRecordWriter &Record) { | 
|  | uint64_t Kind = static_cast<uint64_t>(ES.getKind()); | 
|  | Kind = Kind << 1 | static_cast<bool>(ES.getExpr()); | 
|  | Record.push_back(Kind); | 
|  | if (ES.getExpr()) { | 
|  | Record.AddStmt(ES.getExpr()); | 
|  | } | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitCXXDeductionGuideDecl(CXXDeductionGuideDecl *D) { | 
|  | addExplicitSpecifier(D->getExplicitSpecifier(), Record); | 
|  | Record.AddDeclRef(D->Ctor); | 
|  | VisitFunctionDecl(D); | 
|  | Record.push_back(static_cast<unsigned char>(D->getDeductionCandidateKind())); | 
|  | Record.AddDeclRef(D->getSourceDeductionGuide()); | 
|  | Record.push_back( | 
|  | static_cast<unsigned char>(D->getSourceDeductionGuideKind())); | 
|  | Code = serialization::DECL_CXX_DEDUCTION_GUIDE; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { | 
|  | static_assert(DeclContext::NumObjCMethodDeclBits == 37, | 
|  | "You need to update the serializer after you change the " | 
|  | "ObjCMethodDeclBits"); | 
|  |  | 
|  | VisitNamedDecl(D); | 
|  | // FIXME: convert to LazyStmtPtr? | 
|  | // Unlike C/C++, method bodies will never be in header files. | 
|  | bool HasBodyStuff = D->getBody() != nullptr; | 
|  | Record.push_back(HasBodyStuff); | 
|  | if (HasBodyStuff) { | 
|  | Record.AddStmt(D->getBody()); | 
|  | } | 
|  | Record.AddDeclRef(D->getSelfDecl()); | 
|  | Record.AddDeclRef(D->getCmdDecl()); | 
|  | Record.push_back(D->isInstanceMethod()); | 
|  | Record.push_back(D->isVariadic()); | 
|  | Record.push_back(D->isPropertyAccessor()); | 
|  | Record.push_back(D->isSynthesizedAccessorStub()); | 
|  | Record.push_back(D->isDefined()); | 
|  | Record.push_back(D->isOverriding()); | 
|  | Record.push_back(D->hasSkippedBody()); | 
|  |  | 
|  | Record.push_back(D->isRedeclaration()); | 
|  | Record.push_back(D->hasRedeclaration()); | 
|  | if (D->hasRedeclaration()) { | 
|  | assert(Record.getASTContext().getObjCMethodRedeclaration(D)); | 
|  | Record.AddDeclRef(Record.getASTContext().getObjCMethodRedeclaration(D)); | 
|  | } | 
|  |  | 
|  | // FIXME: stable encoding for @required/@optional | 
|  | Record.push_back(llvm::to_underlying(D->getImplementationControl())); | 
|  | // FIXME: stable encoding for in/out/inout/bycopy/byref/oneway/nullability | 
|  | Record.push_back(D->getObjCDeclQualifier()); | 
|  | Record.push_back(D->hasRelatedResultType()); | 
|  | Record.AddTypeRef(D->getReturnType()); | 
|  | Record.AddTypeSourceInfo(D->getReturnTypeSourceInfo()); | 
|  | Record.AddSourceLocation(D->getEndLoc()); | 
|  | Record.push_back(D->param_size()); | 
|  | for (const auto *P : D->parameters()) | 
|  | Record.AddDeclRef(P); | 
|  |  | 
|  | Record.push_back(D->getSelLocsKind()); | 
|  | unsigned NumStoredSelLocs = D->getNumStoredSelLocs(); | 
|  | SourceLocation *SelLocs = D->getStoredSelLocs(); | 
|  | Record.push_back(NumStoredSelLocs); | 
|  | for (unsigned i = 0; i != NumStoredSelLocs; ++i) | 
|  | Record.AddSourceLocation(SelLocs[i]); | 
|  |  | 
|  | Code = serialization::DECL_OBJC_METHOD; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitObjCTypeParamDecl(ObjCTypeParamDecl *D) { | 
|  | VisitTypedefNameDecl(D); | 
|  | Record.push_back(D->Variance); | 
|  | Record.push_back(D->Index); | 
|  | Record.AddSourceLocation(D->VarianceLoc); | 
|  | Record.AddSourceLocation(D->ColonLoc); | 
|  |  | 
|  | Code = serialization::DECL_OBJC_TYPE_PARAM; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitObjCContainerDecl(ObjCContainerDecl *D) { | 
|  | static_assert(DeclContext::NumObjCContainerDeclBits == 64, | 
|  | "You need to update the serializer after you change the " | 
|  | "ObjCContainerDeclBits"); | 
|  |  | 
|  | VisitNamedDecl(D); | 
|  | Record.AddSourceLocation(D->getAtStartLoc()); | 
|  | Record.AddSourceRange(D->getAtEndRange()); | 
|  | // Abstract class (no need to define a stable serialization::DECL code). | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) { | 
|  | VisitRedeclarable(D); | 
|  | VisitObjCContainerDecl(D); | 
|  | Record.AddTypeRef(QualType(D->getTypeForDecl(), 0)); | 
|  | AddObjCTypeParamList(D->TypeParamList); | 
|  |  | 
|  | Record.push_back(D->isThisDeclarationADefinition()); | 
|  | if (D->isThisDeclarationADefinition()) { | 
|  | // Write the DefinitionData | 
|  | ObjCInterfaceDecl::DefinitionData &Data = D->data(); | 
|  |  | 
|  | Record.AddTypeSourceInfo(D->getSuperClassTInfo()); | 
|  | Record.AddSourceLocation(D->getEndOfDefinitionLoc()); | 
|  | Record.push_back(Data.HasDesignatedInitializers); | 
|  | Record.push_back(D->getODRHash()); | 
|  |  | 
|  | // Write out the protocols that are directly referenced by the @interface. | 
|  | Record.push_back(Data.ReferencedProtocols.size()); | 
|  | for (const auto *P : D->protocols()) | 
|  | Record.AddDeclRef(P); | 
|  | for (const auto &PL : D->protocol_locs()) | 
|  | Record.AddSourceLocation(PL); | 
|  |  | 
|  | // Write out the protocols that are transitively referenced. | 
|  | Record.push_back(Data.AllReferencedProtocols.size()); | 
|  | for (ObjCList<ObjCProtocolDecl>::iterator | 
|  | P = Data.AllReferencedProtocols.begin(), | 
|  | PEnd = Data.AllReferencedProtocols.end(); | 
|  | P != PEnd; ++P) | 
|  | Record.AddDeclRef(*P); | 
|  |  | 
|  |  | 
|  | if (ObjCCategoryDecl *Cat = D->getCategoryListRaw()) { | 
|  | // Ensure that we write out the set of categories for this class. | 
|  | Writer.ObjCClassesWithCategories.insert(D); | 
|  |  | 
|  | // Make sure that the categories get serialized. | 
|  | for (; Cat; Cat = Cat->getNextClassCategoryRaw()) | 
|  | (void)Writer.GetDeclRef(Cat); | 
|  | } | 
|  | } | 
|  |  | 
|  | Code = serialization::DECL_OBJC_INTERFACE; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitObjCIvarDecl(ObjCIvarDecl *D) { | 
|  | VisitFieldDecl(D); | 
|  | // FIXME: stable encoding for @public/@private/@protected/@package | 
|  | Record.push_back(D->getAccessControl()); | 
|  | Record.push_back(D->getSynthesize()); | 
|  |  | 
|  | if (D->getDeclContext() == D->getLexicalDeclContext() && | 
|  | !D->hasAttrs() && | 
|  | !D->isImplicit() && | 
|  | !D->isUsed(false) && | 
|  | !D->isInvalidDecl() && | 
|  | !D->isReferenced() && | 
|  | !D->isModulePrivate() && | 
|  | !D->getBitWidth() && | 
|  | !D->hasExtInfo() && | 
|  | D->getDeclName()) | 
|  | AbbrevToUse = Writer.getDeclObjCIvarAbbrev(); | 
|  |  | 
|  | Code = serialization::DECL_OBJC_IVAR; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { | 
|  | VisitRedeclarable(D); | 
|  | VisitObjCContainerDecl(D); | 
|  |  | 
|  | Record.push_back(D->isThisDeclarationADefinition()); | 
|  | if (D->isThisDeclarationADefinition()) { | 
|  | Record.push_back(D->protocol_size()); | 
|  | for (const auto *I : D->protocols()) | 
|  | Record.AddDeclRef(I); | 
|  | for (const auto &PL : D->protocol_locs()) | 
|  | Record.AddSourceLocation(PL); | 
|  | Record.push_back(D->getODRHash()); | 
|  | } | 
|  |  | 
|  | Code = serialization::DECL_OBJC_PROTOCOL; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitObjCAtDefsFieldDecl(ObjCAtDefsFieldDecl *D) { | 
|  | VisitFieldDecl(D); | 
|  | Code = serialization::DECL_OBJC_AT_DEFS_FIELD; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { | 
|  | VisitObjCContainerDecl(D); | 
|  | Record.AddSourceLocation(D->getCategoryNameLoc()); | 
|  | Record.AddSourceLocation(D->getIvarLBraceLoc()); | 
|  | Record.AddSourceLocation(D->getIvarRBraceLoc()); | 
|  | Record.AddDeclRef(D->getClassInterface()); | 
|  | AddObjCTypeParamList(D->TypeParamList); | 
|  | Record.push_back(D->protocol_size()); | 
|  | for (const auto *I : D->protocols()) | 
|  | Record.AddDeclRef(I); | 
|  | for (const auto &PL : D->protocol_locs()) | 
|  | Record.AddSourceLocation(PL); | 
|  | Code = serialization::DECL_OBJC_CATEGORY; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitObjCCompatibleAliasDecl(ObjCCompatibleAliasDecl *D) { | 
|  | VisitNamedDecl(D); | 
|  | Record.AddDeclRef(D->getClassInterface()); | 
|  | Code = serialization::DECL_OBJC_COMPATIBLE_ALIAS; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitObjCPropertyDecl(ObjCPropertyDecl *D) { | 
|  | VisitNamedDecl(D); | 
|  | Record.AddSourceLocation(D->getAtLoc()); | 
|  | Record.AddSourceLocation(D->getLParenLoc()); | 
|  | Record.AddTypeRef(D->getType()); | 
|  | Record.AddTypeSourceInfo(D->getTypeSourceInfo()); | 
|  | // FIXME: stable encoding | 
|  | Record.push_back((unsigned)D->getPropertyAttributes()); | 
|  | Record.push_back((unsigned)D->getPropertyAttributesAsWritten()); | 
|  | // FIXME: stable encoding | 
|  | Record.push_back((unsigned)D->getPropertyImplementation()); | 
|  | Record.AddDeclarationName(D->getGetterName()); | 
|  | Record.AddSourceLocation(D->getGetterNameLoc()); | 
|  | Record.AddDeclarationName(D->getSetterName()); | 
|  | Record.AddSourceLocation(D->getSetterNameLoc()); | 
|  | Record.AddDeclRef(D->getGetterMethodDecl()); | 
|  | Record.AddDeclRef(D->getSetterMethodDecl()); | 
|  | Record.AddDeclRef(D->getPropertyIvarDecl()); | 
|  | Code = serialization::DECL_OBJC_PROPERTY; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitObjCImplDecl(ObjCImplDecl *D) { | 
|  | VisitObjCContainerDecl(D); | 
|  | Record.AddDeclRef(D->getClassInterface()); | 
|  | // Abstract class (no need to define a stable serialization::DECL code). | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) { | 
|  | VisitObjCImplDecl(D); | 
|  | Record.AddSourceLocation(D->getCategoryNameLoc()); | 
|  | Code = serialization::DECL_OBJC_CATEGORY_IMPL; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitObjCImplementationDecl(ObjCImplementationDecl *D) { | 
|  | VisitObjCImplDecl(D); | 
|  | Record.AddDeclRef(D->getSuperClass()); | 
|  | Record.AddSourceLocation(D->getSuperClassLoc()); | 
|  | Record.AddSourceLocation(D->getIvarLBraceLoc()); | 
|  | Record.AddSourceLocation(D->getIvarRBraceLoc()); | 
|  | Record.push_back(D->hasNonZeroConstructors()); | 
|  | Record.push_back(D->hasDestructors()); | 
|  | Record.push_back(D->NumIvarInitializers); | 
|  | if (D->NumIvarInitializers) | 
|  | Record.AddCXXCtorInitializers( | 
|  | llvm::ArrayRef(D->init_begin(), D->init_end())); | 
|  | Code = serialization::DECL_OBJC_IMPLEMENTATION; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) { | 
|  | VisitDecl(D); | 
|  | Record.AddSourceLocation(D->getBeginLoc()); | 
|  | Record.AddDeclRef(D->getPropertyDecl()); | 
|  | Record.AddDeclRef(D->getPropertyIvarDecl()); | 
|  | Record.AddSourceLocation(D->getPropertyIvarDeclLoc()); | 
|  | Record.AddDeclRef(D->getGetterMethodDecl()); | 
|  | Record.AddDeclRef(D->getSetterMethodDecl()); | 
|  | Record.AddStmt(D->getGetterCXXConstructor()); | 
|  | Record.AddStmt(D->getSetterCXXAssignment()); | 
|  | Code = serialization::DECL_OBJC_PROPERTY_IMPL; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitFieldDecl(FieldDecl *D) { | 
|  | VisitDeclaratorDecl(D); | 
|  | Record.push_back(D->isMutable()); | 
|  |  | 
|  | Record.push_back((D->StorageKind << 1) | D->BitField); | 
|  | if (D->StorageKind == FieldDecl::ISK_CapturedVLAType) | 
|  | Record.AddTypeRef(QualType(D->getCapturedVLAType(), 0)); | 
|  | else if (D->BitField) | 
|  | Record.AddStmt(D->getBitWidth()); | 
|  |  | 
|  | if (!D->getDeclName() || D->isPlaceholderVar(Writer.getLangOpts())) | 
|  | Record.AddDeclRef( | 
|  | Record.getASTContext().getInstantiatedFromUnnamedFieldDecl(D)); | 
|  |  | 
|  | if (D->getDeclContext() == D->getLexicalDeclContext() && | 
|  | !D->hasAttrs() && | 
|  | !D->isImplicit() && | 
|  | !D->isUsed(false) && | 
|  | !D->isInvalidDecl() && | 
|  | !D->isReferenced() && | 
|  | !D->isTopLevelDeclInObjCContainer() && | 
|  | !D->isModulePrivate() && | 
|  | !D->getBitWidth() && | 
|  | !D->hasInClassInitializer() && | 
|  | !D->hasCapturedVLAType() && | 
|  | !D->hasExtInfo() && | 
|  | !ObjCIvarDecl::classofKind(D->getKind()) && | 
|  | !ObjCAtDefsFieldDecl::classofKind(D->getKind()) && | 
|  | D->getDeclName()) | 
|  | AbbrevToUse = Writer.getDeclFieldAbbrev(); | 
|  |  | 
|  | Code = serialization::DECL_FIELD; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitMSPropertyDecl(MSPropertyDecl *D) { | 
|  | VisitDeclaratorDecl(D); | 
|  | Record.AddIdentifierRef(D->getGetterId()); | 
|  | Record.AddIdentifierRef(D->getSetterId()); | 
|  | Code = serialization::DECL_MS_PROPERTY; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitMSGuidDecl(MSGuidDecl *D) { | 
|  | VisitValueDecl(D); | 
|  | MSGuidDecl::Parts Parts = D->getParts(); | 
|  | Record.push_back(Parts.Part1); | 
|  | Record.push_back(Parts.Part2); | 
|  | Record.push_back(Parts.Part3); | 
|  | Record.append(std::begin(Parts.Part4And5), std::end(Parts.Part4And5)); | 
|  | Code = serialization::DECL_MS_GUID; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitUnnamedGlobalConstantDecl( | 
|  | UnnamedGlobalConstantDecl *D) { | 
|  | VisitValueDecl(D); | 
|  | Record.AddAPValue(D->getValue()); | 
|  | Code = serialization::DECL_UNNAMED_GLOBAL_CONSTANT; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitTemplateParamObjectDecl(TemplateParamObjectDecl *D) { | 
|  | VisitValueDecl(D); | 
|  | Record.AddAPValue(D->getValue()); | 
|  | Code = serialization::DECL_TEMPLATE_PARAM_OBJECT; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitIndirectFieldDecl(IndirectFieldDecl *D) { | 
|  | VisitValueDecl(D); | 
|  | Record.push_back(D->getChainingSize()); | 
|  |  | 
|  | for (const auto *P : D->chain()) | 
|  | Record.AddDeclRef(P); | 
|  | Code = serialization::DECL_INDIRECTFIELD; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitVarDecl(VarDecl *D) { | 
|  | VisitRedeclarable(D); | 
|  | VisitDeclaratorDecl(D); | 
|  |  | 
|  | // The order matters here. It will be better to put the bit with higher | 
|  | // probability to be 0 in the end of the bits. See the comments in VisitDecl | 
|  | // for details. | 
|  | BitsPacker VarDeclBits; | 
|  | VarDeclBits.addBits(llvm::to_underlying(D->getLinkageInternal()), | 
|  | /*BitWidth=*/3); | 
|  |  | 
|  | bool ModulesCodegen = shouldVarGenerateHereOnly(D); | 
|  | VarDeclBits.addBit(ModulesCodegen); | 
|  |  | 
|  | VarDeclBits.addBits(D->getStorageClass(), /*BitWidth=*/3); | 
|  | VarDeclBits.addBits(D->getTSCSpec(), /*BitWidth=*/2); | 
|  | VarDeclBits.addBits(D->getInitStyle(), /*BitWidth=*/2); | 
|  | VarDeclBits.addBit(D->isARCPseudoStrong()); | 
|  |  | 
|  | bool HasDeducedType = false; | 
|  | if (!isa<ParmVarDecl>(D)) { | 
|  | VarDeclBits.addBit(D->isThisDeclarationADemotedDefinition()); | 
|  | VarDeclBits.addBit(D->isExceptionVariable()); | 
|  | VarDeclBits.addBit(D->isNRVOVariable()); | 
|  | VarDeclBits.addBit(D->isCXXForRangeDecl()); | 
|  |  | 
|  | VarDeclBits.addBit(D->isInline()); | 
|  | VarDeclBits.addBit(D->isInlineSpecified()); | 
|  | VarDeclBits.addBit(D->isConstexpr()); | 
|  | VarDeclBits.addBit(D->isInitCapture()); | 
|  | VarDeclBits.addBit(D->isPreviousDeclInSameBlockScope()); | 
|  |  | 
|  | VarDeclBits.addBit(D->isEscapingByref()); | 
|  | HasDeducedType = D->getType()->getContainedDeducedType(); | 
|  | VarDeclBits.addBit(HasDeducedType); | 
|  |  | 
|  | if (const auto *IPD = dyn_cast<ImplicitParamDecl>(D)) | 
|  | VarDeclBits.addBits(llvm::to_underlying(IPD->getParameterKind()), | 
|  | /*Width=*/3); | 
|  | else | 
|  | VarDeclBits.addBits(0, /*Width=*/3); | 
|  |  | 
|  | VarDeclBits.addBit(D->isObjCForDecl()); | 
|  | VarDeclBits.addBit(D->isCXXForRangeImplicitVar()); | 
|  | } | 
|  |  | 
|  | Record.push_back(VarDeclBits); | 
|  |  | 
|  | if (ModulesCodegen) | 
|  | Writer.AddDeclRef(D, Writer.ModularCodegenDecls); | 
|  |  | 
|  | if (D->hasAttr<BlocksAttr>()) { | 
|  | BlockVarCopyInit Init = Record.getASTContext().getBlockVarCopyInit(D); | 
|  | Record.AddStmt(Init.getCopyExpr()); | 
|  | if (Init.getCopyExpr()) | 
|  | Record.push_back(Init.canThrow()); | 
|  | } | 
|  |  | 
|  | enum { | 
|  | VarNotTemplate = 0, VarTemplate, StaticDataMemberSpecialization | 
|  | }; | 
|  | if (VarTemplateDecl *TemplD = D->getDescribedVarTemplate()) { | 
|  | Record.push_back(VarTemplate); | 
|  | Record.AddDeclRef(TemplD); | 
|  | } else if (MemberSpecializationInfo *SpecInfo | 
|  | = D->getMemberSpecializationInfo()) { | 
|  | Record.push_back(StaticDataMemberSpecialization); | 
|  | Record.AddDeclRef(SpecInfo->getInstantiatedFrom()); | 
|  | Record.push_back(SpecInfo->getTemplateSpecializationKind()); | 
|  | Record.AddSourceLocation(SpecInfo->getPointOfInstantiation()); | 
|  | } else { | 
|  | Record.push_back(VarNotTemplate); | 
|  | } | 
|  |  | 
|  | if (D->getDeclContext() == D->getLexicalDeclContext() && !D->hasAttrs() && | 
|  | !D->isTopLevelDeclInObjCContainer() && | 
|  | !needsAnonymousDeclarationNumber(D) && | 
|  | D->getDeclName().getNameKind() == DeclarationName::Identifier && | 
|  | !D->hasExtInfo() && D->getFirstDecl() == D->getMostRecentDecl() && | 
|  | D->getKind() == Decl::Var && !D->isInline() && !D->isConstexpr() && | 
|  | !D->isInitCapture() && !D->isPreviousDeclInSameBlockScope() && | 
|  | !D->hasInitWithSideEffects() && !D->isEscapingByref() && | 
|  | !HasDeducedType && D->getStorageDuration() != SD_Static && | 
|  | !D->getDescribedVarTemplate() && !D->getMemberSpecializationInfo() && | 
|  | !D->isObjCForDecl() && !isa<ImplicitParamDecl>(D) && | 
|  | !D->isEscapingByref()) | 
|  | AbbrevToUse = Writer.getDeclVarAbbrev(); | 
|  |  | 
|  | Code = serialization::DECL_VAR; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitImplicitParamDecl(ImplicitParamDecl *D) { | 
|  | VisitVarDecl(D); | 
|  | Code = serialization::DECL_IMPLICIT_PARAM; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitParmVarDecl(ParmVarDecl *D) { | 
|  | VisitVarDecl(D); | 
|  |  | 
|  | // See the implementation of `ParmVarDecl::getParameterIndex()`, which may | 
|  | // exceed the size of the normal bitfield. So it may be better to not pack | 
|  | // these bits. | 
|  | Record.push_back(D->getFunctionScopeIndex()); | 
|  |  | 
|  | BitsPacker ParmVarDeclBits; | 
|  | ParmVarDeclBits.addBit(D->isObjCMethodParameter()); | 
|  | ParmVarDeclBits.addBits(D->getFunctionScopeDepth(), /*BitsWidth=*/7); | 
|  | // FIXME: stable encoding | 
|  | ParmVarDeclBits.addBits(D->getObjCDeclQualifier(), /*BitsWidth=*/7); | 
|  | ParmVarDeclBits.addBit(D->isKNRPromoted()); | 
|  | ParmVarDeclBits.addBit(D->hasInheritedDefaultArg()); | 
|  | ParmVarDeclBits.addBit(D->hasUninstantiatedDefaultArg()); | 
|  | ParmVarDeclBits.addBit(D->getExplicitObjectParamThisLoc().isValid()); | 
|  | Record.push_back(ParmVarDeclBits); | 
|  |  | 
|  | if (D->hasUninstantiatedDefaultArg()) | 
|  | Record.AddStmt(D->getUninstantiatedDefaultArg()); | 
|  | if (D->getExplicitObjectParamThisLoc().isValid()) | 
|  | Record.AddSourceLocation(D->getExplicitObjectParamThisLoc()); | 
|  | Code = serialization::DECL_PARM_VAR; | 
|  |  | 
|  | // If the assumptions about the DECL_PARM_VAR abbrev are true, use it.  Here | 
|  | // we dynamically check for the properties that we optimize for, but don't | 
|  | // know are true of all PARM_VAR_DECLs. | 
|  | if (D->getDeclContext() == D->getLexicalDeclContext() && !D->hasAttrs() && | 
|  | !D->hasExtInfo() && D->getStorageClass() == 0 && !D->isInvalidDecl() && | 
|  | !D->isTopLevelDeclInObjCContainer() && | 
|  | D->getInitStyle() == VarDecl::CInit && // Can params have anything else? | 
|  | D->getInit() == nullptr)               // No default expr. | 
|  | AbbrevToUse = Writer.getDeclParmVarAbbrev(); | 
|  |  | 
|  | // Check things we know are true of *every* PARM_VAR_DECL, which is more than | 
|  | // just us assuming it. | 
|  | assert(!D->getTSCSpec() && "PARM_VAR_DECL can't use TLS"); | 
|  | assert(!D->isThisDeclarationADemotedDefinition() | 
|  | && "PARM_VAR_DECL can't be demoted definition."); | 
|  | assert(D->getAccess() == AS_none && "PARM_VAR_DECL can't be public/private"); | 
|  | assert(!D->isExceptionVariable() && "PARM_VAR_DECL can't be exception var"); | 
|  | assert(D->getPreviousDecl() == nullptr && "PARM_VAR_DECL can't be redecl"); | 
|  | assert(!D->isStaticDataMember() && | 
|  | "PARM_VAR_DECL can't be static data member"); | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitDecompositionDecl(DecompositionDecl *D) { | 
|  | // Record the number of bindings first to simplify deserialization. | 
|  | Record.push_back(D->bindings().size()); | 
|  |  | 
|  | VisitVarDecl(D); | 
|  | for (auto *B : D->bindings()) | 
|  | Record.AddDeclRef(B); | 
|  | Code = serialization::DECL_DECOMPOSITION; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitBindingDecl(BindingDecl *D) { | 
|  | VisitValueDecl(D); | 
|  | Record.AddStmt(D->getBinding()); | 
|  | Code = serialization::DECL_BINDING; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitFileScopeAsmDecl(FileScopeAsmDecl *D) { | 
|  | VisitDecl(D); | 
|  | Record.AddStmt(D->getAsmStringExpr()); | 
|  | Record.AddSourceLocation(D->getRParenLoc()); | 
|  | Code = serialization::DECL_FILE_SCOPE_ASM; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitTopLevelStmtDecl(TopLevelStmtDecl *D) { | 
|  | VisitDecl(D); | 
|  | Record.AddStmt(D->getStmt()); | 
|  | Code = serialization::DECL_TOP_LEVEL_STMT_DECL; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitEmptyDecl(EmptyDecl *D) { | 
|  | VisitDecl(D); | 
|  | Code = serialization::DECL_EMPTY; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitLifetimeExtendedTemporaryDecl( | 
|  | LifetimeExtendedTemporaryDecl *D) { | 
|  | VisitDecl(D); | 
|  | Record.AddDeclRef(D->getExtendingDecl()); | 
|  | Record.AddStmt(D->getTemporaryExpr()); | 
|  | Record.push_back(static_cast<bool>(D->getValue())); | 
|  | if (D->getValue()) | 
|  | Record.AddAPValue(*D->getValue()); | 
|  | Record.push_back(D->getManglingNumber()); | 
|  | Code = serialization::DECL_LIFETIME_EXTENDED_TEMPORARY; | 
|  | } | 
|  | void ASTDeclWriter::VisitBlockDecl(BlockDecl *D) { | 
|  | VisitDecl(D); | 
|  | Record.AddStmt(D->getBody()); | 
|  | Record.AddTypeSourceInfo(D->getSignatureAsWritten()); | 
|  | Record.push_back(D->param_size()); | 
|  | for (ParmVarDecl *P : D->parameters()) | 
|  | Record.AddDeclRef(P); | 
|  | Record.push_back(D->isVariadic()); | 
|  | Record.push_back(D->blockMissingReturnType()); | 
|  | Record.push_back(D->isConversionFromLambda()); | 
|  | Record.push_back(D->doesNotEscape()); | 
|  | Record.push_back(D->canAvoidCopyToHeap()); | 
|  | Record.push_back(D->capturesCXXThis()); | 
|  | Record.push_back(D->getNumCaptures()); | 
|  | for (const auto &capture : D->captures()) { | 
|  | Record.AddDeclRef(capture.getVariable()); | 
|  |  | 
|  | unsigned flags = 0; | 
|  | if (capture.isByRef()) flags |= 1; | 
|  | if (capture.isNested()) flags |= 2; | 
|  | if (capture.hasCopyExpr()) flags |= 4; | 
|  | Record.push_back(flags); | 
|  |  | 
|  | if (capture.hasCopyExpr()) Record.AddStmt(capture.getCopyExpr()); | 
|  | } | 
|  |  | 
|  | Code = serialization::DECL_BLOCK; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitOutlinedFunctionDecl(OutlinedFunctionDecl *D) { | 
|  | Record.push_back(D->getNumParams()); | 
|  | VisitDecl(D); | 
|  | for (unsigned I = 0; I < D->getNumParams(); ++I) | 
|  | Record.AddDeclRef(D->getParam(I)); | 
|  | Record.push_back(D->isNothrow() ? 1 : 0); | 
|  | Record.AddStmt(D->getBody()); | 
|  | Code = serialization::DECL_OUTLINEDFUNCTION; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitCapturedDecl(CapturedDecl *CD) { | 
|  | Record.push_back(CD->getNumParams()); | 
|  | VisitDecl(CD); | 
|  | Record.push_back(CD->getContextParamPosition()); | 
|  | Record.push_back(CD->isNothrow() ? 1 : 0); | 
|  | // Body is stored by VisitCapturedStmt. | 
|  | for (unsigned I = 0; I < CD->getNumParams(); ++I) | 
|  | Record.AddDeclRef(CD->getParam(I)); | 
|  | Code = serialization::DECL_CAPTURED; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitLinkageSpecDecl(LinkageSpecDecl *D) { | 
|  | static_assert(DeclContext::NumLinkageSpecDeclBits == 17, | 
|  | "You need to update the serializer after you change the" | 
|  | "LinkageSpecDeclBits"); | 
|  |  | 
|  | VisitDecl(D); | 
|  | Record.push_back(llvm::to_underlying(D->getLanguage())); | 
|  | Record.AddSourceLocation(D->getExternLoc()); | 
|  | Record.AddSourceLocation(D->getRBraceLoc()); | 
|  | Code = serialization::DECL_LINKAGE_SPEC; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitExportDecl(ExportDecl *D) { | 
|  | VisitDecl(D); | 
|  | Record.AddSourceLocation(D->getRBraceLoc()); | 
|  | Code = serialization::DECL_EXPORT; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitLabelDecl(LabelDecl *D) { | 
|  | VisitNamedDecl(D); | 
|  | Record.AddSourceLocation(D->getBeginLoc()); | 
|  | Code = serialization::DECL_LABEL; | 
|  | } | 
|  |  | 
|  |  | 
|  | void ASTDeclWriter::VisitNamespaceDecl(NamespaceDecl *D) { | 
|  | VisitRedeclarable(D); | 
|  | VisitNamedDecl(D); | 
|  |  | 
|  | BitsPacker NamespaceDeclBits; | 
|  | NamespaceDeclBits.addBit(D->isInline()); | 
|  | NamespaceDeclBits.addBit(D->isNested()); | 
|  | Record.push_back(NamespaceDeclBits); | 
|  |  | 
|  | Record.AddSourceLocation(D->getBeginLoc()); | 
|  | Record.AddSourceLocation(D->getRBraceLoc()); | 
|  |  | 
|  | if (D->isFirstDecl()) | 
|  | Record.AddDeclRef(D->getAnonymousNamespace()); | 
|  | Code = serialization::DECL_NAMESPACE; | 
|  |  | 
|  | if (Writer.hasChain() && D->isAnonymousNamespace() && | 
|  | D == D->getMostRecentDecl()) { | 
|  | // This is a most recent reopening of the anonymous namespace. If its parent | 
|  | // is in a previous PCH (or is the TU), mark that parent for update, because | 
|  | // the original namespace always points to the latest re-opening of its | 
|  | // anonymous namespace. | 
|  | Decl *Parent = cast<Decl>( | 
|  | D->getParent()->getRedeclContext()->getPrimaryContext()); | 
|  | if (Parent->isFromASTFile() || isa<TranslationUnitDecl>(Parent)) { | 
|  | Writer.DeclUpdates[Parent].push_back( | 
|  | ASTWriter::DeclUpdate(DeclUpdateKind::CXXAddedAnonymousNamespace, D)); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitNamespaceAliasDecl(NamespaceAliasDecl *D) { | 
|  | VisitRedeclarable(D); | 
|  | VisitNamedDecl(D); | 
|  | Record.AddSourceLocation(D->getNamespaceLoc()); | 
|  | Record.AddSourceLocation(D->getTargetNameLoc()); | 
|  | Record.AddNestedNameSpecifierLoc(D->getQualifierLoc()); | 
|  | Record.AddDeclRef(D->getNamespace()); | 
|  | Code = serialization::DECL_NAMESPACE_ALIAS; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitUsingDecl(UsingDecl *D) { | 
|  | VisitNamedDecl(D); | 
|  | Record.AddSourceLocation(D->getUsingLoc()); | 
|  | Record.AddNestedNameSpecifierLoc(D->getQualifierLoc()); | 
|  | Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName()); | 
|  | Record.AddDeclRef(D->FirstUsingShadow.getPointer()); | 
|  | Record.push_back(D->hasTypename()); | 
|  | Record.AddDeclRef(Record.getASTContext().getInstantiatedFromUsingDecl(D)); | 
|  | Code = serialization::DECL_USING; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitUsingEnumDecl(UsingEnumDecl *D) { | 
|  | VisitNamedDecl(D); | 
|  | Record.AddSourceLocation(D->getUsingLoc()); | 
|  | Record.AddSourceLocation(D->getEnumLoc()); | 
|  | Record.AddTypeSourceInfo(D->getEnumType()); | 
|  | Record.AddDeclRef(D->FirstUsingShadow.getPointer()); | 
|  | Record.AddDeclRef(Record.getASTContext().getInstantiatedFromUsingEnumDecl(D)); | 
|  | Code = serialization::DECL_USING_ENUM; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitUsingPackDecl(UsingPackDecl *D) { | 
|  | Record.push_back(D->NumExpansions); | 
|  | VisitNamedDecl(D); | 
|  | Record.AddDeclRef(D->getInstantiatedFromUsingDecl()); | 
|  | for (auto *E : D->expansions()) | 
|  | Record.AddDeclRef(E); | 
|  | Code = serialization::DECL_USING_PACK; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitUsingShadowDecl(UsingShadowDecl *D) { | 
|  | VisitRedeclarable(D); | 
|  | VisitNamedDecl(D); | 
|  | Record.AddDeclRef(D->getTargetDecl()); | 
|  | Record.push_back(D->getIdentifierNamespace()); | 
|  | Record.AddDeclRef(D->UsingOrNextShadow); | 
|  | Record.AddDeclRef( | 
|  | Record.getASTContext().getInstantiatedFromUsingShadowDecl(D)); | 
|  |  | 
|  | if (D->getDeclContext() == D->getLexicalDeclContext() && | 
|  | D->getFirstDecl() == D->getMostRecentDecl() && !D->hasAttrs() && | 
|  | !needsAnonymousDeclarationNumber(D) && | 
|  | D->getDeclName().getNameKind() == DeclarationName::Identifier) | 
|  | AbbrevToUse = Writer.getDeclUsingShadowAbbrev(); | 
|  |  | 
|  | Code = serialization::DECL_USING_SHADOW; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitConstructorUsingShadowDecl( | 
|  | ConstructorUsingShadowDecl *D) { | 
|  | VisitUsingShadowDecl(D); | 
|  | Record.AddDeclRef(D->NominatedBaseClassShadowDecl); | 
|  | Record.AddDeclRef(D->ConstructedBaseClassShadowDecl); | 
|  | Record.push_back(D->IsVirtual); | 
|  | Code = serialization::DECL_CONSTRUCTOR_USING_SHADOW; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitUsingDirectiveDecl(UsingDirectiveDecl *D) { | 
|  | VisitNamedDecl(D); | 
|  | Record.AddSourceLocation(D->getUsingLoc()); | 
|  | Record.AddSourceLocation(D->getNamespaceKeyLocation()); | 
|  | Record.AddNestedNameSpecifierLoc(D->getQualifierLoc()); | 
|  | Record.AddDeclRef(D->getNominatedNamespace()); | 
|  | Record.AddDeclRef(dyn_cast<Decl>(D->getCommonAncestor())); | 
|  | Code = serialization::DECL_USING_DIRECTIVE; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitUnresolvedUsingValueDecl(UnresolvedUsingValueDecl *D) { | 
|  | VisitValueDecl(D); | 
|  | Record.AddSourceLocation(D->getUsingLoc()); | 
|  | Record.AddNestedNameSpecifierLoc(D->getQualifierLoc()); | 
|  | Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName()); | 
|  | Record.AddSourceLocation(D->getEllipsisLoc()); | 
|  | Code = serialization::DECL_UNRESOLVED_USING_VALUE; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitUnresolvedUsingTypenameDecl( | 
|  | UnresolvedUsingTypenameDecl *D) { | 
|  | VisitTypeDecl(D); | 
|  | Record.AddSourceLocation(D->getTypenameLoc()); | 
|  | Record.AddNestedNameSpecifierLoc(D->getQualifierLoc()); | 
|  | Record.AddSourceLocation(D->getEllipsisLoc()); | 
|  | Code = serialization::DECL_UNRESOLVED_USING_TYPENAME; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitUnresolvedUsingIfExistsDecl( | 
|  | UnresolvedUsingIfExistsDecl *D) { | 
|  | VisitNamedDecl(D); | 
|  | Code = serialization::DECL_UNRESOLVED_USING_IF_EXISTS; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { | 
|  | VisitRecordDecl(D); | 
|  |  | 
|  | enum { | 
|  | CXXRecNotTemplate = 0, | 
|  | CXXRecTemplate, | 
|  | CXXRecMemberSpecialization, | 
|  | CXXLambda | 
|  | }; | 
|  | if (ClassTemplateDecl *TemplD = D->getDescribedClassTemplate()) { | 
|  | Record.push_back(CXXRecTemplate); | 
|  | Record.AddDeclRef(TemplD); | 
|  | } else if (MemberSpecializationInfo *MSInfo | 
|  | = D->getMemberSpecializationInfo()) { | 
|  | Record.push_back(CXXRecMemberSpecialization); | 
|  | Record.AddDeclRef(MSInfo->getInstantiatedFrom()); | 
|  | Record.push_back(MSInfo->getTemplateSpecializationKind()); | 
|  | Record.AddSourceLocation(MSInfo->getPointOfInstantiation()); | 
|  | } else if (D->isLambda()) { | 
|  | // For a lambda, we need some information early for merging. | 
|  | Record.push_back(CXXLambda); | 
|  | if (auto *Context = D->getLambdaContextDecl()) { | 
|  | Record.AddDeclRef(Context); | 
|  | Record.push_back(D->getLambdaIndexInContext()); | 
|  | } else { | 
|  | Record.push_back(0); | 
|  | } | 
|  | // For lambdas inside template functions, remember the mapping to | 
|  | // deserialize them together. | 
|  | if (auto *FD = llvm::dyn_cast_or_null<FunctionDecl>(D->getDeclContext()); | 
|  | FD && isDefinitionInDependentContext(FD)) { | 
|  | Writer.RelatedDeclsMap[Writer.GetDeclRef(FD)].push_back( | 
|  | Writer.GetDeclRef(D->getLambdaCallOperator())); | 
|  | } | 
|  | } else { | 
|  | Record.push_back(CXXRecNotTemplate); | 
|  | } | 
|  |  | 
|  | Record.push_back(D->isThisDeclarationADefinition()); | 
|  | if (D->isThisDeclarationADefinition()) | 
|  | Record.AddCXXDefinitionData(D); | 
|  |  | 
|  | if (D->isCompleteDefinition() && D->isInNamedModule()) | 
|  | Writer.AddDeclRef(D, Writer.ModularCodegenDecls); | 
|  |  | 
|  | // Store (what we currently believe to be) the key function to avoid | 
|  | // deserializing every method so we can compute it. | 
|  | // | 
|  | // FIXME: Avoid adding the key function if the class is defined in | 
|  | // module purview since in that case the key function is meaningless. | 
|  | if (D->isCompleteDefinition()) | 
|  | Record.AddDeclRef(Record.getASTContext().getCurrentKeyFunction(D)); | 
|  |  | 
|  | Code = serialization::DECL_CXX_RECORD; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitCXXMethodDecl(CXXMethodDecl *D) { | 
|  | VisitFunctionDecl(D); | 
|  | if (D->isCanonicalDecl()) { | 
|  | Record.push_back(D->size_overridden_methods()); | 
|  | for (const CXXMethodDecl *MD : D->overridden_methods()) | 
|  | Record.AddDeclRef(MD); | 
|  | } else { | 
|  | // We only need to record overridden methods once for the canonical decl. | 
|  | Record.push_back(0); | 
|  | } | 
|  |  | 
|  | if (D->getDeclContext() == D->getLexicalDeclContext() && | 
|  | D->getFirstDecl() == D->getMostRecentDecl() && !D->isInvalidDecl() && | 
|  | !D->hasAttrs() && !D->isTopLevelDeclInObjCContainer() && | 
|  | D->getDeclName().getNameKind() == DeclarationName::Identifier && | 
|  | !D->hasExtInfo() && !D->isExplicitlyDefaulted()) { | 
|  | if (D->getTemplatedKind() == FunctionDecl::TK_NonTemplate || | 
|  | D->getTemplatedKind() == FunctionDecl::TK_FunctionTemplate || | 
|  | D->getTemplatedKind() == FunctionDecl::TK_MemberSpecialization || | 
|  | D->getTemplatedKind() == FunctionDecl::TK_DependentNonTemplate) | 
|  | AbbrevToUse = Writer.getDeclCXXMethodAbbrev(D->getTemplatedKind()); | 
|  | else if (D->getTemplatedKind() == | 
|  | FunctionDecl::TK_FunctionTemplateSpecialization) { | 
|  | FunctionTemplateSpecializationInfo *FTSInfo = | 
|  | D->getTemplateSpecializationInfo(); | 
|  |  | 
|  | if (FTSInfo->TemplateArguments->size() == 1) { | 
|  | const TemplateArgument &TA = FTSInfo->TemplateArguments->get(0); | 
|  | if (TA.getKind() == TemplateArgument::Type && | 
|  | !FTSInfo->TemplateArgumentsAsWritten && | 
|  | !FTSInfo->getMemberSpecializationInfo()) | 
|  | AbbrevToUse = Writer.getDeclCXXMethodAbbrev(D->getTemplatedKind()); | 
|  | } | 
|  | } else if (D->getTemplatedKind() == | 
|  | FunctionDecl::TK_DependentFunctionTemplateSpecialization) { | 
|  | DependentFunctionTemplateSpecializationInfo *DFTSInfo = | 
|  | D->getDependentSpecializationInfo(); | 
|  | if (!DFTSInfo->TemplateArgumentsAsWritten) | 
|  | AbbrevToUse = Writer.getDeclCXXMethodAbbrev(D->getTemplatedKind()); | 
|  | } | 
|  | } | 
|  |  | 
|  | Code = serialization::DECL_CXX_METHOD; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { | 
|  | static_assert(DeclContext::NumCXXConstructorDeclBits == 64, | 
|  | "You need to update the serializer after you change the " | 
|  | "CXXConstructorDeclBits"); | 
|  |  | 
|  | Record.push_back(D->getTrailingAllocKind()); | 
|  | addExplicitSpecifier(D->getExplicitSpecifierInternal(), Record); | 
|  | if (auto Inherited = D->getInheritedConstructor()) { | 
|  | Record.AddDeclRef(Inherited.getShadowDecl()); | 
|  | Record.AddDeclRef(Inherited.getConstructor()); | 
|  | } | 
|  |  | 
|  | VisitCXXMethodDecl(D); | 
|  | Code = serialization::DECL_CXX_CONSTRUCTOR; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitCXXDestructorDecl(CXXDestructorDecl *D) { | 
|  | VisitCXXMethodDecl(D); | 
|  |  | 
|  | Record.AddDeclRef(D->getOperatorDelete()); | 
|  | if (D->getOperatorDelete()) | 
|  | Record.AddStmt(D->getOperatorDeleteThisArg()); | 
|  | Record.AddDeclRef(D->getOperatorGlobalDelete()); | 
|  |  | 
|  | Code = serialization::DECL_CXX_DESTRUCTOR; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitCXXConversionDecl(CXXConversionDecl *D) { | 
|  | addExplicitSpecifier(D->getExplicitSpecifier(), Record); | 
|  | VisitCXXMethodDecl(D); | 
|  | Code = serialization::DECL_CXX_CONVERSION; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitImportDecl(ImportDecl *D) { | 
|  | VisitDecl(D); | 
|  | Record.push_back(Writer.getSubmoduleID(D->getImportedModule())); | 
|  | ArrayRef<SourceLocation> IdentifierLocs = D->getIdentifierLocs(); | 
|  | Record.push_back(!IdentifierLocs.empty()); | 
|  | if (IdentifierLocs.empty()) { | 
|  | Record.AddSourceLocation(D->getEndLoc()); | 
|  | Record.push_back(1); | 
|  | } else { | 
|  | for (unsigned I = 0, N = IdentifierLocs.size(); I != N; ++I) | 
|  | Record.AddSourceLocation(IdentifierLocs[I]); | 
|  | Record.push_back(IdentifierLocs.size()); | 
|  | } | 
|  | // Note: the number of source locations must always be the last element in | 
|  | // the record. | 
|  | Code = serialization::DECL_IMPORT; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitAccessSpecDecl(AccessSpecDecl *D) { | 
|  | VisitDecl(D); | 
|  | Record.AddSourceLocation(D->getColonLoc()); | 
|  | Code = serialization::DECL_ACCESS_SPEC; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitFriendDecl(FriendDecl *D) { | 
|  | // Record the number of friend type template parameter lists here | 
|  | // so as to simplify memory allocation during deserialization. | 
|  | Record.push_back(D->NumTPLists); | 
|  | VisitDecl(D); | 
|  | bool hasFriendDecl = isa<NamedDecl *>(D->Friend); | 
|  | Record.push_back(hasFriendDecl); | 
|  | if (hasFriendDecl) | 
|  | Record.AddDeclRef(D->getFriendDecl()); | 
|  | else | 
|  | Record.AddTypeSourceInfo(D->getFriendType()); | 
|  | for (unsigned i = 0; i < D->NumTPLists; ++i) | 
|  | Record.AddTemplateParameterList(D->getFriendTypeTemplateParameterList(i)); | 
|  | Record.AddDeclRef(D->getNextFriend()); | 
|  | Record.push_back(D->UnsupportedFriend); | 
|  | Record.AddSourceLocation(D->FriendLoc); | 
|  | Record.AddSourceLocation(D->EllipsisLoc); | 
|  | Code = serialization::DECL_FRIEND; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitFriendTemplateDecl(FriendTemplateDecl *D) { | 
|  | VisitDecl(D); | 
|  | Record.push_back(D->getNumTemplateParameters()); | 
|  | for (unsigned i = 0, e = D->getNumTemplateParameters(); i != e; ++i) | 
|  | Record.AddTemplateParameterList(D->getTemplateParameterList(i)); | 
|  | Record.push_back(D->getFriendDecl() != nullptr); | 
|  | if (D->getFriendDecl()) | 
|  | Record.AddDeclRef(D->getFriendDecl()); | 
|  | else | 
|  | Record.AddTypeSourceInfo(D->getFriendType()); | 
|  | Record.AddSourceLocation(D->getFriendLoc()); | 
|  | Code = serialization::DECL_FRIEND_TEMPLATE; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitTemplateDecl(TemplateDecl *D) { | 
|  | VisitNamedDecl(D); | 
|  |  | 
|  | Record.AddTemplateParameterList(D->getTemplateParameters()); | 
|  | Record.AddDeclRef(D->getTemplatedDecl()); | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitConceptDecl(ConceptDecl *D) { | 
|  | VisitTemplateDecl(D); | 
|  | Record.AddStmt(D->getConstraintExpr()); | 
|  | Code = serialization::DECL_CONCEPT; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitImplicitConceptSpecializationDecl( | 
|  | ImplicitConceptSpecializationDecl *D) { | 
|  | Record.push_back(D->getTemplateArguments().size()); | 
|  | VisitDecl(D); | 
|  | for (const TemplateArgument &Arg : D->getTemplateArguments()) | 
|  | Record.AddTemplateArgument(Arg); | 
|  | Code = serialization::DECL_IMPLICIT_CONCEPT_SPECIALIZATION; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitRequiresExprBodyDecl(RequiresExprBodyDecl *D) { | 
|  | Code = serialization::DECL_REQUIRES_EXPR_BODY; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitRedeclarableTemplateDecl(RedeclarableTemplateDecl *D) { | 
|  | VisitRedeclarable(D); | 
|  |  | 
|  | // Emit data to initialize CommonOrPrev before VisitTemplateDecl so that | 
|  | // getCommonPtr() can be used while this is still initializing. | 
|  | if (D->isFirstDecl()) { | 
|  | // This declaration owns the 'common' pointer, so serialize that data now. | 
|  | Record.AddDeclRef(D->getInstantiatedFromMemberTemplate()); | 
|  | if (D->getInstantiatedFromMemberTemplate()) | 
|  | Record.push_back(D->isMemberSpecialization()); | 
|  | } | 
|  |  | 
|  | VisitTemplateDecl(D); | 
|  | Record.push_back(D->getIdentifierNamespace()); | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitClassTemplateDecl(ClassTemplateDecl *D) { | 
|  | VisitRedeclarableTemplateDecl(D); | 
|  |  | 
|  | if (D->isFirstDecl()) | 
|  | AddTemplateSpecializations(D); | 
|  |  | 
|  | // Force emitting the corresponding deduction guide in reduced BMI mode. | 
|  | // Otherwise, the deduction guide may be optimized out incorrectly. | 
|  | if (Writer.isGeneratingReducedBMI()) { | 
|  | auto Name = | 
|  | Record.getASTContext().DeclarationNames.getCXXDeductionGuideName(D); | 
|  | for (auto *DG : D->getDeclContext()->noload_lookup(Name)) | 
|  | Writer.GetDeclRef(DG->getCanonicalDecl()); | 
|  | } | 
|  |  | 
|  | Code = serialization::DECL_CLASS_TEMPLATE; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitClassTemplateSpecializationDecl( | 
|  | ClassTemplateSpecializationDecl *D) { | 
|  | RegisterTemplateSpecialization(D->getSpecializedTemplate(), D); | 
|  |  | 
|  | VisitCXXRecordDecl(D); | 
|  |  | 
|  | llvm::PointerUnion<ClassTemplateDecl *, | 
|  | ClassTemplatePartialSpecializationDecl *> InstFrom | 
|  | = D->getSpecializedTemplateOrPartial(); | 
|  | if (Decl *InstFromD = InstFrom.dyn_cast<ClassTemplateDecl *>()) { | 
|  | Record.AddDeclRef(InstFromD); | 
|  | } else { | 
|  | Record.AddDeclRef(cast<ClassTemplatePartialSpecializationDecl *>(InstFrom)); | 
|  | Record.AddTemplateArgumentList(&D->getTemplateInstantiationArgs()); | 
|  | } | 
|  |  | 
|  | Record.AddTemplateArgumentList(&D->getTemplateArgs()); | 
|  | Record.AddSourceLocation(D->getPointOfInstantiation()); | 
|  | Record.push_back(D->getSpecializationKind()); | 
|  | Record.push_back(D->hasStrictPackMatch()); | 
|  | Record.push_back(D->isCanonicalDecl()); | 
|  |  | 
|  | if (D->isCanonicalDecl()) { | 
|  | // When reading, we'll add it to the folding set of the following template. | 
|  | Record.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl()); | 
|  | } | 
|  |  | 
|  | bool ExplicitInstantiation = | 
|  | D->getTemplateSpecializationKind() == | 
|  | TSK_ExplicitInstantiationDeclaration || | 
|  | D->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition; | 
|  | Record.push_back(ExplicitInstantiation); | 
|  | if (ExplicitInstantiation) { | 
|  | Record.AddSourceLocation(D->getExternKeywordLoc()); | 
|  | Record.AddSourceLocation(D->getTemplateKeywordLoc()); | 
|  | } | 
|  |  | 
|  | const ASTTemplateArgumentListInfo *ArgsWritten = | 
|  | D->getTemplateArgsAsWritten(); | 
|  | Record.push_back(!!ArgsWritten); | 
|  | if (ArgsWritten) | 
|  | Record.AddASTTemplateArgumentListInfo(ArgsWritten); | 
|  |  | 
|  | // Mention the implicitly generated C++ deduction guide to make sure the | 
|  | // deduction guide will be rewritten as expected. | 
|  | // | 
|  | // FIXME: Would it be more efficient to add a callback register function | 
|  | // in sema to register the deduction guide? | 
|  | if (Writer.isWritingStdCXXNamedModules()) { | 
|  | auto Name = | 
|  | Record.getASTContext().DeclarationNames.getCXXDeductionGuideName( | 
|  | D->getSpecializedTemplate()); | 
|  | for (auto *DG : D->getDeclContext()->noload_lookup(Name)) | 
|  | Writer.GetDeclRef(DG->getCanonicalDecl()); | 
|  | } | 
|  |  | 
|  | Code = serialization::DECL_CLASS_TEMPLATE_SPECIALIZATION; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl( | 
|  | ClassTemplatePartialSpecializationDecl *D) { | 
|  | Record.AddTemplateParameterList(D->getTemplateParameters()); | 
|  |  | 
|  | VisitClassTemplateSpecializationDecl(D); | 
|  |  | 
|  | // These are read/set from/to the first declaration. | 
|  | if (D->getPreviousDecl() == nullptr) { | 
|  | Record.AddDeclRef(D->getInstantiatedFromMember()); | 
|  | Record.push_back(D->isMemberSpecialization()); | 
|  | } | 
|  |  | 
|  | Code = serialization::DECL_CLASS_TEMPLATE_PARTIAL_SPECIALIZATION; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitVarTemplateDecl(VarTemplateDecl *D) { | 
|  | VisitRedeclarableTemplateDecl(D); | 
|  |  | 
|  | if (D->isFirstDecl()) | 
|  | AddTemplateSpecializations(D); | 
|  | Code = serialization::DECL_VAR_TEMPLATE; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitVarTemplateSpecializationDecl( | 
|  | VarTemplateSpecializationDecl *D) { | 
|  | RegisterTemplateSpecialization(D->getSpecializedTemplate(), D); | 
|  |  | 
|  | llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *> | 
|  | InstFrom = D->getSpecializedTemplateOrPartial(); | 
|  | if (Decl *InstFromD = InstFrom.dyn_cast<VarTemplateDecl *>()) { | 
|  | Record.AddDeclRef(InstFromD); | 
|  | } else { | 
|  | Record.AddDeclRef(cast<VarTemplatePartialSpecializationDecl *>(InstFrom)); | 
|  | Record.AddTemplateArgumentList(&D->getTemplateInstantiationArgs()); | 
|  | } | 
|  |  | 
|  | bool ExplicitInstantiation = | 
|  | D->getTemplateSpecializationKind() == | 
|  | TSK_ExplicitInstantiationDeclaration || | 
|  | D->getTemplateSpecializationKind() == TSK_ExplicitInstantiationDefinition; | 
|  | Record.push_back(ExplicitInstantiation); | 
|  | if (ExplicitInstantiation) { | 
|  | Record.AddSourceLocation(D->getExternKeywordLoc()); | 
|  | Record.AddSourceLocation(D->getTemplateKeywordLoc()); | 
|  | } | 
|  |  | 
|  | const ASTTemplateArgumentListInfo *ArgsWritten = | 
|  | D->getTemplateArgsAsWritten(); | 
|  | Record.push_back(!!ArgsWritten); | 
|  | if (ArgsWritten) | 
|  | Record.AddASTTemplateArgumentListInfo(ArgsWritten); | 
|  |  | 
|  | Record.AddTemplateArgumentList(&D->getTemplateArgs()); | 
|  | Record.AddSourceLocation(D->getPointOfInstantiation()); | 
|  | Record.push_back(D->getSpecializationKind()); | 
|  | Record.push_back(D->IsCompleteDefinition); | 
|  |  | 
|  | VisitVarDecl(D); | 
|  |  | 
|  | Record.push_back(D->isCanonicalDecl()); | 
|  |  | 
|  | if (D->isCanonicalDecl()) { | 
|  | // When reading, we'll add it to the folding set of the following template. | 
|  | Record.AddDeclRef(D->getSpecializedTemplate()->getCanonicalDecl()); | 
|  | } | 
|  |  | 
|  | Code = serialization::DECL_VAR_TEMPLATE_SPECIALIZATION; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitVarTemplatePartialSpecializationDecl( | 
|  | VarTemplatePartialSpecializationDecl *D) { | 
|  | Record.AddTemplateParameterList(D->getTemplateParameters()); | 
|  |  | 
|  | VisitVarTemplateSpecializationDecl(D); | 
|  |  | 
|  | // These are read/set from/to the first declaration. | 
|  | if (D->getPreviousDecl() == nullptr) { | 
|  | Record.AddDeclRef(D->getInstantiatedFromMember()); | 
|  | Record.push_back(D->isMemberSpecialization()); | 
|  | } | 
|  |  | 
|  | Code = serialization::DECL_VAR_TEMPLATE_PARTIAL_SPECIALIZATION; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) { | 
|  | VisitRedeclarableTemplateDecl(D); | 
|  |  | 
|  | if (D->isFirstDecl()) | 
|  | AddTemplateSpecializations(D); | 
|  | Code = serialization::DECL_FUNCTION_TEMPLATE; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { | 
|  | Record.push_back(D->hasTypeConstraint()); | 
|  | VisitTypeDecl(D); | 
|  |  | 
|  | Record.push_back(D->wasDeclaredWithTypename()); | 
|  |  | 
|  | const TypeConstraint *TC = D->getTypeConstraint(); | 
|  | if (D->hasTypeConstraint()) | 
|  | Record.push_back(/*TypeConstraintInitialized=*/TC != nullptr); | 
|  | if (TC) { | 
|  | auto *CR = TC->getConceptReference(); | 
|  | Record.push_back(CR != nullptr); | 
|  | if (CR) | 
|  | Record.AddConceptReference(CR); | 
|  | Record.AddStmt(TC->getImmediatelyDeclaredConstraint()); | 
|  | Record.writeUnsignedOrNone(TC->getArgPackSubstIndex()); | 
|  | Record.writeUnsignedOrNone(D->getNumExpansionParameters()); | 
|  | } | 
|  |  | 
|  | bool OwnsDefaultArg = D->hasDefaultArgument() && | 
|  | !D->defaultArgumentWasInherited(); | 
|  | Record.push_back(OwnsDefaultArg); | 
|  | if (OwnsDefaultArg) | 
|  | Record.AddTemplateArgumentLoc(D->getDefaultArgument()); | 
|  |  | 
|  | if (!D->hasTypeConstraint() && !OwnsDefaultArg && | 
|  | D->getDeclContext() == D->getLexicalDeclContext() && | 
|  | !D->isInvalidDecl() && !D->hasAttrs() && | 
|  | !D->isTopLevelDeclInObjCContainer() && !D->isImplicit() && | 
|  | D->getDeclName().getNameKind() == DeclarationName::Identifier) | 
|  | AbbrevToUse = Writer.getDeclTemplateTypeParmAbbrev(); | 
|  |  | 
|  | Code = serialization::DECL_TEMPLATE_TYPE_PARM; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { | 
|  | // For an expanded parameter pack, record the number of expansion types here | 
|  | // so that it's easier for deserialization to allocate the right amount of | 
|  | // memory. | 
|  | Record.push_back(D->hasPlaceholderTypeConstraint()); | 
|  | if (D->isExpandedParameterPack()) | 
|  | Record.push_back(D->getNumExpansionTypes()); | 
|  |  | 
|  | VisitDeclaratorDecl(D); | 
|  | // TemplateParmPosition. | 
|  | Record.push_back(D->getDepth()); | 
|  | Record.push_back(D->getPosition()); | 
|  |  | 
|  | if (D->hasPlaceholderTypeConstraint()) | 
|  | Record.AddStmt(D->getPlaceholderTypeConstraint()); | 
|  |  | 
|  | if (D->isExpandedParameterPack()) { | 
|  | for (unsigned I = 0, N = D->getNumExpansionTypes(); I != N; ++I) { | 
|  | Record.AddTypeRef(D->getExpansionType(I)); | 
|  | Record.AddTypeSourceInfo(D->getExpansionTypeSourceInfo(I)); | 
|  | } | 
|  |  | 
|  | Code = serialization::DECL_EXPANDED_NON_TYPE_TEMPLATE_PARM_PACK; | 
|  | } else { | 
|  | // Rest of NonTypeTemplateParmDecl. | 
|  | Record.push_back(D->isParameterPack()); | 
|  | bool OwnsDefaultArg = D->hasDefaultArgument() && | 
|  | !D->defaultArgumentWasInherited(); | 
|  | Record.push_back(OwnsDefaultArg); | 
|  | if (OwnsDefaultArg) | 
|  | Record.AddTemplateArgumentLoc(D->getDefaultArgument()); | 
|  | Code = serialization::DECL_NON_TYPE_TEMPLATE_PARM; | 
|  | } | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { | 
|  | // For an expanded parameter pack, record the number of expansion types here | 
|  | // so that it's easier for deserialization to allocate the right amount of | 
|  | // memory. | 
|  | if (D->isExpandedParameterPack()) | 
|  | Record.push_back(D->getNumExpansionTemplateParameters()); | 
|  |  | 
|  | VisitTemplateDecl(D); | 
|  | Record.push_back(D->templateParameterKind()); | 
|  | Record.push_back(D->wasDeclaredWithTypename()); | 
|  | // TemplateParmPosition. | 
|  | Record.push_back(D->getDepth()); | 
|  | Record.push_back(D->getPosition()); | 
|  |  | 
|  | if (D->isExpandedParameterPack()) { | 
|  | for (unsigned I = 0, N = D->getNumExpansionTemplateParameters(); | 
|  | I != N; ++I) | 
|  | Record.AddTemplateParameterList(D->getExpansionTemplateParameters(I)); | 
|  | Code = serialization::DECL_EXPANDED_TEMPLATE_TEMPLATE_PARM_PACK; | 
|  | } else { | 
|  | // Rest of TemplateTemplateParmDecl. | 
|  | Record.push_back(D->isParameterPack()); | 
|  | bool OwnsDefaultArg = D->hasDefaultArgument() && | 
|  | !D->defaultArgumentWasInherited(); | 
|  | Record.push_back(OwnsDefaultArg); | 
|  | if (OwnsDefaultArg) | 
|  | Record.AddTemplateArgumentLoc(D->getDefaultArgument()); | 
|  | Code = serialization::DECL_TEMPLATE_TEMPLATE_PARM; | 
|  | } | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitTypeAliasTemplateDecl(TypeAliasTemplateDecl *D) { | 
|  | VisitRedeclarableTemplateDecl(D); | 
|  | Code = serialization::DECL_TYPE_ALIAS_TEMPLATE; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitStaticAssertDecl(StaticAssertDecl *D) { | 
|  | VisitDecl(D); | 
|  | Record.AddStmt(D->getAssertExpr()); | 
|  | Record.push_back(D->isFailed()); | 
|  | Record.AddStmt(D->getMessage()); | 
|  | Record.AddSourceLocation(D->getRParenLoc()); | 
|  | Code = serialization::DECL_STATIC_ASSERT; | 
|  | } | 
|  |  | 
|  | /// Emit the DeclContext part of a declaration context decl. | 
|  | void ASTDeclWriter::VisitDeclContext(DeclContext *DC) { | 
|  | static_assert(DeclContext::NumDeclContextBits == 13, | 
|  | "You need to update the serializer after you change the " | 
|  | "DeclContextBits"); | 
|  | LookupBlockOffsets Offsets; | 
|  |  | 
|  | if (Writer.isGeneratingReducedBMI() && isa<NamespaceDecl>(DC) && | 
|  | cast<NamespaceDecl>(DC)->isFromExplicitGlobalModule()) { | 
|  | // In reduced BMI, delay writing lexical and visible block for namespace | 
|  | // in the global module fragment. See the comments of DelayedNamespace for | 
|  | // details. | 
|  | Writer.DelayedNamespace.push_back(cast<NamespaceDecl>(DC)); | 
|  | } else { | 
|  | Offsets.LexicalOffset = | 
|  | Writer.WriteDeclContextLexicalBlock(Record.getASTContext(), DC); | 
|  | Writer.WriteDeclContextVisibleBlock(Record.getASTContext(), DC, Offsets); | 
|  | } | 
|  |  | 
|  | Record.AddLookupOffsets(Offsets); | 
|  | } | 
|  |  | 
|  | const Decl *ASTWriter::getFirstLocalDecl(const Decl *D) { | 
|  | assert(IsLocalDecl(D) && "expected a local declaration"); | 
|  |  | 
|  | const Decl *Canon = D->getCanonicalDecl(); | 
|  | if (IsLocalDecl(Canon)) | 
|  | return Canon; | 
|  |  | 
|  | const Decl *&CacheEntry = FirstLocalDeclCache[Canon]; | 
|  | if (CacheEntry) | 
|  | return CacheEntry; | 
|  |  | 
|  | for (const Decl *Redecl = D; Redecl; Redecl = Redecl->getPreviousDecl()) | 
|  | if (IsLocalDecl(Redecl)) | 
|  | D = Redecl; | 
|  | return CacheEntry = D; | 
|  | } | 
|  |  | 
|  | template <typename T> | 
|  | void ASTDeclWriter::VisitRedeclarable(Redeclarable<T> *D) { | 
|  | T *First = D->getFirstDecl(); | 
|  | T *MostRecent = First->getMostRecentDecl(); | 
|  | T *DAsT = static_cast<T *>(D); | 
|  | if (MostRecent != First) { | 
|  | assert(isRedeclarableDeclKind(DAsT->getKind()) && | 
|  | "Not considered redeclarable?"); | 
|  |  | 
|  | Record.AddDeclRef(First); | 
|  |  | 
|  | // Write out a list of local redeclarations of this declaration if it's the | 
|  | // first local declaration in the chain. | 
|  | const Decl *FirstLocal = Writer.getFirstLocalDecl(DAsT); | 
|  | if (DAsT == FirstLocal) { | 
|  | // Emit a list of all imported first declarations so that we can be sure | 
|  | // that all redeclarations visible to this module are before D in the | 
|  | // redecl chain. | 
|  | unsigned I = Record.size(); | 
|  | Record.push_back(0); | 
|  | if (Writer.Chain) | 
|  | AddFirstDeclFromEachModule(DAsT, /*IncludeLocal*/false); | 
|  | // This is the number of imported first declarations + 1. | 
|  | Record[I] = Record.size() - I; | 
|  |  | 
|  | // Collect the set of local redeclarations of this declaration, from | 
|  | // newest to oldest. | 
|  | ASTWriter::RecordData LocalRedecls; | 
|  | ASTRecordWriter LocalRedeclWriter(Record, LocalRedecls); | 
|  | for (const Decl *Prev = FirstLocal->getMostRecentDecl(); | 
|  | Prev != FirstLocal; Prev = Prev->getPreviousDecl()) | 
|  | if (!Prev->isFromASTFile()) | 
|  | LocalRedeclWriter.AddDeclRef(Prev); | 
|  |  | 
|  | // If we have any redecls, write them now as a separate record preceding | 
|  | // the declaration itself. | 
|  | if (LocalRedecls.empty()) | 
|  | Record.push_back(0); | 
|  | else | 
|  | Record.AddOffset(LocalRedeclWriter.Emit(LOCAL_REDECLARATIONS)); | 
|  | } else { | 
|  | Record.push_back(0); | 
|  | Record.AddDeclRef(FirstLocal); | 
|  | } | 
|  |  | 
|  | // Make sure that we serialize both the previous and the most-recent | 
|  | // declarations, which (transitively) ensures that all declarations in the | 
|  | // chain get serialized. | 
|  | // | 
|  | // FIXME: This is not correct; when we reach an imported declaration we | 
|  | // won't emit its previous declaration. | 
|  | (void)Writer.GetDeclRef(D->getPreviousDecl()); | 
|  | (void)Writer.GetDeclRef(MostRecent); | 
|  | } else { | 
|  | // We use the sentinel value 0 to indicate an only declaration. | 
|  | Record.push_back(0); | 
|  | } | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitHLSLBufferDecl(HLSLBufferDecl *D) { | 
|  | VisitNamedDecl(D); | 
|  | VisitDeclContext(D); | 
|  | Record.push_back(D->isCBuffer()); | 
|  | Record.AddSourceLocation(D->getLocStart()); | 
|  | Record.AddSourceLocation(D->getLBraceLoc()); | 
|  | Record.AddSourceLocation(D->getRBraceLoc()); | 
|  |  | 
|  | Code = serialization::DECL_HLSL_BUFFER; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitOMPThreadPrivateDecl(OMPThreadPrivateDecl *D) { | 
|  | Record.writeOMPChildren(D->Data); | 
|  | VisitDecl(D); | 
|  | Code = serialization::DECL_OMP_THREADPRIVATE; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitOMPAllocateDecl(OMPAllocateDecl *D) { | 
|  | Record.writeOMPChildren(D->Data); | 
|  | VisitDecl(D); | 
|  | Code = serialization::DECL_OMP_ALLOCATE; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitOMPRequiresDecl(OMPRequiresDecl *D) { | 
|  | Record.writeOMPChildren(D->Data); | 
|  | VisitDecl(D); | 
|  | Code = serialization::DECL_OMP_REQUIRES; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitOMPDeclareReductionDecl(OMPDeclareReductionDecl *D) { | 
|  | static_assert(DeclContext::NumOMPDeclareReductionDeclBits == 15, | 
|  | "You need to update the serializer after you change the " | 
|  | "NumOMPDeclareReductionDeclBits"); | 
|  |  | 
|  | VisitValueDecl(D); | 
|  | Record.AddSourceLocation(D->getBeginLoc()); | 
|  | Record.AddStmt(D->getCombinerIn()); | 
|  | Record.AddStmt(D->getCombinerOut()); | 
|  | Record.AddStmt(D->getCombiner()); | 
|  | Record.AddStmt(D->getInitOrig()); | 
|  | Record.AddStmt(D->getInitPriv()); | 
|  | Record.AddStmt(D->getInitializer()); | 
|  | Record.push_back(llvm::to_underlying(D->getInitializerKind())); | 
|  | Record.AddDeclRef(D->getPrevDeclInScope()); | 
|  | Code = serialization::DECL_OMP_DECLARE_REDUCTION; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) { | 
|  | Record.writeOMPChildren(D->Data); | 
|  | VisitValueDecl(D); | 
|  | Record.AddDeclarationName(D->getVarName()); | 
|  | Record.AddDeclRef(D->getPrevDeclInScope()); | 
|  | Code = serialization::DECL_OMP_DECLARE_MAPPER; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitOMPCapturedExprDecl(OMPCapturedExprDecl *D) { | 
|  | VisitVarDecl(D); | 
|  | Code = serialization::DECL_OMP_CAPTUREDEXPR; | 
|  | } | 
|  |  | 
|  | void ASTDeclWriter::VisitOpenACCDeclareDecl(OpenACCDeclareDecl *D) { | 
|  | Record.writeUInt32(D->clauses().size()); | 
|  | VisitDecl(D); | 
|  | Record.writeEnum(D->DirKind); | 
|  | Record.AddSourceLocation(D->DirectiveLoc); | 
|  | Record.AddSourceLocation(D->EndLoc); | 
|  | Record.writeOpenACCClauseList(D->clauses()); | 
|  | Code = serialization::DECL_OPENACC_DECLARE; | 
|  | } | 
|  | void ASTDeclWriter::VisitOpenACCRoutineDecl(OpenACCRoutineDecl *D) { | 
|  | Record.writeUInt32(D->clauses().size()); | 
|  | VisitDecl(D); | 
|  | Record.writeEnum(D->DirKind); | 
|  | Record.AddSourceLocation(D->DirectiveLoc); | 
|  | Record.AddSourceLocation(D->EndLoc); | 
|  | Record.AddSourceRange(D->ParensLoc); | 
|  | Record.AddStmt(D->FuncRef); | 
|  | Record.writeOpenACCClauseList(D->clauses()); | 
|  | Code = serialization::DECL_OPENACC_ROUTINE; | 
|  | } | 
|  |  | 
|  | //===----------------------------------------------------------------------===// | 
|  | // ASTWriter Implementation | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | namespace { | 
|  | template <FunctionDecl::TemplatedKind Kind> | 
|  | std::shared_ptr<llvm::BitCodeAbbrev> | 
|  | getFunctionDeclAbbrev(serialization::DeclCode Code) { | 
|  | using namespace llvm; | 
|  |  | 
|  | auto Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(Code)); | 
|  | // RedeclarableDecl | 
|  | Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl | 
|  | Abv->Add(BitCodeAbbrevOp(Kind)); | 
|  | if constexpr (Kind == FunctionDecl::TK_NonTemplate) { | 
|  |  | 
|  | } else if constexpr (Kind == FunctionDecl::TK_FunctionTemplate) { | 
|  | // DescribedFunctionTemplate | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); | 
|  | } else if constexpr (Kind == FunctionDecl::TK_DependentNonTemplate) { | 
|  | // Instantiated From Decl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); | 
|  | } else if constexpr (Kind == FunctionDecl::TK_MemberSpecialization) { | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InstantiatedFrom | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, | 
|  | 3)); // TemplateSpecializationKind | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Specialized Location | 
|  | } else if constexpr (Kind == | 
|  | FunctionDecl::TK_FunctionTemplateSpecialization) { | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Template | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, | 
|  | 3)); // TemplateSpecializationKind | 
|  | Abv->Add(BitCodeAbbrevOp(1)); // Template Argument Size | 
|  | Abv->Add(BitCodeAbbrevOp(TemplateArgument::Type)); // Template Argument Kind | 
|  | Abv->Add( | 
|  | BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Template Argument Type | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Is Defaulted | 
|  | Abv->Add(BitCodeAbbrevOp(0)); // TemplateArgumentsAsWritten | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation | 
|  | Abv->Add(BitCodeAbbrevOp(0)); | 
|  | Abv->Add( | 
|  | BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Canonical Decl of template | 
|  | } else if constexpr (Kind == FunctionDecl:: | 
|  | TK_DependentFunctionTemplateSpecialization) { | 
|  | // Candidates of specialization | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); | 
|  | Abv->Add(BitCodeAbbrevOp(0)); // TemplateArgumentsAsWritten | 
|  | } else { | 
|  | llvm_unreachable("Unknown templated kind?"); | 
|  | } | 
|  | // Decl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, | 
|  | 8)); // Packed DeclBits: ModuleOwnershipKind, | 
|  | // isUsed, isReferenced,  AccessSpecifier, | 
|  | // isImplicit | 
|  | // | 
|  | // The following bits should be 0: | 
|  | // HasStandaloneLexicalDC, HasAttrs, | 
|  | // TopLevelDeclInObjCContainer, | 
|  | // isInvalidDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID | 
|  | // NamedDecl | 
|  | Abv->Add(BitCodeAbbrevOp(DeclarationName::Identifier)); // NameKind | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));     // Identifier | 
|  | Abv->Add(BitCodeAbbrevOp(0));                           // AnonDeclNumber | 
|  | // ValueDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type | 
|  | // DeclaratorDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerLocStart | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // HasExtInfo | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType | 
|  | // FunctionDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 11)); // IDNS | 
|  | Abv->Add(BitCodeAbbrevOp( | 
|  | BitCodeAbbrevOp::Fixed, | 
|  | 28)); // Packed Function Bits: StorageClass, Inline, InlineSpecified, | 
|  | // VirtualAsWritten, Pure, HasInheritedProto, HasWrittenProto, | 
|  | // Deleted, Trivial, TrivialForCall, Defaulted, ExplicitlyDefaulted, | 
|  | // IsIneligibleOrNotSelected, ImplicitReturnZero, Constexpr, | 
|  | // UsesSEHTry, SkippedBody, MultiVersion, LateParsed, | 
|  | // FriendConstraintRefersToEnclosingTemplate, Linkage, | 
|  | // ShouldSkipCheckingODR | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));    // LocEnd | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // ODRHash | 
|  | // This Array slurps the rest of the record. Fortunately we want to encode | 
|  | // (nearly) all the remaining (variable number of) fields in the same way. | 
|  | // | 
|  | // This is: | 
|  | //         NumParams and Params[] from FunctionDecl, and | 
|  | //         NumOverriddenMethods, OverriddenMethods[] from CXXMethodDecl. | 
|  | // | 
|  | //  Add an AbbrevOp for 'size then elements' and use it here. | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); | 
|  | return Abv; | 
|  | } | 
|  |  | 
|  | template <FunctionDecl::TemplatedKind Kind> | 
|  | std::shared_ptr<llvm::BitCodeAbbrev> getCXXMethodAbbrev() { | 
|  | return getFunctionDeclAbbrev<Kind>(serialization::DECL_CXX_METHOD); | 
|  | } | 
|  | } // namespace | 
|  |  | 
|  | void ASTWriter::WriteDeclAbbrevs() { | 
|  | using namespace llvm; | 
|  |  | 
|  | std::shared_ptr<BitCodeAbbrev> Abv; | 
|  |  | 
|  | // Abbreviation for DECL_FIELD | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::DECL_FIELD)); | 
|  | // Decl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, | 
|  | 7)); // Packed DeclBits: ModuleOwnershipKind, | 
|  | // isUsed, isReferenced,  AccessSpecifier, | 
|  | // | 
|  | // The following bits should be 0: | 
|  | // isImplicit, HasStandaloneLexicalDC, HasAttrs, | 
|  | // TopLevelDeclInObjCContainer, | 
|  | // isInvalidDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID | 
|  | // NamedDecl | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber | 
|  | // ValueDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type | 
|  | // DeclaratorDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // hasExtInfo | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType | 
|  | // FieldDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // StorageKind | 
|  | // Type Source Info | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc | 
|  | DeclFieldAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | // Abbreviation for DECL_OBJC_IVAR | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::DECL_OBJC_IVAR)); | 
|  | // Decl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, | 
|  | 12)); // Packed DeclBits: HasStandaloneLexicalDC, | 
|  | // isInvalidDecl, HasAttrs, isImplicit, isUsed, | 
|  | // isReferenced, TopLevelDeclInObjCContainer, | 
|  | // AccessSpecifier, ModuleOwnershipKind | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID | 
|  | // NamedDecl | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber | 
|  | // ValueDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type | 
|  | // DeclaratorDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // hasExtInfo | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType | 
|  | // FieldDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isMutable | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // InitStyle | 
|  | // ObjC Ivar | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getAccessControl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getSynthesize | 
|  | // Type Source Info | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc | 
|  | DeclObjCIvarAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | // Abbreviation for DECL_ENUM | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::DECL_ENUM)); | 
|  | // Redeclarable | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration | 
|  | // Decl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, | 
|  | 7)); // Packed DeclBits: ModuleOwnershipKind, | 
|  | // isUsed, isReferenced,  AccessSpecifier, | 
|  | // | 
|  | // The following bits should be 0: | 
|  | // isImplicit, HasStandaloneLexicalDC, HasAttrs, | 
|  | // TopLevelDeclInObjCContainer, | 
|  | // isInvalidDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID | 
|  | // NamedDecl | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber | 
|  | // TypeDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location | 
|  | // TagDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // IdentifierNamespace | 
|  | Abv->Add(BitCodeAbbrevOp( | 
|  | BitCodeAbbrevOp::Fixed, | 
|  | 9)); // Packed Tag Decl Bits: getTagKind, isCompleteDefinition, | 
|  | // EmbeddedInDeclarator, IsFreeStanding, | 
|  | // isCompleteDefinitionRequired, ExtInfoKind | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // SourceLocation | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // SourceLocation | 
|  | // EnumDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // AddTypeRef | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // IntegerType | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // getPromotionType | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 20)); // Enum Decl Bits | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32));// ODRHash | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // InstantiatedMembEnum | 
|  | // DC | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // LexicalOffset | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // VisibleOffset | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // ModuleLocalOffset | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // TULocalOffset | 
|  | DeclEnumAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | // Abbreviation for DECL_RECORD | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::DECL_RECORD)); | 
|  | // Redeclarable | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration | 
|  | // Decl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, | 
|  | 7)); // Packed DeclBits: ModuleOwnershipKind, | 
|  | // isUsed, isReferenced,  AccessSpecifier, | 
|  | // | 
|  | // The following bits should be 0: | 
|  | // isImplicit, HasStandaloneLexicalDC, HasAttrs, | 
|  | // TopLevelDeclInObjCContainer, | 
|  | // isInvalidDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID | 
|  | // NamedDecl | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber | 
|  | // TypeDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location | 
|  | // TagDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // IdentifierNamespace | 
|  | Abv->Add(BitCodeAbbrevOp( | 
|  | BitCodeAbbrevOp::Fixed, | 
|  | 9)); // Packed Tag Decl Bits: getTagKind, isCompleteDefinition, | 
|  | // EmbeddedInDeclarator, IsFreeStanding, | 
|  | // isCompleteDefinitionRequired, ExtInfoKind | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // SourceLocation | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // SourceLocation | 
|  | // RecordDecl | 
|  | Abv->Add(BitCodeAbbrevOp( | 
|  | BitCodeAbbrevOp::Fixed, | 
|  | 14)); // Packed Record Decl Bits: FlexibleArrayMember, | 
|  | // AnonymousStructUnion, hasObjectMember, hasVolatileMember, | 
|  | // isNonTrivialToPrimitiveDefaultInitialize, | 
|  | // isNonTrivialToPrimitiveCopy, isNonTrivialToPrimitiveDestroy, | 
|  | // hasNonTrivialToPrimitiveDefaultInitializeCUnion, | 
|  | // hasNonTrivialToPrimitiveDestructCUnion, | 
|  | // hasNonTrivialToPrimitiveCopyCUnion, | 
|  | // hasUninitializedExplicitInitFields, isParamDestroyedInCallee, | 
|  | // getArgPassingRestrictions | 
|  | // ODRHash | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 26)); | 
|  |  | 
|  | // DC | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // LexicalOffset | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // VisibleOffset | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // ModuleLocalOffset | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));   // TULocalOffset | 
|  | DeclRecordAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | // Abbreviation for DECL_PARM_VAR | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::DECL_PARM_VAR)); | 
|  | // Redeclarable | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration | 
|  | // Decl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, | 
|  | 8)); // Packed DeclBits: ModuleOwnershipKind, isUsed, | 
|  | // isReferenced, AccessSpecifier, | 
|  | // HasStandaloneLexicalDC, HasAttrs, isImplicit, | 
|  | // TopLevelDeclInObjCContainer, | 
|  | // isInvalidDecl, | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID | 
|  | // NamedDecl | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber | 
|  | // ValueDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type | 
|  | // DeclaratorDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // hasExtInfo | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType | 
|  | // VarDecl | 
|  | Abv->Add( | 
|  | BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, | 
|  | 12)); // Packed Var Decl bits: SClass, TSCSpec, InitStyle, | 
|  | // isARCPseudoStrong, Linkage, ModulesCodegen | 
|  | Abv->Add(BitCodeAbbrevOp(0));                          // VarKind (local enum) | 
|  | // ParmVarDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ScopeIndex | 
|  | Abv->Add(BitCodeAbbrevOp( | 
|  | BitCodeAbbrevOp::Fixed, | 
|  | 19)); // Packed Parm Var Decl bits: IsObjCMethodParameter, ScopeDepth, | 
|  | // ObjCDeclQualifier, KNRPromoted, | 
|  | // HasInheritedDefaultArg, HasUninstantiatedDefaultArg | 
|  | // Type Source Info | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc | 
|  | DeclParmVarAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | // Abbreviation for DECL_TYPEDEF | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::DECL_TYPEDEF)); | 
|  | // Redeclarable | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration | 
|  | // Decl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, | 
|  | 7)); // Packed DeclBits: ModuleOwnershipKind, | 
|  | // isReferenced, isUsed, AccessSpecifier. Other | 
|  | // higher bits should be 0: isImplicit, | 
|  | // HasStandaloneLexicalDC, HasAttrs, | 
|  | // TopLevelDeclInObjCContainer, isInvalidDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID | 
|  | // NamedDecl | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber | 
|  | // TypeDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref | 
|  | // TypedefDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc | 
|  | DeclTypedefAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | // Abbreviation for DECL_VAR | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::DECL_VAR)); | 
|  | // Redeclarable | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // No redeclaration | 
|  | // Decl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, | 
|  | 12)); // Packed DeclBits: HasStandaloneLexicalDC, | 
|  | // isInvalidDecl, HasAttrs, isImplicit, isUsed, | 
|  | // isReferenced, TopLevelDeclInObjCContainer, | 
|  | // AccessSpecifier, ModuleOwnershipKind | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID | 
|  | // NamedDecl | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // AnonDeclNumber | 
|  | // ValueDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type | 
|  | // DeclaratorDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // InnerStartLoc | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // hasExtInfo | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TSIType | 
|  | // VarDecl | 
|  | Abv->Add(BitCodeAbbrevOp( | 
|  | BitCodeAbbrevOp::Fixed, | 
|  | 22)); // Packed Var Decl bits:  Linkage, ModulesCodegen, | 
|  | // SClass, TSCSpec, InitStyle, | 
|  | // isARCPseudoStrong, IsThisDeclarationADemotedDefinition, | 
|  | // isExceptionVariable, isNRVOVariable, isCXXForRangeDecl, | 
|  | // isInline, isInlineSpecified, isConstexpr, | 
|  | // isInitCapture, isPrevDeclInSameScope, hasInitWithSideEffects, | 
|  | // EscapingByref, HasDeducedType, ImplicitParamKind, isObjCForDecl | 
|  | // IsCXXForRangeImplicitVar | 
|  | Abv->Add(BitCodeAbbrevOp(0));                         // VarKind (local enum) | 
|  | // Type Source Info | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Array)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // TypeLoc | 
|  | DeclVarAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | // Abbreviation for DECL_CXX_METHOD | 
|  | DeclCXXMethodAbbrev = | 
|  | Stream.EmitAbbrev(getCXXMethodAbbrev<FunctionDecl::TK_NonTemplate>()); | 
|  | DeclTemplateCXXMethodAbbrev = Stream.EmitAbbrev( | 
|  | getCXXMethodAbbrev<FunctionDecl::TK_FunctionTemplate>()); | 
|  | DeclDependentNonTemplateCXXMethodAbbrev = Stream.EmitAbbrev( | 
|  | getCXXMethodAbbrev<FunctionDecl::TK_DependentNonTemplate>()); | 
|  | DeclMemberSpecializedCXXMethodAbbrev = Stream.EmitAbbrev( | 
|  | getCXXMethodAbbrev<FunctionDecl::TK_MemberSpecialization>()); | 
|  | DeclTemplateSpecializedCXXMethodAbbrev = Stream.EmitAbbrev( | 
|  | getCXXMethodAbbrev<FunctionDecl::TK_FunctionTemplateSpecialization>()); | 
|  | DeclDependentSpecializationCXXMethodAbbrev = Stream.EmitAbbrev( | 
|  | getCXXMethodAbbrev< | 
|  | FunctionDecl::TK_DependentFunctionTemplateSpecialization>()); | 
|  |  | 
|  | // Abbreviation for DECL_TEMPLATE_TYPE_PARM | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::DECL_TEMPLATE_TYPE_PARM)); | 
|  | Abv->Add(BitCodeAbbrevOp(0)); // hasTypeConstraint | 
|  | // Decl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, | 
|  | 7)); // Packed DeclBits: ModuleOwnershipKind, | 
|  | // isReferenced, isUsed, AccessSpecifier. Other | 
|  | // higher bits should be 0: isImplicit, | 
|  | // HasStandaloneLexicalDC, HasAttrs, | 
|  | // TopLevelDeclInObjCContainer, isInvalidDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID | 
|  | // NamedDecl | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name | 
|  | Abv->Add(BitCodeAbbrevOp(0)); | 
|  | // TypeDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type Ref | 
|  | // TemplateTypeParmDecl | 
|  | Abv->Add( | 
|  | BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // wasDeclaredWithTypename | 
|  | Abv->Add(BitCodeAbbrevOp(0));                    // OwnsDefaultArg | 
|  | DeclTemplateTypeParmAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | // Abbreviation for DECL_USING_SHADOW | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::DECL_USING_SHADOW)); | 
|  | // Redeclarable | 
|  | Abv->Add(BitCodeAbbrevOp(0)); // No redeclaration | 
|  | // Decl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, | 
|  | 12)); // Packed DeclBits: HasStandaloneLexicalDC, | 
|  | // isInvalidDecl, HasAttrs, isImplicit, isUsed, | 
|  | // isReferenced, TopLevelDeclInObjCContainer, | 
|  | // AccessSpecifier, ModuleOwnershipKind | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SubmoduleID | 
|  | // NamedDecl | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // NameKind = Identifier | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Name | 
|  | Abv->Add(BitCodeAbbrevOp(0)); | 
|  | // UsingShadowDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));    // TargetDecl | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 11)); // IDNS | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6));    // UsingOrNextShadow | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, | 
|  | 6)); // InstantiatedFromUsingShadowDecl | 
|  | DeclUsingShadowAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | // Abbreviation for EXPR_DECL_REF | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::EXPR_DECL_REF)); | 
|  | // Stmt | 
|  | //  Expr | 
|  | //  PackingBits: DependenceKind, ValueKind. ObjectKind should be 0. | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 7)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type | 
|  | // DeclRefExpr | 
|  | // Packing Bits: , HadMultipleCandidates, RefersToEnclosingVariableOrCapture, | 
|  | // IsImmediateEscalating, NonOdrUseReason. | 
|  | // GetDeclFound, HasQualifier and ExplicitTemplateArgs should be 0. | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclRef | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location | 
|  | DeclRefExprAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | // Abbreviation for EXPR_INTEGER_LITERAL | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::EXPR_INTEGER_LITERAL)); | 
|  | //Stmt | 
|  | // Expr | 
|  | // DependenceKind, ValueKind, ObjectKind | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type | 
|  | // Integer Literal | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location | 
|  | Abv->Add(BitCodeAbbrevOp(32));                      // Bit Width | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Value | 
|  | IntegerLiteralAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | // Abbreviation for EXPR_CHARACTER_LITERAL | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::EXPR_CHARACTER_LITERAL)); | 
|  | //Stmt | 
|  | // Expr | 
|  | // DependenceKind, ValueKind, ObjectKind | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type | 
|  | // Character Literal | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getValue | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Location | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // getKind | 
|  | CharacterLiteralAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | // Abbreviation for EXPR_IMPLICIT_CAST | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::EXPR_IMPLICIT_CAST)); | 
|  | // Stmt | 
|  | // Expr | 
|  | // Packing Bits: DependenceKind, ValueKind, ObjectKind, | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type | 
|  | // CastExpr | 
|  | Abv->Add(BitCodeAbbrevOp(0)); // PathSize | 
|  | // Packing Bits: CastKind, StoredFPFeatures, isPartOfExplicitCast | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 9)); | 
|  | // ImplicitCastExpr | 
|  | ExprImplicitCastAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | // Abbreviation for EXPR_BINARY_OPERATOR | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::EXPR_BINARY_OPERATOR)); | 
|  | // Stmt | 
|  | // Expr | 
|  | // Packing Bits: DependenceKind. ValueKind and ObjectKind should | 
|  | // be 0 in this case. | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type | 
|  | // BinaryOperator | 
|  | Abv->Add( | 
|  | BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpCode and HasFPFeatures | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location | 
|  | BinaryOperatorAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | // Abbreviation for EXPR_COMPOUND_ASSIGN_OPERATOR | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::EXPR_COMPOUND_ASSIGN_OPERATOR)); | 
|  | // Stmt | 
|  | // Expr | 
|  | // Packing Bits: DependenceKind. ValueKind and ObjectKind should | 
|  | // be 0 in this case. | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 5)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type | 
|  | // BinaryOperator | 
|  | // Packing Bits: OpCode. The HasFPFeatures bit should be 0 | 
|  | Abv->Add( | 
|  | BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // OpCode and HasFPFeatures | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location | 
|  | // CompoundAssignOperator | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LHSType | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Result Type | 
|  | CompoundAssignOperatorAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | // Abbreviation for EXPR_CALL | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::EXPR_CALL)); | 
|  | // Stmt | 
|  | // Expr | 
|  | // Packing Bits: DependenceKind, ValueKind, ObjectKind, | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type | 
|  | // CallExpr | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // NumArgs | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // ADLCallKind | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location | 
|  | CallExprAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | // Abbreviation for EXPR_CXX_OPERATOR_CALL | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::EXPR_CXX_OPERATOR_CALL)); | 
|  | // Stmt | 
|  | // Expr | 
|  | // Packing Bits: DependenceKind, ValueKind, ObjectKind, | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type | 
|  | // CallExpr | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // NumArgs | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // ADLCallKind | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location | 
|  | // CXXOperatorCallExpr | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Operator Kind | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location | 
|  | CXXOperatorCallExprAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | // Abbreviation for EXPR_CXX_MEMBER_CALL | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::EXPR_CXX_MEMBER_CALL)); | 
|  | // Stmt | 
|  | // Expr | 
|  | // Packing Bits: DependenceKind, ValueKind, ObjectKind, | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 10)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type | 
|  | // CallExpr | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // NumArgs | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // ADLCallKind | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location | 
|  | // CXXMemberCallExpr | 
|  | CXXMemberCallExprAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | // Abbreviation for STMT_COMPOUND | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::STMT_COMPOUND)); | 
|  | // Stmt | 
|  | // CompoundStmt | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Num Stmts | 
|  | Abv->Add(BitCodeAbbrevOp(0));                       // hasStoredFPFeatures | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Source Location | 
|  | CompoundStmtAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_LEXICAL)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); | 
|  | DeclContextLexicalAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_VISIBLE)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); | 
|  | DeclContextVisibleLookupAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_MODULE_LOCAL_VISIBLE)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); | 
|  | DeclModuleLocalVisibleLookupAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_TU_LOCAL_VISIBLE)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); | 
|  | DeclTULocalLookupAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::DECL_SPECIALIZATIONS)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); | 
|  | DeclSpecializationsAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  |  | 
|  | Abv = std::make_shared<BitCodeAbbrev>(); | 
|  | Abv->Add(BitCodeAbbrevOp(serialization::DECL_PARTIAL_SPECIALIZATIONS)); | 
|  | Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); | 
|  | DeclPartialSpecializationsAbbrev = Stream.EmitAbbrev(std::move(Abv)); | 
|  | } | 
|  |  | 
|  | /// isRequiredDecl - Check if this is a "required" Decl, which must be seen by | 
|  | /// consumers of the AST. | 
|  | /// | 
|  | /// Such decls will always be deserialized from the AST file, so we would like | 
|  | /// this to be as restrictive as possible. Currently the predicate is driven by | 
|  | /// code generation requirements, if other clients have a different notion of | 
|  | /// what is "required" then we may have to consider an alternate scheme where | 
|  | /// clients can iterate over the top-level decls and get information on them, | 
|  | /// without necessary deserializing them. We could explicitly require such | 
|  | /// clients to use a separate API call to "realize" the decl. This should be | 
|  | /// relatively painless since they would presumably only do it for top-level | 
|  | /// decls. | 
|  | static bool isRequiredDecl(const Decl *D, ASTContext &Context, | 
|  | Module *WritingModule) { | 
|  | // Named modules have different semantics than header modules. Every named | 
|  | // module units owns a translation unit. So the importer of named modules | 
|  | // doesn't need to deserilize everything ahead of time. | 
|  | if (WritingModule && WritingModule->isNamedModule()) { | 
|  | // The PragmaCommentDecl and PragmaDetectMismatchDecl are MSVC's extension. | 
|  | // And the behavior of MSVC for such cases will leak this to the module | 
|  | // users. Given pragma is not a standard thing, the compiler has the space | 
|  | // to do their own decision. Let's follow MSVC here. | 
|  | if (isa<PragmaCommentDecl, PragmaDetectMismatchDecl>(D)) | 
|  | return true; | 
|  | return false; | 
|  | } | 
|  |  | 
|  | // An ObjCMethodDecl is never considered as "required" because its | 
|  | // implementation container always is. | 
|  |  | 
|  | // File scoped assembly or obj-c or OMP declare target implementation must be | 
|  | // seen. | 
|  | if (isa<FileScopeAsmDecl, TopLevelStmtDecl, ObjCImplDecl>(D)) | 
|  | return true; | 
|  |  | 
|  | if (WritingModule && isPartOfPerModuleInitializer(D)) { | 
|  | // These declarations are part of the module initializer, and are emitted | 
|  | // if and when the module is imported, rather than being emitted eagerly. | 
|  | return false; | 
|  | } | 
|  |  | 
|  | return Context.DeclMustBeEmitted(D); | 
|  | } | 
|  |  | 
|  | void ASTWriter::WriteDecl(ASTContext &Context, Decl *D) { | 
|  | PrettyDeclStackTraceEntry CrashInfo(Context, D, SourceLocation(), | 
|  | "serializing"); | 
|  |  | 
|  | // Determine the ID for this declaration. | 
|  | LocalDeclID ID; | 
|  | assert(!D->isFromASTFile() && "should not be emitting imported decl"); | 
|  | LocalDeclID &IDR = DeclIDs[D]; | 
|  | if (IDR.isInvalid()) | 
|  | IDR = NextDeclID++; | 
|  |  | 
|  | ID = IDR; | 
|  |  | 
|  | assert(ID >= FirstDeclID && "invalid decl ID"); | 
|  |  | 
|  | RecordData Record; | 
|  | ASTDeclWriter W(*this, Context, Record, GeneratingReducedBMI); | 
|  |  | 
|  | // Build a record for this declaration | 
|  | W.Visit(D); | 
|  |  | 
|  | // Emit this declaration to the bitstream. | 
|  | uint64_t Offset = W.Emit(D); | 
|  |  | 
|  | // Record the offset for this declaration | 
|  | SourceLocation Loc = D->getLocation(); | 
|  | SourceLocationEncoding::RawLocEncoding RawLoc = | 
|  | getRawSourceLocationEncoding(getAdjustedLocation(Loc)); | 
|  |  | 
|  | unsigned Index = ID.getRawValue() - FirstDeclID.getRawValue(); | 
|  | if (DeclOffsets.size() == Index) | 
|  | DeclOffsets.emplace_back(RawLoc, Offset, DeclTypesBlockStartOffset); | 
|  | else if (DeclOffsets.size() < Index) { | 
|  | // FIXME: Can/should this happen? | 
|  | DeclOffsets.resize(Index+1); | 
|  | DeclOffsets[Index].setRawLoc(RawLoc); | 
|  | DeclOffsets[Index].setBitOffset(Offset, DeclTypesBlockStartOffset); | 
|  | } else { | 
|  | llvm_unreachable("declarations should be emitted in ID order"); | 
|  | } | 
|  |  | 
|  | SourceManager &SM = Context.getSourceManager(); | 
|  | if (Loc.isValid() && SM.isLocalSourceLocation(Loc)) | 
|  | associateDeclWithFile(D, ID); | 
|  |  | 
|  | // Note declarations that should be deserialized eagerly so that we can add | 
|  | // them to a record in the AST file later. | 
|  | if (isRequiredDecl(D, Context, WritingModule)) | 
|  | AddDeclRef(D, EagerlyDeserializedDecls); | 
|  | } | 
|  |  | 
|  | void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) { | 
|  | // Switch case IDs are per function body. | 
|  | Writer->ClearSwitchCaseIDs(); | 
|  |  | 
|  | assert(FD->doesThisDeclarationHaveABody()); | 
|  | bool ModulesCodegen = shouldFunctionGenerateHereOnly(FD); | 
|  | Record->push_back(ModulesCodegen); | 
|  | if (ModulesCodegen) | 
|  | Writer->AddDeclRef(FD, Writer->ModularCodegenDecls); | 
|  | if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) { | 
|  | Record->push_back(CD->getNumCtorInitializers()); | 
|  | if (CD->getNumCtorInitializers()) | 
|  | AddCXXCtorInitializers(llvm::ArrayRef(CD->init_begin(), CD->init_end())); | 
|  | } | 
|  | AddStmt(FD->getBody()); | 
|  | } |