Mercurial > hg > CbC > CbC_llvm
view clang-tools-extra/clangd/Preamble.h @ 221:79ff65ed7e25
LLVM12 Original
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 15 Jun 2021 19:15:29 +0900 |
parents | 0572611fdcc8 |
children | 5f20bc1ed4ff |
line wrap: on
line source
//===--- Preamble.h - Reusing expensive parts of the AST ---------*- C++-*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // The vast majority of code in a typical translation unit is in the headers // included at the top of the file. // // The preamble optimization says that we can parse this code once, and reuse // the result multiple times. The preamble is invalidated by changes to the // code in the preamble region, to the compile command, or to files on disk. // // This is the most important optimization in clangd: it allows operations like // code-completion to have sub-second latency. It is supported by the // PrecompiledPreamble functionality in clang, which wraps the techniques used // by PCH files, modules etc into a convenient interface. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREAMBLE_H #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREAMBLE_H #include "CollectMacros.h" #include "Compiler.h" #include "Diagnostics.h" #include "FS.h" #include "Headers.h" #include "index/CanonicalIncludes.h" #include "support/Path.h" #include "clang/Frontend/CompilerInvocation.h" #include "clang/Frontend/PrecompiledPreamble.h" #include "clang/Lex/Lexer.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/StringRef.h" #include <memory> #include <string> #include <vector> namespace clang { namespace clangd { /// The parsed preamble and associated data. /// /// As we must avoid re-parsing the preamble, any information that can only /// be obtained during parsing must be eagerly captured and stored here. struct PreambleData { PreambleData(const ParseInputs &Inputs, PrecompiledPreamble Preamble, std::vector<Diag> Diags, IncludeStructure Includes, MainFileMacros Macros, std::unique_ptr<PreambleFileStatusCache> StatCache, CanonicalIncludes CanonIncludes); // Version of the ParseInputs this preamble was built from. std::string Version; tooling::CompileCommand CompileCommand; PrecompiledPreamble Preamble; std::vector<Diag> Diags; // Processes like code completions and go-to-definitions will need #include // information, and their compile action skips preamble range. IncludeStructure Includes; // Macros defined in the preamble section of the main file. // Users care about headers vs main-file, not preamble vs non-preamble. // These should be treated as main-file entities e.g. for code completion. MainFileMacros Macros; // Cache of FS operations performed when building the preamble. // When reusing a preamble, this cache can be consumed to save IO. std::unique_ptr<PreambleFileStatusCache> StatCache; CanonicalIncludes CanonIncludes; }; using PreambleParsedCallback = std::function<void(ASTContext &, std::shared_ptr<clang::Preprocessor>, const CanonicalIncludes &)>; /// Build a preamble for the new inputs unless an old one can be reused. /// If \p PreambleCallback is set, it will be run on top of the AST while /// building the preamble. std::shared_ptr<const PreambleData> buildPreamble(PathRef FileName, CompilerInvocation CI, const ParseInputs &Inputs, bool StoreInMemory, PreambleParsedCallback PreambleCallback); /// Returns true if \p Preamble is reusable for \p Inputs. Note that it will /// return true when some missing headers are now available. /// FIXME: Should return more information about the delta between \p Preamble /// and \p Inputs, e.g. new headers. bool isPreambleCompatible(const PreambleData &Preamble, const ParseInputs &Inputs, PathRef FileName, const CompilerInvocation &CI); /// Stores information required to parse a TU using a (possibly stale) Baseline /// preamble. Later on this information can be injected into the main file by /// updating compiler invocation with \c apply. This injected section /// approximately reflects additions to the preamble in Modified contents, e.g. /// new include directives. class PreamblePatch { public: /// \p Preamble is used verbatim. static PreamblePatch unmodified(const PreambleData &Preamble); /// Builds a patch that contains new PP directives introduced to the preamble /// section of \p Modified compared to \p Baseline. /// FIXME: This only handles include directives, we should at least handle /// define/undef. static PreamblePatch create(llvm::StringRef FileName, const ParseInputs &Modified, const PreambleData &Baseline); /// Adjusts CI (which compiles the modified inputs) to be used with the /// baseline preamble. This is done by inserting an artifical include to the /// \p CI that contains new directives calculated in create. void apply(CompilerInvocation &CI) const; /// Returns #include directives from the \c Modified preamble that were /// resolved using the \c Baseline preamble. This covers the new locations of /// inclusions that were moved around, but not inclusions of new files. Those /// will be recorded when parsing the main file: the includes in the injected /// section will be resolved back to their spelled positions in the main file /// using the presumed-location mechanism. std::vector<Inclusion> preambleIncludes() const; /// Returns preamble bounds for the Modified. PreambleBounds modifiedBounds() const { return ModifiedBounds; } /// Returns textual patch contents. llvm::StringRef text() const { return PatchContents; } /// Whether diagnostics generated using this patch are trustable. bool preserveDiagnostics() const { return PatchContents.empty(); } private: PreamblePatch() = default; std::string PatchContents; std::string PatchFileName; /// Includes that are present in both \p Baseline and \p Modified. Used for /// patching includes of baseline preamble. std::vector<Inclusion> PreambleIncludes; PreambleBounds ModifiedBounds = {0, false}; }; /// Translates locations inside preamble patch to their main-file equivalent /// using presumed locations. Returns \p Loc if it isn't inside preamble patch. SourceLocation translatePreamblePatchLocation(SourceLocation Loc, const SourceManager &SM); } // namespace clangd } // namespace clang #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREAMBLE_H