diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 892d7363e06dd..e093e6ad9d12c 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -559,6 +559,8 @@ class ASTWriter : public ASTDeserializationListener, void WriteIdentifierTable(Preprocessor &PP, IdentifierResolver &IdResolver, bool IsModule); void WriteDeclAndTypes(ASTContext &Context); + void PrepareWritingSpecialDecls(Sema &SemaRef); + void WriteSpecialDeclRecords(Sema &SemaRef); void WriteDeclUpdatesBlocks(RecordDataImpl &OffsetsRecord); void WriteDeclContextVisibleUpdate(const DeclContext *DC); void WriteFPPragmaOptions(const FPOptionsOverride &Opts); diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index c3cf242391b74..ffeab4db9f6af 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -4733,6 +4733,14 @@ ASTFileSignature ASTWriter::WriteAST(Sema &SemaRef, StringRef OutputFile, return Signature; } +template +static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec) { + for (typename Vector::iterator I = Vec.begin(nullptr, true), E = Vec.end(); + I != E; ++I) { + Writer.GetDeclRef(*I); + } +} + template static void AddLazyVectorDecls(ASTWriter &Writer, Vector &Vec, ASTWriter::RecordData &Record) { @@ -4835,24 +4843,10 @@ void ASTWriter::computeNonAffectingInputFiles() { FileMgr.trackVFSUsage(false); } -ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, - Module *WritingModule) { - using namespace llvm; - - bool isModule = WritingModule != nullptr; - - // Make sure that the AST reader knows to finalize itself. - if (Chain) - Chain->finalizeForWriting(); - +void ASTWriter::PrepareWritingSpecialDecls(Sema &SemaRef) { ASTContext &Context = SemaRef.Context; - Preprocessor &PP = SemaRef.PP; - - // This needs to be done very early, since everything that writes - // SourceLocations or FileIDs depends on it. - computeNonAffectingInputFiles(); - writeUnhashedControlBlock(PP, Context); + bool isModule = WritingModule != nullptr; // Set up predefined declaration IDs. auto RegisterPredefDecl = [&] (Decl *D, PredefinedDeclIDs ID) { @@ -4888,43 +4882,144 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, RegisterPredefDecl(Context.TypePackElementDecl, PREDEF_DECL_TYPE_PACK_ELEMENT_ID); - // Build a record containing all of the tentative definitions in this file, in + // Writing all of the tentative definitions in this file, in // TentativeDefinitions order. Generally, this record will be empty for // headers. RecordData TentativeDefinitions; - AddLazyVectorDecls(*this, SemaRef.TentativeDefinitions, TentativeDefinitions); + AddLazyVectorDecls(*this, SemaRef.TentativeDefinitions); - // Build a record containing all of the file scoped decls in this file. - RecordData UnusedFileScopedDecls; + // Writing all of the file scoped decls in this file. if (!isModule) - AddLazyVectorDecls(*this, SemaRef.UnusedFileScopedDecls, - UnusedFileScopedDecls); + AddLazyVectorDecls(*this, SemaRef.UnusedFileScopedDecls); - // Build a record containing all of the delegating constructors we still need + // Writing all of the delegating constructors we still need // to resolve. - RecordData DelegatingCtorDecls; if (!isModule) - AddLazyVectorDecls(*this, SemaRef.DelegatingCtorDecls, DelegatingCtorDecls); + AddLazyVectorDecls(*this, SemaRef.DelegatingCtorDecls); - // Write the set of weak, undeclared identifiers. We always write the - // entire table, since later PCH files in a PCH chain are only interested in - // the results at the end of the chain. - RecordData WeakUndeclaredIdentifiers; - for (const auto &WeakUndeclaredIdentifierList : - SemaRef.WeakUndeclaredIdentifiers) { - const IdentifierInfo *const II = WeakUndeclaredIdentifierList.first; - for (const auto &WI : WeakUndeclaredIdentifierList.second) { - AddIdentifierRef(II, WeakUndeclaredIdentifiers); - AddIdentifierRef(WI.getAlias(), WeakUndeclaredIdentifiers); - AddSourceLocation(WI.getLocation(), WeakUndeclaredIdentifiers); + // Writing all of the ext_vector declarations. + AddLazyVectorDecls(*this, SemaRef.ExtVectorDecls); + + // Writing all of the VTable uses information. + if (!SemaRef.VTableUses.empty()) + for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) + GetDeclRef(SemaRef.VTableUses[I].first); + + // Writing all of the UnusedLocalTypedefNameCandidates. + for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates) + GetDeclRef(TD); + + // Writing all of pending implicit instantiations. + for (const auto &I : SemaRef.PendingInstantiations) + GetDeclRef(I.first); + assert(SemaRef.PendingLocalImplicitInstantiations.empty() && + "There are local ones at end of translation unit!"); + + // Writing some declaration references. + if (SemaRef.StdNamespace || SemaRef.StdBadAlloc || SemaRef.StdAlignValT) { + GetDeclRef(SemaRef.getStdNamespace()); + GetDeclRef(SemaRef.getStdBadAlloc()); + GetDeclRef(SemaRef.getStdAlignValT()); + } + + if (Context.getcudaConfigureCallDecl()) + GetDeclRef(Context.getcudaConfigureCallDecl()); + + // Writing all of the known namespaces. + for (const auto &I : SemaRef.KnownNamespaces) + if (!I.second) + GetDeclRef(I.first); + + // Writing all used, undefined objects that require definitions. + SmallVector, 16> Undefined; + SemaRef.getUndefinedButUsed(Undefined); + for (const auto &I : Undefined) + GetDeclRef(I.first); + + // Writing all delete-expressions that we would like to + // analyze later in AST. + if (!isModule) + for (const auto &DeleteExprsInfo : + SemaRef.getMismatchingDeleteExpressions()) + GetDeclRef(DeleteExprsInfo.first); + + const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); + + // Force all top level declarations to be emitted. + // + // We start emitting top level declarations from the module purview to + // implement the eliding unreachable declaration feature. + for (const auto *D : TU->noload_decls()) { + if (D->isFromASTFile()) + continue; + + if (GeneratingReducedBMI && D->isFromExplicitGlobalModule()) + continue; + + GetDeclRef(D); + } + + // Make sure visible decls, added to DeclContexts previously loaded from + // an AST file, are registered for serialization. Likewise for template + // specializations added to imported templates. + for (const auto *I : DeclsToEmitEvenIfUnreferenced) + GetDeclRef(I); + DeclsToEmitEvenIfUnreferenced.clear(); + + // Make sure all decls associated with an identifier are registered for + // serialization, if we're storing decls with identifiers. + if (!WritingModule || !getLangOpts().CPlusPlus) { + llvm::SmallVector IIs; + for (const auto &ID : SemaRef.PP.getIdentifierTable()) { + const IdentifierInfo *II = ID.second; + if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization()) + IIs.push_back(II); } + // Sort the identifiers to visit based on their name. + llvm::sort(IIs, llvm::deref>()); + for (const IdentifierInfo *II : IIs) + for (const Decl *D : SemaRef.IdResolver.decls(II)) + GetDeclRef(D); } - // Build a record containing all of the ext_vector declarations. + // Write all of the DeclsToCheckForDeferredDiags. + for (auto *D : SemaRef.DeclsToCheckForDeferredDiags) + GetDeclRef(D); +} + +void ASTWriter::WriteSpecialDeclRecords(Sema &SemaRef) { + ASTContext &Context = SemaRef.Context; + + bool isModule = WritingModule != nullptr; + + // Write the record containing external, unnamed definitions. + if (!EagerlyDeserializedDecls.empty()) + Stream.EmitRecord(EAGERLY_DESERIALIZED_DECLS, EagerlyDeserializedDecls); + + if (!ModularCodegenDecls.empty()) + Stream.EmitRecord(MODULAR_CODEGEN_DECLS, ModularCodegenDecls); + + // Write the record containing tentative definitions. + RecordData TentativeDefinitions; + AddLazyVectorDecls(*this, SemaRef.TentativeDefinitions, TentativeDefinitions); + if (!TentativeDefinitions.empty()) + Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions); + + // Write the record containing unused file scoped decls. + RecordData UnusedFileScopedDecls; + if (!isModule) + AddLazyVectorDecls(*this, SemaRef.UnusedFileScopedDecls, + UnusedFileScopedDecls); + if (!UnusedFileScopedDecls.empty()) + Stream.EmitRecord(UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls); + + // Write the record containing ext_vector type names. RecordData ExtVectorDecls; AddLazyVectorDecls(*this, SemaRef.ExtVectorDecls, ExtVectorDecls); + if (!ExtVectorDecls.empty()) + Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls); - // Build a record containing all of the VTable uses information. + // Write the record containing VTable uses information. RecordData VTableUses; if (!SemaRef.VTableUses.empty()) { for (unsigned I = 0, N = SemaRef.VTableUses.size(); I != N; ++I) { @@ -4932,56 +5027,81 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, AddSourceLocation(SemaRef.VTableUses[I].second, VTableUses); VTableUses.push_back(SemaRef.VTablesUsed[SemaRef.VTableUses[I].first]); } + Stream.EmitRecord(VTABLE_USES, VTableUses); } - // Build a record containing all of the UnusedLocalTypedefNameCandidates. + // Write the record containing potentially unused local typedefs. RecordData UnusedLocalTypedefNameCandidates; for (const TypedefNameDecl *TD : SemaRef.UnusedLocalTypedefNameCandidates) AddDeclRef(TD, UnusedLocalTypedefNameCandidates); + if (!UnusedLocalTypedefNameCandidates.empty()) + Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES, + UnusedLocalTypedefNameCandidates); - // Build a record containing all of pending implicit instantiations. + // Write the record containing pending implicit instantiations. RecordData PendingInstantiations; for (const auto &I : SemaRef.PendingInstantiations) { AddDeclRef(I.first, PendingInstantiations); AddSourceLocation(I.second, PendingInstantiations); } - assert(SemaRef.PendingLocalImplicitInstantiations.empty() && - "There are local ones at end of translation unit!"); + if (!PendingInstantiations.empty()) + Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations); - // Build a record containing some declaration references. + // Write the record containing declaration references of Sema. RecordData SemaDeclRefs; if (SemaRef.StdNamespace || SemaRef.StdBadAlloc || SemaRef.StdAlignValT) { AddDeclRef(SemaRef.getStdNamespace(), SemaDeclRefs); AddDeclRef(SemaRef.getStdBadAlloc(), SemaDeclRefs); AddDeclRef(SemaRef.getStdAlignValT(), SemaDeclRefs); } + if (!SemaDeclRefs.empty()) + Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs); + + // Write the record containing decls to be checked for deferred diags. + SmallVector DeclsToCheckForDeferredDiags; + for (auto *D : SemaRef.DeclsToCheckForDeferredDiags) + DeclsToCheckForDeferredDiags.push_back(GetDeclRef(D)); + if (!DeclsToCheckForDeferredDiags.empty()) + Stream.EmitRecord(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS, + DeclsToCheckForDeferredDiags); + // Write the record containing CUDA-specific declaration references. RecordData CUDASpecialDeclRefs; if (Context.getcudaConfigureCallDecl()) { AddDeclRef(Context.getcudaConfigureCallDecl(), CUDASpecialDeclRefs); + Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs); } - // Build a record containing all of the known namespaces. + // Write the delegating constructors. + RecordData DelegatingCtorDecls; + if (!isModule) + AddLazyVectorDecls(*this, SemaRef.DelegatingCtorDecls, DelegatingCtorDecls); + if (!DelegatingCtorDecls.empty()) + Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls); + + // Write the known namespaces. RecordData KnownNamespaces; for (const auto &I : SemaRef.KnownNamespaces) { if (!I.second) AddDeclRef(I.first, KnownNamespaces); } + if (!KnownNamespaces.empty()) + Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces); - // Build a record of all used, undefined objects that require definitions. + // Write the undefined internal functions and variables, and inline functions. RecordData UndefinedButUsed; - SmallVector, 16> Undefined; SemaRef.getUndefinedButUsed(Undefined); for (const auto &I : Undefined) { AddDeclRef(I.first, UndefinedButUsed); AddSourceLocation(I.second, UndefinedButUsed); } - - // Build a record containing all delete-expressions that we would like to + if (!UndefinedButUsed.empty()) + Stream.EmitRecord(UNDEFINED_BUT_USED, UndefinedButUsed); + + // Write all delete-expressions that we would like to // analyze later in AST. RecordData DeleteExprsToAnalyze; - if (!isModule) { for (const auto &DeleteExprsInfo : SemaRef.getMismatchingDeleteExpressions()) { @@ -4993,6 +5113,44 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, } } } + if (!DeleteExprsToAnalyze.empty()) + Stream.EmitRecord(DELETE_EXPRS_TO_ANALYZE, DeleteExprsToAnalyze); +} + +ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, + Module *WritingModule) { + using namespace llvm; + + bool isModule = WritingModule != nullptr; + + // Make sure that the AST reader knows to finalize itself. + if (Chain) + Chain->finalizeForWriting(); + + ASTContext &Context = SemaRef.Context; + Preprocessor &PP = SemaRef.PP; + + // This needs to be done very early, since everything that writes + // SourceLocations or FileIDs depends on it. + computeNonAffectingInputFiles(); + + writeUnhashedControlBlock(PP, Context); + + // Write the set of weak, undeclared identifiers. We always write the + // entire table, since later PCH files in a PCH chain are only interested in + // the results at the end of the chain. + RecordData WeakUndeclaredIdentifiers; + for (const auto &WeakUndeclaredIdentifierList : + SemaRef.WeakUndeclaredIdentifiers) { + const IdentifierInfo *const II = WeakUndeclaredIdentifierList.first; + for (const auto &WI : WeakUndeclaredIdentifierList.second) { + AddIdentifierRef(II, WeakUndeclaredIdentifiers); + AddIdentifierRef(WI.getAlias(), WeakUndeclaredIdentifiers); + AddSourceLocation(WI.getLocation(), WeakUndeclaredIdentifiers); + } + } + + PrepareWritingSpecialDecls(SemaRef); // Write the control block WriteControlBlock(PP, Context, isysroot); @@ -5010,45 +5168,6 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, Stream.EmitRecord(METADATA_OLD_FORMAT, Record); } - const TranslationUnitDecl *TU = Context.getTranslationUnitDecl(); - - // Force all top level declarations to be emitted. - // - // We start emitting top level declarations from the module purview to - // implement the eliding unreachable declaration feature. - for (const auto *D : TU->noload_decls()) { - if (D->isFromASTFile()) - continue; - - if (GeneratingReducedBMI && D->isFromExplicitGlobalModule()) - continue; - - GetDeclRef(D); - } - - // Make sure visible decls, added to DeclContexts previously loaded from - // an AST file, are registered for serialization. Likewise for template - // specializations added to imported templates. - for (const auto *I : DeclsToEmitEvenIfUnreferenced) { - GetDeclRef(I); - } - - // Make sure all decls associated with an identifier are registered for - // serialization, if we're storing decls with identifiers. - if (!WritingModule || !getLangOpts().CPlusPlus) { - llvm::SmallVector IIs; - for (const auto &ID : PP.getIdentifierTable()) { - const IdentifierInfo *II = ID.second; - if (!Chain || !II->isFromAST() || II->hasChangedSinceDeserialization()) - IIs.push_back(II); - } - // Sort the identifiers to visit based on their name. - llvm::sort(IIs, llvm::deref>()); - for (const IdentifierInfo *II : IIs) - for (const Decl *D : SemaRef.IdResolver.decls(II)) - GetDeclRef(D); - } - // For method pool in the module, if it contains an entry for a selector, // the entry should be complete, containing everything introduced by that // module and all modules it imports. It's possible that the entry is out of @@ -5139,11 +5258,6 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, Buffer.data(), Buffer.size()); } - // Build a record containing all of the DeclsToCheckForDeferredDiags. - SmallVector DeclsToCheckForDeferredDiags; - for (auto *D : SemaRef.DeclsToCheckForDeferredDiags) - DeclsToCheckForDeferredDiags.push_back(GetDeclRef(D)); - WriteDeclAndTypes(Context); WriteFileDeclIDsMap(); @@ -5165,71 +5279,13 @@ ASTFileSignature ASTWriter::WriteASTCore(Sema &SemaRef, StringRef isysroot, Stream.EmitRecord(SPECIAL_TYPES, SpecialTypes); - // Write the record containing external, unnamed definitions. - if (!EagerlyDeserializedDecls.empty()) - Stream.EmitRecord(EAGERLY_DESERIALIZED_DECLS, EagerlyDeserializedDecls); - - if (!ModularCodegenDecls.empty()) - Stream.EmitRecord(MODULAR_CODEGEN_DECLS, ModularCodegenDecls); - - // Write the record containing tentative definitions. - if (!TentativeDefinitions.empty()) - Stream.EmitRecord(TENTATIVE_DEFINITIONS, TentativeDefinitions); - - // Write the record containing unused file scoped decls. - if (!UnusedFileScopedDecls.empty()) - Stream.EmitRecord(UNUSED_FILESCOPED_DECLS, UnusedFileScopedDecls); + WriteSpecialDeclRecords(SemaRef); // Write the record containing weak undeclared identifiers. if (!WeakUndeclaredIdentifiers.empty()) Stream.EmitRecord(WEAK_UNDECLARED_IDENTIFIERS, WeakUndeclaredIdentifiers); - // Write the record containing ext_vector type names. - if (!ExtVectorDecls.empty()) - Stream.EmitRecord(EXT_VECTOR_DECLS, ExtVectorDecls); - - // Write the record containing VTable uses information. - if (!VTableUses.empty()) - Stream.EmitRecord(VTABLE_USES, VTableUses); - - // Write the record containing potentially unused local typedefs. - if (!UnusedLocalTypedefNameCandidates.empty()) - Stream.EmitRecord(UNUSED_LOCAL_TYPEDEF_NAME_CANDIDATES, - UnusedLocalTypedefNameCandidates); - - // Write the record containing pending implicit instantiations. - if (!PendingInstantiations.empty()) - Stream.EmitRecord(PENDING_IMPLICIT_INSTANTIATIONS, PendingInstantiations); - - // Write the record containing declaration references of Sema. - if (!SemaDeclRefs.empty()) - Stream.EmitRecord(SEMA_DECL_REFS, SemaDeclRefs); - - // Write the record containing decls to be checked for deferred diags. - if (!DeclsToCheckForDeferredDiags.empty()) - Stream.EmitRecord(DECLS_TO_CHECK_FOR_DEFERRED_DIAGS, - DeclsToCheckForDeferredDiags); - - // Write the record containing CUDA-specific declaration references. - if (!CUDASpecialDeclRefs.empty()) - Stream.EmitRecord(CUDA_SPECIAL_DECL_REFS, CUDASpecialDeclRefs); - - // Write the delegating constructors. - if (!DelegatingCtorDecls.empty()) - Stream.EmitRecord(DELEGATING_CTORS, DelegatingCtorDecls); - - // Write the known namespaces. - if (!KnownNamespaces.empty()) - Stream.EmitRecord(KNOWN_NAMESPACES, KnownNamespaces); - - // Write the undefined internal functions and variables, and inline functions. - if (!UndefinedButUsed.empty()) - Stream.EmitRecord(UNDEFINED_BUT_USED, UndefinedButUsed); - - if (!DeleteExprsToAnalyze.empty()) - Stream.EmitRecord(DELETE_EXPRS_TO_ANALYZE, DeleteExprsToAnalyze); - if (!WritingModule) { // Write the submodules that were imported, if any. struct ModuleInfo {