clang-tools  17.0.0git
Preamble.h
Go to the documentation of this file.
1 //===--- Preamble.h - Reusing expensive parts of the AST ---------*- C++-*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // The vast majority of code in a typical translation unit is in the headers
10 // included at the top of the file.
11 //
12 // The preamble optimization says that we can parse this code once, and reuse
13 // the result multiple times. The preamble is invalidated by changes to the
14 // code in the preamble region, to the compile command, or to files on disk.
15 //
16 // This is the most important optimization in clangd: it allows operations like
17 // code-completion to have sub-second latency. It is supported by the
18 // PrecompiledPreamble functionality in clang, which wraps the techniques used
19 // by PCH files, modules etc into a convenient interface.
20 //
21 //===----------------------------------------------------------------------===//
22 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREAMBLE_H
23 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREAMBLE_H
24 
25 #include "CollectMacros.h"
26 #include "Compiler.h"
27 #include "Diagnostics.h"
28 #include "FS.h"
29 #include "Headers.h"
30 #include "clang-include-cleaner/Record.h"
32 #include "support/Path.h"
33 #include "clang/Frontend/CompilerInvocation.h"
34 #include "clang/Frontend/PrecompiledPreamble.h"
35 #include "clang/Lex/Lexer.h"
36 #include "clang/Tooling/CompilationDatabase.h"
37 #include "llvm/ADT/StringRef.h"
38 
39 #include <memory>
40 #include <string>
41 #include <vector>
42 
43 namespace clang {
44 namespace clangd {
45 
46 /// The parsed preamble and associated data.
47 ///
48 /// As we must avoid re-parsing the preamble, any information that can only
49 /// be obtained during parsing must be eagerly captured and stored here.
50 struct PreambleData {
51  PreambleData(PrecompiledPreamble Preamble) : Preamble(std::move(Preamble)) {}
52 
53  // Version of the ParseInputs this preamble was built from.
54  std::string Version;
55  tooling::CompileCommand CompileCommand;
56  PrecompiledPreamble Preamble;
57  std::vector<Diag> Diags;
58  // Processes like code completions and go-to-definitions will need #include
59  // information, and their compile action skips preamble range.
61  // Captures #include-mapping information in #included headers.
62  include_cleaner::PragmaIncludes Pragmas;
63  // Macros defined in the preamble section of the main file.
64  // Users care about headers vs main-file, not preamble vs non-preamble.
65  // These should be treated as main-file entities e.g. for code completion.
67  // Pragma marks defined in the preamble section of the main file.
68  std::vector<PragmaMark> Marks;
69  // Cache of FS operations performed when building the preamble.
70  // When reusing a preamble, this cache can be consumed to save IO.
71  std::unique_ptr<PreambleFileStatusCache> StatCache;
73  // Whether there was a (possibly-incomplete) include-guard on the main file.
74  // We need to propagate this information "by hand" to subsequent parses.
75  bool MainIsIncludeGuarded = false;
76 };
77 
78 using PreambleParsedCallback = std::function<void(ASTContext &, Preprocessor &,
79  const CanonicalIncludes &)>;
80 
81 /// Timings and statistics from the premble build. Unlike PreambleData, these
82 /// do not need to be stored for later, but can be useful for logging, metrics,
83 /// etc.
85  /// Total wall time it took to build preamble, in seconds.
87  /// Time spent in filesystem operations during the build, in seconds.
89 
90  /// Estimate of the memory used while building the preamble.
91  /// This memory has been released when buildPreamble returns.
92  /// For example, this includes the size of the in-memory AST (ASTContext).
93  size_t BuildSize;
94  /// The serialized size of the preamble.
95  /// This storage is needed while the preamble is used (but may be on disk).
97 };
98 
99 /// Build a preamble for the new inputs unless an old one can be reused.
100 /// If \p PreambleCallback is set, it will be run on top of the AST while
101 /// building the preamble.
102 /// If Stats is not non-null, build statistics will be exported there.
103 std::shared_ptr<const PreambleData>
104 buildPreamble(PathRef FileName, CompilerInvocation CI,
105  const ParseInputs &Inputs, bool StoreInMemory,
106  PreambleParsedCallback PreambleCallback,
107  PreambleBuildStats *Stats = nullptr);
108 
109 /// Returns true if \p Preamble is reusable for \p Inputs. Note that it will
110 /// return true when some missing headers are now available.
111 /// FIXME: Should return more information about the delta between \p Preamble
112 /// and \p Inputs, e.g. new headers.
113 bool isPreambleCompatible(const PreambleData &Preamble,
115  const CompilerInvocation &CI);
116 
117 /// Stores information required to parse a TU using a (possibly stale) Baseline
118 /// preamble. Later on this information can be injected into the main file by
119 /// updating compiler invocation with \c apply. This injected section
120 /// approximately reflects additions to the preamble in Modified contents, e.g.
121 /// new include directives.
123 public:
124  enum class PatchType { MacroDirectives, All };
125  /// \p Preamble is used verbatim.
126  static PreamblePatch unmodified(const PreambleData &Preamble);
127  /// Builds a patch that contains new PP directives introduced to the preamble
128  /// section of \p Modified compared to \p Baseline.
129  /// FIXME: This only handles include directives, we should at least handle
130  /// define/undef.
131  static PreamblePatch createFullPatch(llvm::StringRef FileName,
132  const ParseInputs &Modified,
133  const PreambleData &Baseline);
134  static PreamblePatch createMacroPatch(llvm::StringRef FileName,
135  const ParseInputs &Modified,
136  const PreambleData &Baseline);
137 
138  /// Adjusts CI (which compiles the modified inputs) to be used with the
139  /// baseline preamble. This is done by inserting an artifical include to the
140  /// \p CI that contains new directives calculated in create.
141  void apply(CompilerInvocation &CI) const;
142 
143  /// Returns #include directives from the \c Modified preamble that were
144  /// resolved using the \c Baseline preamble. This covers the new locations of
145  /// inclusions that were moved around, but not inclusions of new files. Those
146  /// will be recorded when parsing the main file: the includes in the injected
147  /// section will be resolved back to their spelled positions in the main file
148  /// using the presumed-location mechanism.
149  std::vector<Inclusion> preambleIncludes() const;
150 
151  /// Returns preamble bounds for the Modified.
152  PreambleBounds modifiedBounds() const { return ModifiedBounds; }
153 
154  /// Returns textual patch contents.
155  llvm::StringRef text() const { return PatchContents; }
156 
157  /// Whether diagnostics generated using this patch are trustable.
158  bool preserveDiagnostics() const { return PatchContents.empty(); }
159 
160 private:
161  static PreamblePatch create(llvm::StringRef FileName,
162  const ParseInputs &Modified,
163  const PreambleData &Baseline,
165 
166  PreamblePatch() = default;
167  std::string PatchContents;
168  std::string PatchFileName;
169  /// Includes that are present in both \p Baseline and \p Modified. Used for
170  /// patching includes of baseline preamble.
171  std::vector<Inclusion> PreambleIncludes;
172  PreambleBounds ModifiedBounds = {0, false};
173 };
174 
175 /// Translates locations inside preamble patch to their main-file equivalent
176 /// using presumed locations. Returns \p Loc if it isn't inside preamble patch.
177 SourceLocation translatePreamblePatchLocation(SourceLocation Loc,
178  const SourceManager &SM);
179 
180 } // namespace clangd
181 } // namespace clang
182 
183 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREAMBLE_H
clang::clangd::buildPreamble
std::shared_ptr< const PreambleData > buildPreamble(PathRef FileName, CompilerInvocation CI, const ParseInputs &Inputs, bool StoreInMemory, PreambleParsedCallback PreambleCallback, PreambleBuildStats *Stats)
Build a preamble for the new inputs unless an old one can be reused.
Definition: Preamble.cpp:473
clang::clangd::PreambleData::MainIsIncludeGuarded
bool MainIsIncludeGuarded
Definition: Preamble.h:75
Loc
SourceLocation Loc
Definition: KernelNameRestrictionCheck.cpp:43
clang::clangd::PreambleData::StatCache
std::unique_ptr< PreambleFileStatusCache > StatCache
Definition: Preamble.h:71
clang::clangd::isPreambleCompatible
bool isPreambleCompatible(const PreambleData &Preamble, const ParseInputs &Inputs, PathRef FileName, const CompilerInvocation &CI)
Returns true if Preamble is reusable for Inputs.
Definition: Preamble.cpp:591
Headers.h
clang::clangd::PreamblePatch::text
llvm::StringRef text() const
Returns textual patch contents.
Definition: Preamble.h:155
Path.h
clang::clangd::PreambleData::Macros
MainFileMacros Macros
Definition: Preamble.h:66
clang::clangd::PreambleData::Preamble
PrecompiledPreamble Preamble
Definition: Preamble.h:56
CI
std::unique_ptr< CompilerInvocation > CI
Definition: TUScheduler.cpp:548
clang::clangd::PreamblePatch::unmodified
static PreamblePatch unmodified(const PreambleData &Preamble)
Preamble is used verbatim.
Definition: Preamble.cpp:755
clang::clangd::PreambleBuildStats::TotalBuildTime
double TotalBuildTime
Total wall time it took to build preamble, in seconds.
Definition: Preamble.h:86
clang::clangd::PreamblePatch
Stores information required to parse a TU using a (possibly stale) Baseline preamble.
Definition: Preamble.h:122
clang::clangd::PreambleBuildStats
Timings and statistics from the premble build.
Definition: Preamble.h:84
clang::clangd::PreambleData::Includes
IncludeStructure Includes
Definition: Preamble.h:60
clang::clangd::PreambleData::Pragmas
include_cleaner::PragmaIncludes Pragmas
Definition: Preamble.h:62
clang::clangd::PreambleBuildStats::SerializedSize
size_t SerializedSize
The serialized size of the preamble.
Definition: Preamble.h:96
clang::clangd::IncludeStructure
Definition: Headers.h:129
Inputs
ParseInputs Inputs
Definition: TUScheduler.cpp:549
clang::clangd::PreambleData::Version
std::string Version
Definition: Preamble.h:54
clang::clangd::PreamblePatch::apply
void apply(CompilerInvocation &CI) const
Adjusts CI (which compiles the modified inputs) to be used with the baseline preamble.
Definition: Preamble.cpp:735
clang::clangd::ParseInputs
Information required to run clang, e.g. to parse AST or do code completion.
Definition: Compiler.h:48
CanonicalIncludes.h
clang::clangd::PreamblePatch::preserveDiagnostics
bool preserveDiagnostics() const
Whether diagnostics generated using this patch are trustable.
Definition: Preamble.h:158
clang::clangd::PreambleData
The parsed preamble and associated data.
Definition: Preamble.h:50
clang::clangd::CanonicalIncludes
Maps a definition location onto an #include file, based on a set of filename rules.
Definition: CanonicalIncludes.h:37
clang::clangd::PreambleBuildStats::FileSystemTime
double FileSystemTime
Time spent in filesystem operations during the build, in seconds.
Definition: Preamble.h:88
clang::clangd::PreamblePatch::createMacroPatch
static PreamblePatch createMacroPatch(llvm::StringRef FileName, const ParseInputs &Modified, const PreambleData &Baseline)
Definition: Preamble.cpp:729
clang::clangd::PreamblePatch::PatchType::MacroDirectives
@ MacroDirectives
clang::clangd::PreamblePatch::PatchType
PatchType
Definition: Preamble.h:124
CollectMacros.h
clang::clangd::MainFileMacros
Definition: CollectMacros.h:29
clang::clangd::PreambleData::Diags
std::vector< Diag > Diags
Definition: Preamble.h:57
Diagnostics.h
FileName
StringRef FileName
Definition: KernelNameRestrictionCheck.cpp:44
clang::clangd::PreambleData::Marks
std::vector< PragmaMark > Marks
Definition: Preamble.h:68
clang::clangd::PreambleData::CompileCommand
tooling::CompileCommand CompileCommand
Definition: Preamble.h:55
clang::clangd::PreamblePatch::modifiedBounds
PreambleBounds modifiedBounds() const
Returns preamble bounds for the Modified.
Definition: Preamble.h:152
Compiler.h
clang::clangd::PreamblePatch::createFullPatch
static PreamblePatch createFullPatch(llvm::StringRef FileName, const ParseInputs &Modified, const PreambleData &Baseline)
Builds a patch that contains new PP directives introduced to the preamble section of Modified compare...
Definition: Preamble.cpp:723
clang::clangd::PathRef
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:29
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
FS.h
clang::clangd::PreambleBuildStats::BuildSize
size_t BuildSize
Estimate of the memory used while building the preamble.
Definition: Preamble.h:93
clang::clangd::PreambleData::PreambleData
PreambleData(PrecompiledPreamble Preamble)
Definition: Preamble.h:51
clang::clangd::PreambleData::CanonIncludes
CanonicalIncludes CanonIncludes
Definition: Preamble.h:72
clang::clangd::PreambleParsedCallback
std::function< void(ASTContext &, Preprocessor &, const CanonicalIncludes &)> PreambleParsedCallback
Definition: Preamble.h:79
clang::clangd::PreamblePatch::preambleIncludes
std::vector< Inclusion > preambleIncludes() const
Returns #include directives from the Modified preamble that were resolved using the Baseline preamble...
Definition: Preamble.cpp:751
clang::clangd::PreamblePatch::PatchType::All
@ All
clang::clangd::translatePreamblePatchLocation
SourceLocation translatePreamblePatchLocation(SourceLocation Loc, const SourceManager &SM)
Translates locations inside preamble patch to their main-file equivalent using presumed locations.
Definition: Preamble.cpp:762