Index: clang-tools-extra/trunk/clangd/ClangdUnit.h =================================================================== --- clang-tools-extra/trunk/clangd/ClangdUnit.h +++ clang-tools-extra/trunk/clangd/ClangdUnit.h @@ -48,6 +48,17 @@ llvm::SmallVector FixIts; }; +// Stores Preamble and associated data. +struct PreambleData { + PreambleData(PrecompiledPreamble Preamble, + std::vector TopLevelDeclIDs, + std::vector Diags); + + PrecompiledPreamble Preamble; + std::vector TopLevelDeclIDs; + std::vector Diags; +}; + /// Stores and provides access to parsed AST. class ParsedAST { public: @@ -55,8 +66,7 @@ /// it is reused during parsing. static llvm::Optional Build(std::unique_ptr CI, - const PrecompiledPreamble *Preamble, - ArrayRef PreambleDeclIDs, + std::shared_ptr Preamble, std::unique_ptr Buffer, std::shared_ptr PCHs, IntrusiveRefCntPtr VFS, clangd::Logger &Logger); @@ -80,15 +90,18 @@ const std::vector &getDiagnostics() const; private: - ParsedAST(std::unique_ptr Clang, + ParsedAST(std::shared_ptr Preamble, + std::unique_ptr Clang, std::unique_ptr Action, std::vector TopLevelDecls, - std::vector PendingTopLevelDecls, std::vector Diags); private: void ensurePreambleDeclsDeserialized(); + // In-memory preambles must outlive the AST, it is important that this member + // goes before Clang and Action. + std::shared_ptr Preamble; // We store an "incomplete" FrontendAction (i.e. no EndSourceFile was called // on it) and CompilerInstance used to run it. That way we don't have to do // complex memory management of all Clang structures on our own. (They are @@ -100,7 +113,7 @@ // Data, stored after parsing. std::vector Diags; std::vector TopLevelDecls; - std::vector PendingTopLevelDecls; + bool PreambleDeclsDeserialized; }; // Provides thread-safe access to ParsedAST. @@ -124,17 +137,6 @@ mutable llvm::Optional AST; }; -// Stores Preamble and associated data. -struct PreambleData { - PreambleData(PrecompiledPreamble Preamble, - std::vector TopLevelDeclIDs, - std::vector Diags); - - PrecompiledPreamble Preamble; - std::vector TopLevelDeclIDs; - std::vector Diags; -}; - /// Manages resources, required by clangd. Allows to rebuild file with new /// contents, and provides AST and Preamble for it. class CppFile : public std::enable_shared_from_this { Index: clang-tools-extra/trunk/clangd/ClangdUnit.cpp =================================================================== --- clang-tools-extra/trunk/clangd/ClangdUnit.cpp +++ clang-tools-extra/trunk/clangd/ClangdUnit.cpp @@ -879,8 +879,7 @@ llvm::Optional ParsedAST::Build(std::unique_ptr CI, - const PrecompiledPreamble *Preamble, - ArrayRef PreambleDeclIDs, + std::shared_ptr Preamble, std::unique_ptr Buffer, std::shared_ptr PCHs, IntrusiveRefCntPtr VFS, @@ -889,8 +888,10 @@ std::vector ASTDiags; StoreDiagsConsumer UnitDiagsConsumer(/*ref*/ ASTDiags); + const PrecompiledPreamble *PreamblePCH = + Preamble ? &Preamble->Preamble : nullptr; auto Clang = prepareCompilerInstance( - std::move(CI), Preamble, std::move(Buffer), std::move(PCHs), + std::move(CI), PreamblePCH, std::move(Buffer), std::move(PCHs), std::move(VFS), /*ref*/ UnitDiagsConsumer); // Recover resources if we crash before exiting this method. @@ -912,15 +913,8 @@ Clang->getDiagnostics().setClient(new EmptyDiagsConsumer); std::vector ParsedDecls = Action->takeTopLevelDecls(); - std::vector PendingDecls; - if (Preamble) { - PendingDecls.reserve(PreambleDeclIDs.size()); - PendingDecls.insert(PendingDecls.begin(), PreambleDeclIDs.begin(), - PreambleDeclIDs.end()); - } - - return ParsedAST(std::move(Clang), std::move(Action), std::move(ParsedDecls), - std::move(PendingDecls), std::move(ASTDiags)); + return ParsedAST(std::move(Preamble), std::move(Clang), std::move(Action), + std::move(ParsedDecls), std::move(ASTDiags)); } namespace { @@ -1061,24 +1055,25 @@ } void ParsedAST::ensurePreambleDeclsDeserialized() { - if (PendingTopLevelDecls.empty()) + if (PreambleDeclsDeserialized || !Preamble) return; std::vector Resolved; - Resolved.reserve(PendingTopLevelDecls.size()); + Resolved.reserve(Preamble->TopLevelDeclIDs.size()); ExternalASTSource &Source = *getASTContext().getExternalSource(); - for (serialization::DeclID TopLevelDecl : PendingTopLevelDecls) { + for (serialization::DeclID TopLevelDecl : Preamble->TopLevelDeclIDs) { // Resolve the declaration ID to an actual declaration, possibly // deserializing the declaration in the process. if (Decl *D = Source.GetExternalDecl(TopLevelDecl)) Resolved.push_back(D); } - TopLevelDecls.reserve(TopLevelDecls.size() + PendingTopLevelDecls.size()); + TopLevelDecls.reserve(TopLevelDecls.size() + + Preamble->TopLevelDeclIDs.size()); TopLevelDecls.insert(TopLevelDecls.begin(), Resolved.begin(), Resolved.end()); - PendingTopLevelDecls.clear(); + PreambleDeclsDeserialized = true; } ParsedAST::ParsedAST(ParsedAST &&Other) = default; @@ -1112,14 +1107,21 @@ return Diags; } -ParsedAST::ParsedAST(std::unique_ptr Clang, +PreambleData::PreambleData(PrecompiledPreamble Preamble, + std::vector TopLevelDeclIDs, + std::vector Diags) + : Preamble(std::move(Preamble)), + TopLevelDeclIDs(std::move(TopLevelDeclIDs)), Diags(std::move(Diags)) {} + +ParsedAST::ParsedAST(std::shared_ptr Preamble, + std::unique_ptr Clang, std::unique_ptr Action, std::vector TopLevelDecls, - std::vector PendingTopLevelDecls, std::vector Diags) - : Clang(std::move(Clang)), Action(std::move(Action)), - Diags(std::move(Diags)), TopLevelDecls(std::move(TopLevelDecls)), - PendingTopLevelDecls(std::move(PendingTopLevelDecls)) { + : Preamble(std::move(Preamble)), Clang(std::move(Clang)), + Action(std::move(Action)), Diags(std::move(Diags)), + TopLevelDecls(std::move(TopLevelDecls)), + PreambleDeclsDeserialized(false) { assert(this->Clang); assert(this->Action); } @@ -1130,12 +1132,6 @@ ParsedASTWrapper::ParsedASTWrapper(llvm::Optional AST) : AST(std::move(AST)) {} -PreambleData::PreambleData(PrecompiledPreamble Preamble, - std::vector TopLevelDeclIDs, - std::vector Diags) - : Preamble(std::move(Preamble)), - TopLevelDeclIDs(std::move(TopLevelDeclIDs)), Diags(std::move(Diags)) {} - std::shared_ptr CppFile::Create(PathRef FileName, tooling::CompileCommand Command, bool StorePreamblesInMemory, @@ -1330,12 +1326,8 @@ } // unlock Mutex // Prepare the Preamble and supplementary data for rebuilding AST. - const PrecompiledPreamble *PreambleForAST = nullptr; - ArrayRef SerializedPreambleDecls = llvm::None; std::vector Diagnostics; if (NewPreamble) { - PreambleForAST = &NewPreamble->Preamble; - SerializedPreambleDecls = NewPreamble->TopLevelDeclIDs; Diagnostics.insert(Diagnostics.begin(), NewPreamble->Diags.begin(), NewPreamble->Diags.end()); } @@ -1345,9 +1337,9 @@ { trace::Span Tracer("Build"); SPAN_ATTACH(Tracer, "File", That->FileName); - NewAST = ParsedAST::Build( - std::move(CI), PreambleForAST, SerializedPreambleDecls, - std::move(ContentsBuffer), PCHs, VFS, That->Logger); + NewAST = + ParsedAST::Build(std::move(CI), std::move(NewPreamble), + std::move(ContentsBuffer), PCHs, VFS, That->Logger); } if (NewAST) {