Index: clangd/ClangdUnit.h =================================================================== --- clangd/ClangdUnit.h +++ clangd/ClangdUnit.h @@ -48,6 +48,8 @@ llvm::SmallVector FixIts; }; +struct PreambleData; + /// Stores and provides access to parsed AST. class ParsedAST { public: @@ -55,8 +57,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 +81,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 +104,7 @@ // Data, stored after parsing. std::vector Diags; std::vector TopLevelDecls; - std::vector PendingTopLevelDecls; + bool PreambleDeclsDeserialized; }; // Provides thread-safe access to ParsedAST. Index: clangd/ClangdUnit.cpp =================================================================== --- clangd/ClangdUnit.cpp +++ clangd/ClangdUnit.cpp @@ -878,8 +878,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, @@ -888,8 +887,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. @@ -911,15 +912,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 { @@ -1060,24 +1054,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; @@ -1111,14 +1106,15 @@ return Diags; } -ParsedAST::ParsedAST(std::unique_ptr Clang, +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); } @@ -1328,12 +1324,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()); } @@ -1342,9 +1334,9 @@ llvm::Optional NewAST; { trace::Span Tracer(llvm::Twine("Build: ") + 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) {