| //===--- 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/DeclContextInternals.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; |
| |
| //===----------------------------------------------------------------------===// |
| // Declaration serialization |
| //===----------------------------------------------------------------------===// |
| |
| namespace clang { |
| class ASTDeclWriter : public DeclVisitor<ASTDeclWriter, void> { |
| ASTWriter &Writer; |
| ASTContext &Context; |
| ASTRecordWriter Record; |
| |
| serialization::DeclCode Code; |
| unsigned AbbrevToUse; |
| |
| public: |
| ASTDeclWriter(ASTWriter &Writer, ASTContext &Context, |
| ASTWriter::RecordDataImpl &Record) |
| : Writer(Writer), Context(Context), Record(Writer, Record), |
| Code((serialization::DeclCode)0), AbbrevToUse(0) {} |
| |
| 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 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 VisitClassScopeFunctionSpecializationDecl( |
| ClassScopeFunctionSpecializationDecl *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 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 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 VisitUsingPackDecl(UsingPackDecl *D); |
| void VisitUsingShadowDecl(UsingShadowDecl *D); |
| void VisitConstructorUsingShadowDecl(ConstructorUsingShadowDecl *D); |
| void VisitLinkageSpecDecl(LinkageSpecDecl *D); |
| void VisitExportDecl(ExportDecl *D); |
| void VisitFileScopeAsmDecl(FileScopeAsmDecl *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 VisitCapturedDecl(CapturedDecl *D); |
| void VisitEmptyDecl(EmptyDecl *D); |
| void VisitLifetimeExtendedTemporaryDecl(LifetimeExtendedTemporaryDecl *D); |
| |
| void VisitDeclContext(DeclContext *DC); |
| template <typename T> void VisitRedeclarable(Redeclarable<T> *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); |
| |
| /// 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()); |
| } |
| |
| /// 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; |
| // 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; |
| } |
| for (const auto &F : Firsts) |
| Record.AddDeclRef(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; |
| } |
| ArrayRef<Decl> getPartialSpecializations(FunctionTemplateDecl::Common *) { |
| return None; |
| } |
| |
| 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 != Writer.Context->getExternalSource() && |
| Common->LazySpecializations) { |
| D->LoadLazySpecializations(); |
| assert(!Common->LazySpecializations); |
| } |
| |
| ArrayRef<DeclID> LazySpecializations; |
| if (auto *LS = Common->LazySpecializations) |
| LazySpecializations = llvm::makeArrayRef(LS + 1, LS[0]); |
| |
| // Add a slot to the record for the number of specializations. |
| unsigned I = Record.size(); |
| Record.push_back(0); |
| |
| // AddFirstDeclFromEachModule might trigger deserialization, invalidating |
| // *Specializations iterators. |
| llvm::SmallVector<const Decl*, 16> Specs; |
| for (auto &Entry : Common->Specializations) |
| Specs.push_back(getSpecializationDecl(Entry)); |
| for (auto &Entry : getPartialSpecializations(Common)) |
| Specs.push_back(getSpecializationDecl(Entry)); |
| |
| for (auto *D : Specs) { |
| assert(D->isCanonicalDecl() && "non-canonical decl in set"); |
| AddFirstDeclFromEachModule(D, /*IncludeLocal*/true); |
| } |
| Record.append(LazySpecializations.begin(), LazySpecializations.end()); |
| |
| // Update the size entry we added earlier. |
| Record[I] = Record.size() - I - 1; |
| } |
| |
| /// 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; |
| |
| Writer.DeclUpdates[Template].push_back(ASTWriter::DeclUpdate( |
| UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, Specialization)); |
| } |
| }; |
| } |
| |
| 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 (DeclaratorDecl *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 (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { |
| Record.push_back(FD->doesThisDeclarationHaveABody()); |
| if (FD->doesThisDeclarationHaveABody()) |
| Record.AddFunctionDefinition(FD); |
| } |
| |
| // 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 (DeclContext *DC = dyn_cast<DeclContext>(D)) |
| VisitDeclContext(DC); |
| } |
| |
| void ASTDeclWriter::VisitDecl(Decl *D) { |
| Record.AddDeclRef(cast_or_null<Decl>(D->getDeclContext())); |
| if (D->getDeclContext() != D->getLexicalDeclContext()) |
| Record.AddDeclRef(cast_or_null<Decl>(D->getLexicalDeclContext())); |
| else |
| Record.push_back(0); |
| Record.push_back(D->isInvalidDecl()); |
| Record.push_back(D->hasAttrs()); |
| if (D->hasAttrs()) |
| Record.AddAttributes(D->getAttrs()); |
| Record.push_back(D->isImplicit()); |
| Record.push_back(D->isUsed(false)); |
| Record.push_back(D->isReferenced()); |
| Record.push_back(D->isTopLevelDeclInObjCContainer()); |
| Record.push_back(D->getAccess()); |
| Record.push_back(D->isModulePrivate()); |
| 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()); |
| 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) { |
| VisitRedeclarable(D); |
| VisitTypeDecl(D); |
| Record.push_back(D->getIdentifierNamespace()); |
| Record.push_back((unsigned)D->getTagKind()); // FIXME: stable encoding |
| if (!isa<CXXRecordDecl>(D)) |
| Record.push_back(D->isCompleteDefinition()); |
| Record.push_back(D->isEmbeddedInDeclarator()); |
| Record.push_back(D->isFreeStanding()); |
| Record.push_back(D->isCompleteDefinitionRequired()); |
| Record.AddSourceRange(D->getBraceRange()); |
| |
| if (D->hasExtInfo()) { |
| Record.push_back(1); |
| Record.AddQualifierInfo(*D->getExtInfo()); |
| } else if (auto *TD = D->getTypedefNameForAnonDecl()) { |
| Record.push_back(2); |
| Record.AddDeclRef(TD); |
| Record.AddIdentifierRef(TD->getDeclName().getAsIdentifierInfo()); |
| } else { |
| Record.push_back(0); |
| } |
| } |
| |
| void ASTDeclWriter::VisitEnumDecl(EnumDecl *D) { |
| VisitTagDecl(D); |
| Record.AddTypeSourceInfo(D->getIntegerTypeSourceInfo()); |
| if (!D->getIntegerTypeSourceInfo()) |
| Record.AddTypeRef(D->getIntegerType()); |
| Record.AddTypeRef(D->getPromotionType()); |
| Record.push_back(D->getNumPositiveBits()); |
| Record.push_back(D->getNumNegativeBits()); |
| Record.push_back(D->isScoped()); |
| Record.push_back(D->isScopedUsingClassTag()); |
| Record.push_back(D->isFixed()); |
| 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->isImplicit() && |
| !D->isUsed(false) && |
| !D->hasExtInfo() && |
| !D->getTypedefNameForAnonDecl() && |
| D->getFirstDecl() == D->getMostRecentDecl() && |
| !D->isInvalidDecl() && |
| !D->isReferenced() && |
| !D->isTopLevelDeclInObjCContainer() && |
| D->getAccess() == AS_none && |
| !D->isModulePrivate() && |
| !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) { |
| VisitTagDecl(D); |
| Record.push_back(D->hasFlexibleArrayMember()); |
| Record.push_back(D->isAnonymousStructOrUnion()); |
| Record.push_back(D->hasObjectMember()); |
| Record.push_back(D->hasVolatileMember()); |
| Record.push_back(D->isNonTrivialToPrimitiveDefaultInitialize()); |
| Record.push_back(D->isNonTrivialToPrimitiveCopy()); |
| Record.push_back(D->isNonTrivialToPrimitiveDestroy()); |
| Record.push_back(D->hasNonTrivialToPrimitiveDefaultInitializeCUnion()); |
| Record.push_back(D->hasNonTrivialToPrimitiveDestructCUnion()); |
| Record.push_back(D->hasNonTrivialToPrimitiveCopyCUnion()); |
| Record.push_back(D->isParamDestroyedInCallee()); |
| Record.push_back(D->getArgPassingRestrictions()); |
| |
| if (D->getDeclContext() == D->getLexicalDeclContext() && |
| !D->hasAttrs() && |
| !D->isImplicit() && |
| !D->isUsed(false) && |
| !D->hasExtInfo() && |
| !D->getTypedefNameForAnonDecl() && |
| D->getFirstDecl() == D->getMostRecentDecl() && |
| !D->isInvalidDecl() && |
| !D->isReferenced() && |
| !D->isTopLevelDeclInObjCContainer() && |
| D->getAccess() == AS_none && |
| !D->isModulePrivate() && |
| !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(Info->TrailingRequiresClause); |
| } |
| // The location information is deferred until the end of the record. |
| Record.AddTypeRef(D->getTypeSourceInfo() ? D->getTypeSourceInfo()->getType() |
| : QualType()); |
| } |
| |
| void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { |
| VisitRedeclarable(D); |
| VisitDeclaratorDecl(D); |
| Record.AddDeclarationNameLoc(D->DNLoc, D->getDeclName()); |
| Record.push_back(D->getIdentifierNamespace()); |
| |
| // FunctionDecl's body is handled last at ASTWriterDecl::Visit, |
| // after everything else is written. |
| Record.push_back(static_cast<int>(D->getStorageClass())); // FIXME: stable encoding |
| Record.push_back(D->isInlineSpecified()); |
| Record.push_back(D->isInlined()); |
| Record.push_back(D->isVirtualAsWritten()); |
| Record.push_back(D->isPure()); |
| Record.push_back(D->hasInheritedPrototype()); |
| Record.push_back(D->hasWrittenPrototype()); |
| Record.push_back(D->isDeletedBit()); |
| Record.push_back(D->isTrivial()); |
| Record.push_back(D->isTrivialForCall()); |
| Record.push_back(D->isDefaulted()); |
| Record.push_back(D->isExplicitlyDefaulted()); |
| Record.push_back(D->hasImplicitReturnZero()); |
| Record.push_back(D->getConstexprKind()); |
| Record.push_back(D->usesSEHTry()); |
| Record.push_back(D->hasSkippedBody()); |
| Record.push_back(D->isMultiVersion()); |
| Record.push_back(D->isLateTemplateParsed()); |
| Record.push_back(D->getLinkageInternal()); |
| Record.AddSourceLocation(D->getEndLoc()); |
| |
| Record.push_back(D->getODRHash()); |
| Record.push_back(D->usesFPIntrin()); |
| |
| if (D->isDefaulted()) { |
| if (auto *FDI = D->getDefaultedFunctionInfo()) { |
| 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); |
| } |
| } |
| |
| Record.push_back(D->getTemplatedKind()); |
| switch (D->getTemplatedKind()) { |
| case FunctionDecl::TK_NonTemplate: |
| 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.push_back(FTSInfo->TemplateArgumentsAsWritten->NumTemplateArgs); |
| for (int i=0, e = FTSInfo->TemplateArgumentsAsWritten->NumTemplateArgs; |
| i!=e; ++i) |
| Record.AddTemplateArgumentLoc( |
| (*FTSInfo->TemplateArgumentsAsWritten)[i]); |
| Record.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->LAngleLoc); |
| Record.AddSourceLocation(FTSInfo->TemplateArgumentsAsWritten->RAngleLoc); |
| } |
| |
| 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(); |
| |
| // Templates. |
| Record.push_back(DFTSInfo->getNumTemplates()); |
| for (int i=0, e = DFTSInfo->getNumTemplates(); i != e; ++i) |
| Record.AddDeclRef(DFTSInfo->getTemplate(i)); |
| |
| // Templates args. |
| Record.push_back(DFTSInfo->getNumTemplateArgs()); |
| for (int i=0, e = DFTSInfo->getNumTemplateArgs(); i != e; ++i) |
| Record.AddTemplateArgumentLoc(DFTSInfo->getTemplateArg(i)); |
| Record.AddSourceLocation(DFTSInfo->getLAngleLoc()); |
| Record.AddSourceLocation(DFTSInfo->getRAngleLoc()); |
| break; |
| } |
| } |
| |
| 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); |
| VisitFunctionDecl(D); |
| Record.push_back(D->isCopyDeductionCandidate()); |
| Code = serialization::DECL_CXX_DEDUCTION_GUIDE; |
| } |
| |
| void ASTDeclWriter::VisitObjCMethodDecl(ObjCMethodDecl *D) { |
| 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(Context.getObjCMethodRedeclaration(D)); |
| Record.AddDeclRef(Context.getObjCMethodRedeclaration(D)); |
| } |
| |
| // FIXME: stable encoding for @required/@optional |
| Record.push_back(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) { |
| 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); |
| |
| // 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); |
| } |
| |
| 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::makeArrayRef(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()); |
| |
| FieldDecl::InitStorageKind ISK = D->InitStorage.getInt(); |
| Record.push_back(ISK); |
| if (ISK == FieldDecl::ISK_CapturedVLAType) |
| Record.AddTypeRef(QualType(D->getCapturedVLAType(), 0)); |
| else if (ISK) |
| Record.AddStmt(D->getInClassInitializer()); |
| |
| Record.AddStmt(D->getBitWidth()); |
| |
| if (!D->getDeclName()) |
| Record.AddDeclRef(Context.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); |
| for (auto C : Parts.Part4And5) |
| Record.push_back(C); |
| Code = serialization::DECL_MS_GUID; |
| } |
| |
| 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); |
| Record.push_back(D->getStorageClass()); |
| Record.push_back(D->getTSCSpec()); |
| Record.push_back(D->getInitStyle()); |
| Record.push_back(D->isARCPseudoStrong()); |
| if (!isa<ParmVarDecl>(D)) { |
| Record.push_back(D->isThisDeclarationADemotedDefinition()); |
| Record.push_back(D->isExceptionVariable()); |
| Record.push_back(D->isNRVOVariable()); |
| Record.push_back(D->isCXXForRangeDecl()); |
| Record.push_back(D->isObjCForDecl()); |
| Record.push_back(D->isInline()); |
| Record.push_back(D->isInlineSpecified()); |
| Record.push_back(D->isConstexpr()); |
| Record.push_back(D->isInitCapture()); |
| Record.push_back(D->isPreviousDeclInSameBlockScope()); |
| if (const auto *IPD = dyn_cast<ImplicitParamDecl>(D)) |
| Record.push_back(static_cast<unsigned>(IPD->getParameterKind())); |
| else |
| Record.push_back(0); |
| Record.push_back(D->isEscapingByref()); |
| } |
| Record.push_back(D->getLinkageInternal()); |
| |
| if (D->getInit()) { |
| if (!D->isInitKnownICE()) |
| Record.push_back(1); |
| else { |
| Record.push_back( |
| 2 | |
| (D->isInitICE() ? 1 : 0) | |
| (D->ensureEvaluatedStmt()->HasConstantDestruction ? 4 : 0)); |
| } |
| Record.AddStmt(D->getInit()); |
| } else { |
| Record.push_back(0); |
| } |
| |
| if (D->hasAttr<BlocksAttr>() && D->getType()->getAsCXXRecordDecl()) { |
| BlockVarCopyInit Init = Writer.Context->getBlockVarCopyInit(D); |
| Record.AddStmt(Init.getCopyExpr()); |
| if (Init.getCopyExpr()) |
| Record.push_back(Init.canThrow()); |
| } |
| |
| if (D->getStorageDuration() == SD_Static) { |
| bool ModulesCodegen = false; |
| if (Writer.WritingModule && |
| !D->getDescribedVarTemplate() && !D->getMemberSpecializationInfo() && |
| !isa<VarTemplateSpecializationDecl>(D)) { |
| // When building a C++ Modules TS module interface unit, a strong |
| // definition in the module interface is provided by the compilation of |
| // that module interface unit, not by its users. (Inline variables are |
| // still emitted in module users.) |
| ModulesCodegen = |
| (Writer.WritingModule->Kind == Module::ModuleInterfaceUnit || |
| (D->hasAttr<DLLExportAttr>() && |
| Writer.Context->getLangOpts().BuildingPCHWithObjectFile)) && |
| Writer.Context->GetGVALinkageForVariable(D) == GVA_StrongExternal; |
| } |
| Record.push_back(ModulesCodegen); |
| if (ModulesCodegen) |
| Writer.ModularCodegenDecls.push_back(Writer.GetDeclRef(D)); |
| } |
| |
| 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->isImplicit() && |
| !D->isUsed(false) && |
| !D->isInvalidDecl() && |
| !D->isReferenced() && |
| !D->isTopLevelDeclInObjCContainer() && |
| D->getAccess() == AS_none && |
| !D->isModulePrivate() && |
| !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->hasAttr<BlocksAttr>() && D->getType()->getAsCXXRecordDecl()) && |
| !D->isEscapingByref() && |
| D->getStorageDuration() != SD_Static && |
| !D->getMemberSpecializationInfo()) |
| 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); |
| Record.push_back(D->isObjCMethodParameter()); |
| Record.push_back(D->getFunctionScopeDepth()); |
| Record.push_back(D->getFunctionScopeIndex()); |
| Record.push_back(D->getObjCDeclQualifier()); // FIXME: stable encoding |
| Record.push_back(D->isKNRPromoted()); |
| Record.push_back(D->hasInheritedDefaultArg()); |
| Record.push_back(D->hasUninstantiatedDefaultArg()); |
| if (D->hasUninstantiatedDefaultArg()) |
| Record.AddStmt(D->getUninstantiatedDefaultArg()); |
| 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->isImplicit() && |
| !D->isUsed(false) && |
| !D->isInvalidDecl() && |
| !D->isReferenced() && |
| D->getAccess() == AS_none && |
| !D->isModulePrivate() && |
| D->getStorageClass() == 0 && |
| D->getInitStyle() == VarDecl::CInit && // Can params have anything else? |
| D->getFunctionScopeDepth() == 0 && |
| D->getObjCDeclQualifier() == 0 && |
| !D->isKNRPromoted() && |
| !D->hasInheritedDefaultArg() && |
| D->getInit() == nullptr && |
| !D->hasUninstantiatedDefaultArg()) // 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->getAsmString()); |
| Record.AddSourceLocation(D->getRParenLoc()); |
| Code = serialization::DECL_FILE_SCOPE_ASM; |
| } |
| |
| 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::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) { |
| VisitDecl(D); |
| Record.push_back(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); |
| Record.push_back(D->isInline()); |
| Record.AddSourceLocation(D->getBeginLoc()); |
| Record.AddSourceLocation(D->getRBraceLoc()); |
| |
| if (D->isOriginalNamespace()) |
| 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(UPD_CXX_ADDED_ANONYMOUS_NAMESPACE, 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(Context.getInstantiatedFromUsingDecl(D)); |
| Code = serialization::DECL_USING; |
| } |
| |
| 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(Context.getInstantiatedFromUsingShadowDecl(D)); |
| 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::VisitCXXRecordDecl(CXXRecordDecl *D) { |
| VisitRecordDecl(D); |
| |
| enum { |
| CXXRecNotTemplate = 0, CXXRecTemplate, CXXRecMemberSpecialization |
| }; |
| 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 { |
| Record.push_back(CXXRecNotTemplate); |
| } |
| |
| Record.push_back(D->isThisDeclarationADefinition()); |
| if (D->isThisDeclarationADefinition()) |
| Record.AddCXXDefinitionData(D); |
| |
| // Store (what we currently believe to be) the key function to avoid |
| // deserializing every method so we can compute it. |
| if (D->isCompleteDefinition()) |
| Record.AddDeclRef(Context.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->hasInheritedPrototype() && |
| D->hasWrittenPrototype()) |
| AbbrevToUse = Writer.getDeclCXXMethodAbbrev(); |
| |
| Code = serialization::DECL_CXX_METHOD; |
| } |
| |
| void ASTDeclWriter::VisitCXXConstructorDecl(CXXConstructorDecl *D) { |
| Record.push_back(D->getTraillingAllocKind()); |
| addExplicitSpecifier(D->getExplicitSpecifier(), 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()); |
| |
| 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 = D->Friend.is<NamedDecl*>(); |
| 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); |
| 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.AddDeclRef(D->getTemplatedDecl()); |
| Record.AddTemplateParameterList(D->getTemplateParameters()); |
| } |
| |
| void ASTDeclWriter::VisitConceptDecl(ConceptDecl *D) { |
| VisitTemplateDecl(D); |
| Record.AddStmt(D->getConstraintExpr()); |
| Code = serialization::DECL_CONCEPT; |
| } |
| |
| 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); |
| 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(InstFrom.get<ClassTemplatePartialSpecializationDecl *>()); |
| Record.AddTemplateArgumentList(&D->getTemplateInstantiationArgs()); |
| } |
| |
| Record.AddTemplateArgumentList(&D->getTemplateArgs()); |
| Record.AddSourceLocation(D->getPointOfInstantiation()); |
| Record.push_back(D->getSpecializationKind()); |
| 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()); |
| } |
| |
| // Explicit info. |
| Record.AddTypeSourceInfo(D->getTypeAsWritten()); |
| if (D->getTypeAsWritten()) { |
| Record.AddSourceLocation(D->getExternLoc()); |
| Record.AddSourceLocation(D->getTemplateKeywordLoc()); |
| } |
| |
| Code = serialization::DECL_CLASS_TEMPLATE_SPECIALIZATION; |
| } |
| |
| void ASTDeclWriter::VisitClassTemplatePartialSpecializationDecl( |
| ClassTemplatePartialSpecializationDecl *D) { |
| Record.AddTemplateParameterList(D->getTemplateParameters()); |
| Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); |
| |
| 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); |
| |
| VisitVarDecl(D); |
| |
| llvm::PointerUnion<VarTemplateDecl *, VarTemplatePartialSpecializationDecl *> |
| InstFrom = D->getSpecializedTemplateOrPartial(); |
| if (Decl *InstFromD = InstFrom.dyn_cast<VarTemplateDecl *>()) { |
| Record.AddDeclRef(InstFromD); |
| } else { |
| Record.AddDeclRef(InstFrom.get<VarTemplatePartialSpecializationDecl *>()); |
| Record.AddTemplateArgumentList(&D->getTemplateInstantiationArgs()); |
| } |
| |
| // Explicit info. |
| Record.AddTypeSourceInfo(D->getTypeAsWritten()); |
| if (D->getTypeAsWritten()) { |
| Record.AddSourceLocation(D->getExternLoc()); |
| Record.AddSourceLocation(D->getTemplateKeywordLoc()); |
| } |
| |
| Record.AddTemplateArgumentList(&D->getTemplateArgs()); |
| Record.AddSourceLocation(D->getPointOfInstantiation()); |
| Record.push_back(D->getSpecializationKind()); |
| Record.push_back(D->IsCompleteDefinition); |
| 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()); |
| Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); |
| |
| 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::VisitClassScopeFunctionSpecializationDecl( |
| ClassScopeFunctionSpecializationDecl *D) { |
| VisitDecl(D); |
| Record.AddDeclRef(D->getSpecialization()); |
| Record.push_back(D->hasExplicitTemplateArgs()); |
| if (D->hasExplicitTemplateArgs()) |
| Record.AddASTTemplateArgumentListInfo(D->getTemplateArgsAsWritten()); |
| Code = serialization::DECL_CLASS_SCOPE_FUNCTION_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(); |
| Record.push_back(TC != nullptr); |
| if (TC) { |
| Record.AddNestedNameSpecifierLoc(TC->getNestedNameSpecifierLoc()); |
| Record.AddDeclarationNameInfo(TC->getConceptNameInfo()); |
| Record.AddDeclRef(TC->getNamedConcept()); |
| Record.push_back(TC->getTemplateArgsAsWritten() != nullptr); |
| if (TC->getTemplateArgsAsWritten()) |
| Record.AddASTTemplateArgumentListInfo(TC->getTemplateArgsAsWritten()); |
| Record.AddStmt(TC->getImmediatelyDeclaredConstraint()); |
| Record.push_back(D->isExpandedParameterPack()); |
| if (D->isExpandedParameterPack()) |
| Record.push_back(D->getNumExpansionParameters()); |
| } |
| |
| bool OwnsDefaultArg = D->hasDefaultArgument() && |
| !D->defaultArgumentWasInherited(); |
| Record.push_back(OwnsDefaultArg); |
| if (OwnsDefaultArg) |
| Record.AddTypeSourceInfo(D->getDefaultArgumentInfo()); |
| |
| 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. |
| Expr *TypeConstraint = D->getPlaceholderTypeConstraint(); |
| Record.push_back(!!TypeConstraint); |
| if (D->isExpandedParameterPack()) |
| Record.push_back(D->getNumExpansionTypes()); |
| |
| VisitDeclaratorDecl(D); |
| // TemplateParmPosition. |
| Record.push_back(D->getDepth()); |
| Record.push_back(D->getPosition()); |
| if (TypeConstraint) |
| Record.AddStmt(TypeConstraint); |
| |
| 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.AddStmt(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); |
| // 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) { |
| Record.AddOffset(Writer.WriteDeclContextLexicalBlock(Context, DC)); |
| Record.AddOffset(Writer.WriteDeclContextVisibleBlock(Context, DC)); |
| } |
| |
| 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::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) { |
| 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(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; |
| } |
| |
| //===----------------------------------------------------------------------===// |
| // ASTWriter Implementation |
| //===----------------------------------------------------------------------===// |
| |
| 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::VBR, 6)); // DeclContext |
| Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext |
| Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl |
| Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs |
| Abv->Add(BitCodeAbbrevOp(0)); // isImplicit |
| Abv->Add(BitCodeAbbrevOp(0)); // isUsed |
| Abv->Add(BitCodeAbbrevOp(0)); // isReferenced |
| Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // AccessSpecifier |
| Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate |
| 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 |
| // 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::VBR, 6)); // DeclContext |
| Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext |
| Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl |
| Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs |
| Abv->Add(BitCodeAbbrevOp(0)); // isImplicit |
| Abv->Add(BitCodeAbbrevOp(0)); // isUsed |
| Abv->Add(BitCodeAbbrevOp(0)); // isReferenced |
| Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // AccessSpecifier |
| Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate |
| 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::VBR, 6)); // DeclContext |
| Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext |
| Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl |
| Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs |
| Abv->Add(BitCodeAbbrevOp(0)); // isImplicit |
| Abv->Add(BitCodeAbbrevOp(0)); // isUsed |
| Abv->Add(BitCodeAbbrevOp(0)); // isReferenced |
| Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer |
| Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier |
| Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate |
| 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 |
| // TagDecl |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IdentifierNamespace |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getTagKind |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCompleteDefinition |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // EmbeddedInDeclarator |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFreeStanding |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsCompleteDefinitionRequired |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation |
| Abv->Add(BitCodeAbbrevOp(0)); // ExtInfoKind |
| // 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::VBR, 6)); // getNumPositiveBits |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getNumNegativeBits |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isScoped |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isScopedUsingClassTag |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isFixed |
| 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 |
| 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::VBR, 6)); // DeclContext |
| Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext |
| Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl |
| Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs |
| Abv->Add(BitCodeAbbrevOp(0)); // isImplicit |
| Abv->Add(BitCodeAbbrevOp(0)); // isUsed |
| Abv->Add(BitCodeAbbrevOp(0)); // isReferenced |
| Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer |
| Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier |
| Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate |
| 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 |
| // TagDecl |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // IdentifierNamespace |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // getTagKind |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCompleteDefinition |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // EmbeddedInDeclarator |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsFreeStanding |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsCompleteDefinitionRequired |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // SourceLocation |
| Abv->Add(BitCodeAbbrevOp(0)); // ExtInfoKind |
| // RecordDecl |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // FlexibleArrayMember |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // AnonymousStructUnion |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // hasObjectMember |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // hasVolatileMember |
| |
| // isNonTrivialToPrimitiveDefaultInitialize |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); |
| // isNonTrivialToPrimitiveCopy |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); |
| // isNonTrivialToPrimitiveDestroy |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); |
| // hasNonTrivialToPrimitiveDefaultInitializeCUnion |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); |
| // hasNonTrivialToPrimitiveDestructCUnion |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); |
| // hasNonTrivialToPrimitiveCopyCUnion |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); |
| // isParamDestroyedInCallee |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); |
| // getArgPassingRestrictions |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); |
| |
| // DC |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LexicalOffset |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // VisibleOffset |
| 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::VBR, 6)); // DeclContext |
| Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext |
| Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl |
| Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs |
| Abv->Add(BitCodeAbbrevOp(0)); // isImplicit |
| Abv->Add(BitCodeAbbrevOp(0)); // isUsed |
| Abv->Add(BitCodeAbbrevOp(0)); // isReferenced |
| Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer |
| Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier |
| Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate |
| 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(0)); // SClass |
| Abv->Add(BitCodeAbbrevOp(0)); // TSCSpec |
| Abv->Add(BitCodeAbbrevOp(0)); // InitStyle |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isARCPseudoStrong |
| Abv->Add(BitCodeAbbrevOp(0)); // Linkage |
| Abv->Add(BitCodeAbbrevOp(0)); // HasInit |
| Abv->Add(BitCodeAbbrevOp(0)); // HasMemberSpecializationInfo |
| // ParmVarDecl |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsObjCMethodParameter |
| Abv->Add(BitCodeAbbrevOp(0)); // ScopeDepth |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // ScopeIndex |
| Abv->Add(BitCodeAbbrevOp(0)); // ObjCDeclQualifier |
| Abv->Add(BitCodeAbbrevOp(0)); // KNRPromoted |
| Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedDefaultArg |
| Abv->Add(BitCodeAbbrevOp(0)); // 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::VBR, 6)); // DeclContext |
| Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext |
| Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl |
| Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs |
| Abv->Add(BitCodeAbbrevOp(0)); // isImplicit |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isUsed |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isReferenced |
| Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // C++ AccessSpecifier |
| Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate |
| 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::VBR, 6)); // DeclContext |
| Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext |
| Abv->Add(BitCodeAbbrevOp(0)); // isInvalidDecl |
| Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs |
| Abv->Add(BitCodeAbbrevOp(0)); // isImplicit |
| Abv->Add(BitCodeAbbrevOp(0)); // isUsed |
| Abv->Add(BitCodeAbbrevOp(0)); // isReferenced |
| Abv->Add(BitCodeAbbrevOp(0)); // TopLevelDeclInObjCContainer |
| Abv->Add(BitCodeAbbrevOp(AS_none)); // C++ AccessSpecifier |
| Abv->Add(BitCodeAbbrevOp(0)); // ModulePrivate |
| 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, 3)); // SClass |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // TSCSpec |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // InitStyle |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isARCPseudoStrong |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // IsThisDeclarationADemotedDefinition |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isExceptionVariable |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isNRVOVariable |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isCXXForRangeDecl |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // isObjCForDecl |
| Abv->Add(BitCodeAbbrevOp(0)); // isInline |
| Abv->Add(BitCodeAbbrevOp(0)); // isInlineSpecified |
| Abv->Add(BitCodeAbbrevOp(0)); // isConstexpr |
| Abv->Add(BitCodeAbbrevOp(0)); // isInitCapture |
| Abv->Add(BitCodeAbbrevOp(0)); // isPrevDeclInSameScope |
| Abv->Add(BitCodeAbbrevOp(0)); // ImplicitParamKind |
| Abv->Add(BitCodeAbbrevOp(0)); // EscapingByref |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // IsInitICE (local) |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // 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 |
| Abv = std::make_shared<BitCodeAbbrev>(); |
| Abv->Add(BitCodeAbbrevOp(serialization::DECL_CXX_METHOD)); |
| // RedeclarableDecl |
| Abv->Add(BitCodeAbbrevOp(0)); // CanonicalDecl |
| // Decl |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // DeclContext |
| Abv->Add(BitCodeAbbrevOp(0)); // LexicalDeclContext |
| Abv->Add(BitCodeAbbrevOp(0)); // Invalid |
| Abv->Add(BitCodeAbbrevOp(0)); // HasAttrs |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Implicit |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Used |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Referenced |
| Abv->Add(BitCodeAbbrevOp(0)); // InObjCContainer |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 2)); // Access |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ModulePrivate |
| 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, 3)); // StorageClass |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Inline |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // InlineSpecified |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // VirtualAsWritten |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Pure |
| Abv->Add(BitCodeAbbrevOp(0)); // HasInheritedProto |
| Abv->Add(BitCodeAbbrevOp(1)); // HasWrittenProto |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Deleted |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Trivial |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // TrivialForCall |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Defaulted |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ExplicitlyDefaulted |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // ImplicitReturnZero |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // Constexpr |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // UsesSEHTry |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // SkippedBody |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // MultiVersion |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // LateParsed |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // Linkage |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // LocEnd |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 32)); // ODRHash |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); // TemplateKind |
| // 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 the function template information if any, then |
| // 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)); |
| DeclCXXMethodAbbrev = Stream.EmitAbbrev(std::move(Abv)); |
| |
| // Abbreviation for EXPR_DECL_REF |
| Abv = std::make_shared<BitCodeAbbrev>(); |
| Abv->Add(BitCodeAbbrevOp(serialization::EXPR_DECL_REF)); |
| //Stmt |
| // Expr |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //TypeDependent |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ContainsErrors |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind |
| //DeclRefExpr |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HasQualifier |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //GetDeclFound |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ExplicitTemplateArgs |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //HadMultipleCandidates |
| Abv->Add(BitCodeAbbrevOp(0)); // RefersToEnclosingVariableOrCapture |
| Abv->Add(BitCodeAbbrevOp(0)); // NonOdrUseReason |
| 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 |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //TypeDependent |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ContainsErrors |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind |
| //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 |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //TypeDependent |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ContainsErrors |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind |
| //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 |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::VBR, 6)); // Type |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //TypeDependent |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ValueDependent |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //InstantiationDependent |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //UnexpandedParamPack |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); //ContainsErrors |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetValueKind |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 3)); //GetObjectKind |
| // CastExpr |
| Abv->Add(BitCodeAbbrevOp(0)); // PathSize |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // HasFPFeatures |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 6)); // CastKind |
| Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Fixed, 1)); // PartOfExplicitCast |
| // ImplicitCastExpr |
| ExprImplicitCastAbbrev = 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)); |
| } |
| |
| /// 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, |
| bool WritingModule) { |
| // 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>(D) || isa<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. |
| serialization::DeclID ID; |
| assert(!D->isFromASTFile() && "should not be emitting imported decl"); |
| serialization::DeclID &IDR = DeclIDs[D]; |
| if (IDR == 0) |
| IDR = NextDeclID++; |
| |
| ID = IDR; |
| |
| assert(ID >= FirstDeclID && "invalid decl ID"); |
| |
| RecordData Record; |
| ASTDeclWriter W(*this, Context, Record); |
| |
| // 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(); |
| unsigned Index = ID - FirstDeclID; |
| if (DeclOffsets.size() == Index) |
| DeclOffsets.emplace_back(Loc, Offset, DeclTypesBlockStartOffset); |
| else if (DeclOffsets.size() < Index) { |
| // FIXME: Can/should this happen? |
| DeclOffsets.resize(Index+1); |
| DeclOffsets[Index].setLocation(Loc); |
| 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)) |
| EagerlyDeserializedDecls.push_back(ID); |
| } |
| |
| void ASTRecordWriter::AddFunctionDefinition(const FunctionDecl *FD) { |
| // Switch case IDs are per function body. |
| Writer->ClearSwitchCaseIDs(); |
| |
| assert(FD->doesThisDeclarationHaveABody()); |
| bool ModulesCodegen = false; |
| if (!FD->isDependentContext()) { |
| Optional<GVALinkage> Linkage; |
| if (Writer->WritingModule && |
| Writer->WritingModule->Kind == Module::ModuleInterfaceUnit) { |
| // When building a C++ Modules TS module interface unit, a strong |
| // definition in the module interface is provided by the compilation of |
| // that module interface unit, not by its users. (Inline functions are |
| // still emitted in module users.) |
| Linkage = Writer->Context->GetGVALinkageForFunction(FD); |
| ModulesCodegen = *Linkage == GVA_StrongExternal; |
| } |
| if (Writer->Context->getLangOpts().ModulesCodegen || |
| (FD->hasAttr<DLLExportAttr>() && |
| Writer->Context->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>()) { |
| if (!Linkage) |
| Linkage = Writer->Context->GetGVALinkageForFunction(FD); |
| ModulesCodegen = |
| *Linkage != GVA_Internal && *Linkage != GVA_AvailableExternally; |
| } |
| } |
| } |
| Record->push_back(ModulesCodegen); |
| if (ModulesCodegen) |
| Writer->ModularCodegenDecls.push_back(Writer->GetDeclRef(FD)); |
| if (auto *CD = dyn_cast<CXXConstructorDecl>(FD)) { |
| Record->push_back(CD->getNumCtorInitializers()); |
| if (CD->getNumCtorInitializers()) |
| AddCXXCtorInitializers( |
| llvm::makeArrayRef(CD->init_begin(), CD->init_end())); |
| } |
| AddStmt(FD->getBody()); |
| } |