Warning: That file was not part of the compilation database. It may have many parsing errors.

1//===--- PrecompiledPreamble.h - Build precompiled preambles ----*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Helper class to build precompiled preamble.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_FRONTEND_PRECOMPILED_PREAMBLE_H
15#define LLVM_CLANG_FRONTEND_PRECOMPILED_PREAMBLE_H
16
17#include "clang/Lex/Lexer.h"
18#include "clang/Lex/Preprocessor.h"
19#include "llvm/ADT/IntrusiveRefCntPtr.h"
20#include "llvm/Support/AlignOf.h"
21#include "llvm/Support/MD5.h"
22#include <cstddef>
23#include <memory>
24#include <system_error>
25#include <type_traits>
26
27namespace llvm {
28class MemoryBuffer;
29}
30
31namespace clang {
32namespace vfs {
33class FileSystem;
34}
35
36class CompilerInstance;
37class CompilerInvocation;
38class DeclGroupRef;
39class PCHContainerOperations;
40
41/// Runs lexer to compute suggested preamble bounds.
42PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts,
43 llvm::MemoryBuffer *Buffer,
44 unsigned MaxLines);
45
46class PreambleCallbacks;
47
48/// A class holding a PCH and all information to check whether it is valid to
49/// reuse the PCH for the subsequent runs. Use BuildPreamble to create PCH and
50/// CanReusePreamble + AddImplicitPreamble to make use of it.
51class PrecompiledPreamble {
52 class PCHStorage;
53 struct PreambleFileHash;
54
55public:
56 /// Try to build PrecompiledPreamble for \p Invocation. See
57 /// BuildPreambleError for possible error codes.
58 ///
59 /// \param Invocation Original CompilerInvocation with options to compile the
60 /// file.
61 ///
62 /// \param MainFileBuffer Buffer with the contents of the main file.
63 ///
64 /// \param Bounds Bounds of the preamble, result of calling
65 /// ComputePreambleBounds.
66 ///
67 /// \param Diagnostics Diagnostics engine to be used while building the
68 /// preamble.
69 ///
70 /// \param VFS An instance of vfs::FileSystem to be used for file
71 /// accesses.
72 ///
73 /// \param PCHContainerOps An instance of PCHContainerOperations.
74 ///
75 /// \param StoreInMemory Store PCH in memory. If false, PCH will be stored in
76 /// a temporary file.
77 ///
78 /// \param Callbacks A set of callbacks to be executed when building
79 /// the preamble.
80 static llvm::ErrorOr<PrecompiledPreamble>
81 Build(const CompilerInvocation &Invocation,
82 const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
83 DiagnosticsEngine &Diagnostics, IntrusiveRefCntPtr<vfs::FileSystem> VFS,
84 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
85 bool StoreInMemory, PreambleCallbacks &Callbacks);
86
87 PrecompiledPreamble(PrecompiledPreamble &&) = default;
88 PrecompiledPreamble &operator=(PrecompiledPreamble &&) = default;
89
90 /// PreambleBounds used to build the preamble.
91 PreambleBounds getBounds() const;
92
93 /// Returns the size, in bytes, that preamble takes on disk or in memory.
94 /// For on-disk preambles returns 0 if filesystem operations fail. Intended to
95 /// be used for logging and debugging purposes only.
96 std::size_t getSize() const;
97
98 /// Check whether PrecompiledPreamble can be reused for the new contents(\p
99 /// MainFileBuffer) of the main file.
100 bool CanReuse(const CompilerInvocation &Invocation,
101 const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
102 vfs::FileSystem *VFS) const;
103
104 /// Changes options inside \p CI to use PCH from this preamble. Also remaps
105 /// main file to \p MainFileBuffer and updates \p VFS to ensure the preamble
106 /// is accessible.
107 /// Requires that CanReuse() is true.
108 /// For in-memory preambles, PrecompiledPreamble instance continues to own the
109 /// MemoryBuffer with the Preamble after this method returns. The caller is
110 /// responsible for making sure the PrecompiledPreamble instance outlives the
111 /// compiler run and the AST that will be using the PCH.
112 void AddImplicitPreamble(CompilerInvocation &CI,
113 IntrusiveRefCntPtr<vfs::FileSystem> &VFS,
114 llvm::MemoryBuffer *MainFileBuffer) const;
115
116 /// Configure \p CI to use this preamble.
117 /// Like AddImplicitPreamble, but doesn't assume CanReuse() is true.
118 /// If this preamble does not match the file, it may parse differently.
119 void OverridePreamble(CompilerInvocation &CI,
120 IntrusiveRefCntPtr<vfs::FileSystem> &VFS,
121 llvm::MemoryBuffer *MainFileBuffer) const;
122
123private:
124 PrecompiledPreamble(PCHStorage Storage, std::vector<char> PreambleBytes,
125 bool PreambleEndsAtStartOfLine,
126 llvm::StringMap<PreambleFileHash> FilesInPreamble);
127
128 /// A temp file that would be deleted on destructor call. If destructor is not
129 /// called for any reason, the file will be deleted at static objects'
130 /// destruction.
131 /// An assertion will fire if two TempPCHFiles are created with the same name,
132 /// so it's not intended to be used outside preamble-handling.
133 class TempPCHFile {
134 public:
135 // A main method used to construct TempPCHFile.
136 static llvm::ErrorOr<TempPCHFile> CreateNewPreamblePCHFile();
137
138 /// Call llvm::sys::fs::createTemporaryFile to create a new temporary file.
139 static llvm::ErrorOr<TempPCHFile> createInSystemTempDir(const Twine &Prefix,
140 StringRef Suffix);
141 /// Create a new instance of TemporaryFile for file at \p Path. Use with
142 /// extreme caution, there's an assertion checking that there's only a
143 /// single instance of TempPCHFile alive for each path.
144 static llvm::ErrorOr<TempPCHFile> createFromCustomPath(const Twine &Path);
145
146 private:
147 TempPCHFile(std::string FilePath);
148
149 public:
150 TempPCHFile(TempPCHFile &&Other);
151 TempPCHFile &operator=(TempPCHFile &&Other);
152
153 TempPCHFile(const TempPCHFile &) = delete;
154 ~TempPCHFile();
155
156 /// A path where temporary file is stored.
157 llvm::StringRef getFilePath() const;
158
159 private:
160 void RemoveFileIfPresent();
161
162 private:
163 llvm::Optional<std::string> FilePath;
164 };
165
166 class InMemoryPreamble {
167 public:
168 std::string Data;
169 };
170
171 class PCHStorage {
172 public:
173 enum class Kind { Empty, InMemory, TempFile };
174
175 PCHStorage() = default;
176 PCHStorage(TempPCHFile File);
177 PCHStorage(InMemoryPreamble Memory);
178
179 PCHStorage(const PCHStorage &) = delete;
180 PCHStorage &operator=(const PCHStorage &) = delete;
181
182 PCHStorage(PCHStorage &&Other);
183 PCHStorage &operator=(PCHStorage &&Other);
184
185 ~PCHStorage();
186
187 Kind getKind() const;
188
189 TempPCHFile &asFile();
190 const TempPCHFile &asFile() const;
191
192 InMemoryPreamble &asMemory();
193 const InMemoryPreamble &asMemory() const;
194
195 private:
196 void destroy();
197 void setEmpty();
198
199 private:
200 Kind StorageKind = Kind::Empty;
201 llvm::AlignedCharArrayUnion<TempPCHFile, InMemoryPreamble> Storage = {};
202 };
203
204 /// Data used to determine if a file used in the preamble has been changed.
205 struct PreambleFileHash {
206 /// All files have size set.
207 off_t Size = 0;
208
209 /// Modification time is set for files that are on disk. For memory
210 /// buffers it is zero.
211 time_t ModTime = 0;
212
213 /// Memory buffers have MD5 instead of modification time. We don't
214 /// compute MD5 for on-disk files because we hope that modification time is
215 /// enough to tell if the file was changed.
216 llvm::MD5::MD5Result MD5 = {};
217
218 static PreambleFileHash createForFile(off_t Size, time_t ModTime);
219 static PreambleFileHash
220 createForMemoryBuffer(const llvm::MemoryBuffer *Buffer);
221
222 friend bool operator==(const PreambleFileHash &LHS,
223 const PreambleFileHash &RHS) {
224 return LHS.Size == RHS.Size && LHS.ModTime == RHS.ModTime &&
225 LHS.MD5 == RHS.MD5;
226 }
227 friend bool operator!=(const PreambleFileHash &LHS,
228 const PreambleFileHash &RHS) {
229 return !(LHS == RHS);
230 }
231 };
232
233 /// Helper function to set up PCH for the preamble into \p CI and \p VFS to
234 /// with the specified \p Bounds.
235 void configurePreamble(PreambleBounds Bounds, CompilerInvocation &CI,
236 IntrusiveRefCntPtr<vfs::FileSystem> &VFS,
237 llvm::MemoryBuffer *MainFileBuffer) const;
238
239 /// Sets up the PreprocessorOptions and changes VFS, so that PCH stored in \p
240 /// Storage is accessible to clang. This method is an implementation detail of
241 /// AddImplicitPreamble.
242 static void setupPreambleStorage(const PCHStorage &Storage,
243 PreprocessorOptions &PreprocessorOpts,
244 IntrusiveRefCntPtr<vfs::FileSystem> &VFS);
245
246 /// Manages the memory buffer or temporary file that stores the PCH.
247 PCHStorage Storage;
248 /// Keeps track of the files that were used when computing the
249 /// preamble, with both their buffer size and their modification time.
250 ///
251 /// If any of the files have changed from one compile to the next,
252 /// the preamble must be thrown away.
253 llvm::StringMap<PreambleFileHash> FilesInPreamble;
254 /// The contents of the file that was used to precompile the preamble. Only
255 /// contains first PreambleBounds::Size bytes. Used to compare if the relevant
256 /// part of the file has not changed, so that preamble can be reused.
257 std::vector<char> PreambleBytes;
258 /// See PreambleBounds::PreambleEndsAtStartOfLine
259 bool PreambleEndsAtStartOfLine;
260};
261
262/// A set of callbacks to gather useful information while building a preamble.
263class PreambleCallbacks {
264public:
265 virtual ~PreambleCallbacks() = default;
266
267 /// Called before FrontendAction::BeginSourceFile.
268 /// Can be used to store references to various CompilerInstance fields
269 /// (e.g. SourceManager) that may be interesting to the consumers of other
270 /// callbacks.
271 virtual void BeforeExecute(CompilerInstance &CI);
272 /// Called after FrontendAction::Execute(), but before
273 /// FrontendAction::EndSourceFile(). Can be used to transfer ownership of
274 /// various CompilerInstance fields before they are destroyed.
275 virtual void AfterExecute(CompilerInstance &CI);
276 /// Called after PCH has been emitted. \p Writer may be used to retrieve
277 /// information about AST, serialized in PCH.
278 virtual void AfterPCHEmitted(ASTWriter &Writer);
279 /// Called for each TopLevelDecl.
280 /// NOTE: To allow more flexibility a custom ASTConsumer could probably be
281 /// used instead, but having only this method allows a simpler API.
282 virtual void HandleTopLevelDecl(DeclGroupRef DG);
283 /// Creates wrapper class for PPCallbacks so we can also process information
284 /// about includes that are inside of a preamble
285 virtual std::unique_ptr<PPCallbacks> createPPCallbacks();
286};
287
288enum class BuildPreambleError {
289 PreambleIsEmpty = 1,
290 CouldntCreateTempFile,
291 CouldntCreateTargetInfo,
292 BeginSourceFileFailed,
293 CouldntEmitPCH
294};
295
296class BuildPreambleErrorCategory final : public std::error_category {
297public:
298 const char *name() const noexcept override;
299 std::string message(int condition) const override;
300};
301
302std::error_code make_error_code(BuildPreambleError Error);
303} // namespace clang
304
305namespace std {
306template <>
307struct is_error_code_enum<clang::BuildPreambleError> : std::true_type {};
308} // namespace std
309
310#endif
311

Warning: That file was not part of the compilation database. It may have many parsing errors.