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/Basic/SourceManager.h"
34#include "clang/Frontend/CompilerInvocation.h"
35#include "clang/Frontend/PrecompiledPreamble.h"
36#include "clang/Lex/Lexer.h"
37#include "clang/Tooling/CompilationDatabase.h"
38#include "llvm/ADT/ArrayRef.h"
39#include "llvm/ADT/StringRef.h"
40
41#include <cstddef>
42#include <functional>
43#include <memory>
44#include <string>
45#include <utility>
46#include <vector>
47
48namespace clang {
49namespace clangd {
50
51/// The parsed preamble and associated data.
52///
53/// As we must avoid re-parsing the preamble, any information that can only
54/// be obtained during parsing must be eagerly captured and stored here.
56 PreambleData(PrecompiledPreamble Preamble) : Preamble(std::move(Preamble)) {}
57
58 // Version of the ParseInputs this preamble was built from.
59 std::string Version;
60 tooling::CompileCommand CompileCommand;
61 PrecompiledPreamble Preamble;
62 std::vector<Diag> Diags;
63 // Processes like code completions and go-to-definitions will need #include
64 // information, and their compile action skips preamble range.
66 // Captures #include-mapping information in #included headers.
67 include_cleaner::PragmaIncludes Pragmas;
68 // Macros defined in the preamble section of the main file.
69 // Users care about headers vs main-file, not preamble vs non-preamble.
70 // These should be treated as main-file entities e.g. for code completion.
72 // Pragma marks defined in the preamble section of the main file.
73 std::vector<PragmaMark> Marks;
74 // Cache of FS operations performed when building the preamble.
75 // When reusing a preamble, this cache can be consumed to save IO.
76 std::unique_ptr<PreambleFileStatusCache> StatCache;
78 // Whether there was a (possibly-incomplete) include-guard on the main file.
79 // We need to propagate this information "by hand" to subsequent parses.
81};
82
83using PreambleParsedCallback = std::function<void(ASTContext &, Preprocessor &,
84 const CanonicalIncludes &)>;
85
86/// Timings and statistics from the premble build. Unlike PreambleData, these
87/// do not need to be stored for later, but can be useful for logging, metrics,
88/// etc.
90 /// Total wall time it took to build preamble, in seconds.
92 /// Time spent in filesystem operations during the build, in seconds.
94
95 /// Estimate of the memory used while building the preamble.
96 /// This memory has been released when buildPreamble returns.
97 /// For example, this includes the size of the in-memory AST (ASTContext).
98 size_t BuildSize;
99 /// The serialized size of the preamble.
100 /// This storage is needed while the preamble is used (but may be on disk).
102};
103
104/// Build a preamble for the new inputs unless an old one can be reused.
105/// If \p PreambleCallback is set, it will be run on top of the AST while
106/// building the preamble.
107/// If Stats is not non-null, build statistics will be exported there.
108std::shared_ptr<const PreambleData>
109buildPreamble(PathRef FileName, CompilerInvocation CI,
110 const ParseInputs &Inputs, bool StoreInMemory,
111 PreambleParsedCallback PreambleCallback,
112 PreambleBuildStats *Stats = nullptr);
113
114/// Returns true if \p Preamble is reusable for \p Inputs. Note that it will
115/// return true when some missing headers are now available.
116/// FIXME: Should return more information about the delta between \p Preamble
117/// and \p Inputs, e.g. new headers.
119 const ParseInputs &Inputs, PathRef FileName,
120 const CompilerInvocation &CI);
121
122/// Stores information required to parse a TU using a (possibly stale) Baseline
123/// preamble. Later on this information can be injected into the main file by
124/// updating compiler invocation with \c apply. This injected section
125/// approximately reflects additions to the preamble in Modified contents, e.g.
126/// new include directives.
128public:
130 /// \p Preamble is used verbatim.
132 /// Builds a patch that contains new PP directives introduced to the preamble
133 /// section of \p Modified compared to \p Baseline.
134 /// FIXME: This only handles include directives, we should at least handle
135 /// define/undef.
136 static PreamblePatch createFullPatch(llvm::StringRef FileName,
137 const ParseInputs &Modified,
138 const PreambleData &Baseline);
139 static PreamblePatch createMacroPatch(llvm::StringRef FileName,
140 const ParseInputs &Modified,
141 const PreambleData &Baseline);
142 /// Returns the FileEntry for the preamble patch of MainFilePath in SM, if
143 /// any.
144 static const FileEntry *getPatchEntry(llvm::StringRef MainFilePath,
145 const SourceManager &SM);
146
147 /// Adjusts CI (which compiles the modified inputs) to be used with the
148 /// baseline preamble. This is done by inserting an artifical include to the
149 /// \p CI that contains new directives calculated in create.
150 void apply(CompilerInvocation &CI) const;
151
152 /// Returns #include directives from the \c Modified preamble that were
153 /// resolved using the \c Baseline preamble. This covers the new locations of
154 /// inclusions that were moved around, but not inclusions of new files. Those
155 /// will be recorded when parsing the main file: the includes in the injected
156 /// section will be resolved back to their spelled positions in the main file
157 /// using the presumed-location mechanism.
158 std::vector<Inclusion> preambleIncludes() const;
159
160 /// Returns preamble bounds for the Modified.
161 PreambleBounds modifiedBounds() const { return ModifiedBounds; }
162
163 /// Returns textual patch contents.
164 llvm::StringRef text() const { return PatchContents; }
165
166 /// Whether diagnostics generated using this patch are trustable.
167 bool preserveDiagnostics() const;
168
169 /// Returns diag locations for Modified contents.
170 llvm::ArrayRef<Diag> patchedDiags() const { return PatchedDiags; }
171
172 static constexpr llvm::StringLiteral HeaderName = "__preamble_patch__.h";
173
174 llvm::ArrayRef<PragmaMark> marks() const;
175 const MainFileMacros &mainFileMacros() const;
176
177private:
178 static PreamblePatch create(llvm::StringRef FileName,
179 const ParseInputs &Modified,
180 const PreambleData &Baseline,
182
183 PreamblePatch() = default;
184 std::string PatchContents;
185 std::string PatchFileName;
186 // Includes that are present in both Baseline and Modified. Used for
187 // patching includes of baseline preamble.
188 std::vector<Inclusion> PreambleIncludes;
189 // Diags that were attached to a line preserved in Modified contents.
190 std::vector<Diag> PatchedDiags;
191 PreambleBounds ModifiedBounds = {0, false};
192 const PreambleData *Baseline = nullptr;
193 std::vector<PragmaMark> PatchedMarks;
194 MainFileMacros PatchedMacros;
195};
196
197} // namespace clangd
198} // namespace clang
199
200#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_PREAMBLE_H
StringRef FileName
std::unique_ptr< CompilerInvocation > CI
Maps a definition location onto an #include file, based on a set of filename rules.
Stores information required to parse a TU using a (possibly stale) Baseline preamble.
Definition: Preamble.h:127
bool preserveDiagnostics() const
Whether diagnostics generated using this patch are trustable.
Definition: Preamble.cpp:913
const MainFileMacros & mainFileMacros() const
Definition: Preamble.cpp:923
llvm::ArrayRef< PragmaMark > marks() const
Definition: Preamble.cpp:917
void apply(CompilerInvocation &CI) const
Adjusts CI (which compiles the modified inputs) to be used with the baseline preamble.
Definition: Preamble.cpp:884
static PreamblePatch unmodified(const PreambleData &Preamble)
Preamble is used verbatim.
Definition: Preamble.cpp:904
llvm::ArrayRef< Diag > patchedDiags() const
Returns diag locations for Modified contents.
Definition: Preamble.h:170
llvm::StringRef text() const
Returns textual patch contents.
Definition: Preamble.h:164
static PreamblePatch createMacroPatch(llvm::StringRef FileName, const ParseInputs &Modified, const PreambleData &Baseline)
Definition: Preamble.cpp:878
static const FileEntry * getPatchEntry(llvm::StringRef MainFilePath, const SourceManager &SM)
Returns the FileEntry for the preamble patch of MainFilePath in SM, if any.
Definition: Preamble.cpp:929
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:872
static constexpr llvm::StringLiteral HeaderName
Definition: Preamble.h:172
std::vector< Inclusion > preambleIncludes() const
Returns #include directives from the Modified preamble that were resolved using the Baseline preamble...
Definition: Preamble.cpp:900
PreambleBounds modifiedBounds() const
Returns preamble bounds for the Modified.
Definition: Preamble.h:161
bool isPreambleCompatible(const PreambleData &Preamble, const ParseInputs &Inputs, PathRef FileName, const CompilerInvocation &CI)
Returns true if Preamble is reusable for Inputs.
Definition: Preamble.cpp:699
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:581
std::function< void(ASTContext &, Preprocessor &, const CanonicalIncludes &)> PreambleParsedCallback
Definition: Preamble.h:84
llvm::StringRef PathRef
A typedef to represent a ref to file path.
Definition: Path.h:29
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Information required to run clang, e.g. to parse AST or do code completion.
Definition: Compiler.h:48
Timings and statistics from the premble build.
Definition: Preamble.h:89
double FileSystemTime
Time spent in filesystem operations during the build, in seconds.
Definition: Preamble.h:93
size_t BuildSize
Estimate of the memory used while building the preamble.
Definition: Preamble.h:98
double TotalBuildTime
Total wall time it took to build preamble, in seconds.
Definition: Preamble.h:91
size_t SerializedSize
The serialized size of the preamble.
Definition: Preamble.h:101
The parsed preamble and associated data.
Definition: Preamble.h:55
std::vector< Diag > Diags
Definition: Preamble.h:62
std::vector< PragmaMark > Marks
Definition: Preamble.h:73
PrecompiledPreamble Preamble
Definition: Preamble.h:61
CanonicalIncludes CanonIncludes
Definition: Preamble.h:77
std::unique_ptr< PreambleFileStatusCache > StatCache
Definition: Preamble.h:76
PreambleData(PrecompiledPreamble Preamble)
Definition: Preamble.h:56
include_cleaner::PragmaIncludes Pragmas
Definition: Preamble.h:67
tooling::CompileCommand CompileCommand
Definition: Preamble.h:60
IncludeStructure Includes
Definition: Preamble.h:65
MainFileMacros Macros
Definition: Preamble.h:71