ilya-biryukov created this revision. In-memory preambles will not be copied anymore, so we need to make sure they outlive the AST.
https://reviews.llvm.org/D40301 Files: clangd/ClangdUnit.cpp clangd/ClangdUnit.h
Index: clangd/ClangdUnit.h =================================================================== --- clangd/ClangdUnit.h +++ clangd/ClangdUnit.h @@ -48,15 +48,16 @@ llvm::SmallVector<tooling::Replacement, 1> FixIts; }; +struct PreambleData; + /// Stores and provides access to parsed AST. class ParsedAST { public: /// Attempts to run Clang and store parsed AST. If \p Preamble is non-null /// it is reused during parsing. static llvm::Optional<ParsedAST> Build(std::unique_ptr<clang::CompilerInvocation> CI, - const PrecompiledPreamble *Preamble, - ArrayRef<serialization::DeclID> PreambleDeclIDs, + std::shared_ptr<const PreambleData> Preamble, std::unique_ptr<llvm::MemoryBuffer> Buffer, std::shared_ptr<PCHContainerOperations> PCHs, IntrusiveRefCntPtr<vfs::FileSystem> VFS, clangd::Logger &Logger); @@ -80,15 +81,18 @@ const std::vector<DiagWithFixIts> &getDiagnostics() const; private: - ParsedAST(std::unique_ptr<CompilerInstance> Clang, + ParsedAST(std::shared_ptr<const PreambleData> Preamble, + std::unique_ptr<CompilerInstance> Clang, std::unique_ptr<FrontendAction> Action, std::vector<const Decl *> TopLevelDecls, - std::vector<serialization::DeclID> PendingTopLevelDecls, std::vector<DiagWithFixIts> 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<const PreambleData> 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<DiagWithFixIts> Diags; std::vector<const Decl *> TopLevelDecls; - std::vector<serialization::DeclID> PendingTopLevelDecls; + bool PreambleDeclsDeserialized; }; // Provides thread-safe access to ParsedAST. Index: clangd/ClangdUnit.cpp =================================================================== --- clangd/ClangdUnit.cpp +++ clangd/ClangdUnit.cpp @@ -878,18 +878,19 @@ llvm::Optional<ParsedAST> ParsedAST::Build(std::unique_ptr<clang::CompilerInvocation> CI, - const PrecompiledPreamble *Preamble, - ArrayRef<serialization::DeclID> PreambleDeclIDs, + std::shared_ptr<const PreambleData> Preamble, std::unique_ptr<llvm::MemoryBuffer> Buffer, std::shared_ptr<PCHContainerOperations> PCHs, IntrusiveRefCntPtr<vfs::FileSystem> VFS, clangd::Logger &Logger) { std::vector<DiagWithFixIts> 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<const Decl *> ParsedDecls = Action->takeTopLevelDecls(); - std::vector<serialization::DeclID> 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<const Decl *> 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<CompilerInstance> Clang, +ParsedAST::ParsedAST(std::shared_ptr<const PreambleData> Preamble, + std::unique_ptr<CompilerInstance> Clang, std::unique_ptr<FrontendAction> Action, std::vector<const Decl *> TopLevelDecls, - std::vector<serialization::DeclID> PendingTopLevelDecls, std::vector<DiagWithFixIts> 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,23 +1324,19 @@ } // unlock Mutex // Prepare the Preamble and supplementary data for rebuilding AST. - const PrecompiledPreamble *PreambleForAST = nullptr; - ArrayRef<serialization::DeclID> SerializedPreambleDecls = llvm::None; std::vector<DiagWithFixIts> Diagnostics; if (NewPreamble) { - PreambleForAST = &NewPreamble->Preamble; - SerializedPreambleDecls = NewPreamble->TopLevelDeclIDs; Diagnostics.insert(Diagnostics.begin(), NewPreamble->Diags.begin(), NewPreamble->Diags.end()); } // Compute updated AST. llvm::Optional<ParsedAST> 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) {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits