diff --git a/clang-tools-extra/clangd/Preamble.cpp b/clang-tools-extra/clangd/Preamble.cpp --- a/clang-tools-extra/clangd/Preamble.cpp +++ b/clang-tools-extra/clangd/Preamble.cpp @@ -20,7 +20,9 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/SourceManager.h" +#include "clang/Basic/TargetInfo.h" #include "clang/Basic/TokenKinds.h" +#include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/FrontendActions.h" #include "clang/Lex/HeaderSearch.h" @@ -66,10 +68,31 @@ llvm::makeArrayRef(LHS.CommandLine).equals(RHS.CommandLine); } +struct AliveAST { +public: + AliveAST(CompilerInstance &Clang) + : Invocation(Clang.getInvocationPtr()), + Diagnostics(&Clang.getDiagnostics()), FileMgr(&Clang.getFileManager()), + SourceMgr(&Clang.getSourceManager()), PP(Clang.getPreprocessorPtr()), + Context(&Clang.getASTContext()) {} + + ASTContext &getASTContext() { return *Context; } + const std::shared_ptr &getPreprocessor() { return PP; } + +private: + std::shared_ptr Invocation; + IntrusiveRefCntPtr Diagnostics; + IntrusiveRefCntPtr Target; + IntrusiveRefCntPtr AuxTarget; + IntrusiveRefCntPtr FileMgr; + IntrusiveRefCntPtr SourceMgr; + std::shared_ptr PP; + IntrusiveRefCntPtr Context; +}; + class CppFilePreambleCallbacks : public PreambleCallbacks { public: - CppFilePreambleCallbacks(PathRef File, PreambleParsedCallback ParsedCallback) - : File(File), ParsedCallback(ParsedCallback) {} + CppFilePreambleCallbacks(PathRef File) : File(File) {} IncludeStructure takeIncludes() { return std::move(Includes); } @@ -79,14 +102,12 @@ CanonicalIncludes takeCanonicalIncludes() { return std::move(CanonIncludes); } + AliveAST takeLife() { return std::move(*Alive); } + bool isMainFileIncludeGuarded() const { return IsMainFileIncludeGuarded; } void AfterExecute(CompilerInstance &CI) override { - if (ParsedCallback) { - trace::Span Tracer("Running PreambleCallback"); - ParsedCallback(CI.getASTContext(), CI.getPreprocessorPtr(), - CanonIncludes); - } + Alive.emplace(CI); const SourceManager &SM = CI.getSourceManager(); const FileEntry *MainFE = SM.getFileEntryForID(SM.getMainFileID()); @@ -131,7 +152,6 @@ private: PathRef File; - PreambleParsedCallback ParsedCallback; IncludeStructure Includes; CanonicalIncludes CanonIncludes; MainFileMacros Macros; @@ -140,6 +160,8 @@ std::unique_ptr IWYUHandler = nullptr; const clang::LangOptions *LangOpts = nullptr; const SourceManager *SourceMgr = nullptr; + + llvm::Optional Alive; }; // Represents directives other than includes, where basic textual information is @@ -374,7 +396,7 @@ // to read back. We rely on dynamic index for the comments instead. CI.getPreprocessorOpts().WriteCommentListToPCH = false; - CppFilePreambleCallbacks CapturedInfo(FileName, PreambleCallback); + CppFilePreambleCallbacks CapturedInfo(FileName); auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory); llvm::SmallString<32> AbsFileName(FileName); VFS->makeAbsolute(AbsFileName); @@ -402,6 +424,14 @@ Result->CanonIncludes = CapturedInfo.takeCanonicalIncludes(); Result->StatCache = std::move(StatCache); Result->MainIsIncludeGuarded = CapturedInfo.isMainFileIncludeGuarded(); + + if (PreambleCallback) { + trace::Span Tracer("Running PreambleCallback"); + auto Alive = CapturedInfo.takeLife(); + PreambleCallback(Alive.getASTContext(), Alive.getPreprocessor(), + Result->CanonIncludes); + } + return Result; } diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -233,6 +233,8 @@ return *Invocation; } + std::shared_ptr getInvocationPtr() { return Invocation; } + /// setInvocation - Replace the current invocation. void setInvocation(std::shared_ptr Value);