clang 24.0.0git
PrecompiledPreamble.h
Go to the documentation of this file.
1//===--- PrecompiledPreamble.h - Build precompiled preambles ----*- 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// Helper class to build precompiled preamble.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_FRONTEND_PRECOMPILEDPREAMBLE_H
14#define LLVM_CLANG_FRONTEND_PRECOMPILEDPREAMBLE_H
15
16#include "clang/Lex/Lexer.h"
18#include "llvm/ADT/IntrusiveRefCntPtr.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/Support/MD5.h"
21#include "llvm/Support/VirtualFileSystemFwd.h"
22#include <cstddef>
23#include <memory>
24#include <system_error>
25#include <type_traits>
26
27namespace llvm {
28class MemoryBuffer;
29class MemoryBufferRef;
30} // namespace llvm
31
32namespace clang {
35class Decl;
36class DeclGroupRef;
38
39/// Runs lexer to compute suggested preamble bounds.
41 const llvm::MemoryBufferRef &Buffer,
42 unsigned MaxLines);
43
45
46/// A class holding a PCH and all information to check whether it is valid to
47/// reuse the PCH for the subsequent runs. Use BuildPreamble to create PCH and
48/// CanReusePreamble + AddImplicitPreamble to make use of it.
50 class PCHStorage;
51 struct PreambleFileHash;
52
53public:
54 /// Try to build PrecompiledPreamble for \p Invocation. See
55 /// BuildPreambleError for possible error codes.
56 ///
57 /// \param Invocation Original CompilerInvocation with options to compile the
58 /// file.
59 ///
60 /// \param MainFileBuffer Buffer with the contents of the main file.
61 ///
62 /// \param Bounds Bounds of the preamble, result of calling
63 /// ComputePreambleBounds.
64 ///
65 /// \param Diagnostics Diagnostics engine to be used while building the
66 /// preamble.
67 ///
68 /// \param VFS An instance of vfs::FileSystem to be used for file
69 /// accesses.
70 ///
71 /// \param PCHContainerOps An instance of PCHContainerOperations.
72 ///
73 /// \param StoreInMemory Store PCH in memory. If false, PCH will be stored in
74 /// a temporary file.
75 ///
76 /// \param StoragePath The path to a directory, in which to create a temporary
77 /// file to store PCH in. If empty, the default system temporary directory is
78 /// used. This parameter is ignored if \p StoreInMemory is true.
79 ///
80 /// \param Callbacks A set of callbacks to be executed when building
81 /// the preamble.
82 static llvm::ErrorOr<PrecompiledPreamble>
83 Build(const CompilerInvocation &Invocation,
84 const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
87 std::shared_ptr<PCHContainerOperations> PCHContainerOps,
88 bool StoreInMemory, StringRef StoragePath,
89 PreambleCallbacks &Callbacks);
90
94
95 /// PreambleBounds used to build the preamble.
97
98 /// Returns the size, in bytes, that preamble takes on disk or in memory.
99 /// For on-disk preambles returns 0 if filesystem operations fail. Intended to
100 /// be used for logging and debugging purposes only.
101 std::size_t getSize() const;
102
103 /// Returned string is not null-terminated.
104 llvm::StringRef getContents() const {
105 return {PreambleBytes.data(), PreambleBytes.size()};
106 }
107
108 /// Check whether PrecompiledPreamble can be reused for the new contents(\p
109 /// MainFileBuffer) of the main file.
110 bool CanReuse(const CompilerInvocation &Invocation,
111 const llvm::MemoryBufferRef &MainFileBuffer,
112 PreambleBounds Bounds, llvm::vfs::FileSystem &VFS) const;
113
114 /// Changes options inside \p CI to use PCH from this preamble. Also remaps
115 /// main file to \p MainFileBuffer and updates \p VFS to ensure the preamble
116 /// is accessible.
117 /// Requires that CanReuse() is true.
118 /// For in-memory preambles, PrecompiledPreamble instance continues to own the
119 /// MemoryBuffer with the Preamble after this method returns. The caller is
120 /// responsible for making sure the PrecompiledPreamble instance outlives the
121 /// compiler run and the AST that will be using the PCH.
124 llvm::MemoryBuffer *MainFileBuffer) const;
125
126 /// Configure \p CI to use this preamble.
127 /// Like AddImplicitPreamble, but doesn't assume CanReuse() is true.
128 /// If this preamble does not match the file, it may parse differently.
131 llvm::MemoryBuffer *MainFileBuffer) const;
132
133private:
134 PrecompiledPreamble(std::unique_ptr<PCHStorage> Storage,
135 std::vector<char> PreambleBytes,
136 bool PreambleEndsAtStartOfLine,
137 llvm::StringMap<PreambleFileHash> FilesInPreamble,
138 llvm::StringSet<> MissingFiles);
139
140 /// Data used to determine if a file used in the preamble has been changed.
141 struct PreambleFileHash {
142 /// All files have size set.
143 off_t Size = 0;
144
145 /// Modification time is set for files that are on disk. For memory
146 /// buffers it is zero.
147 time_t ModTime = 0;
148
149 /// Memory buffers have MD5 instead of modification time. We don't
150 /// compute MD5 for on-disk files because we hope that modification time is
151 /// enough to tell if the file was changed.
152 llvm::MD5::MD5Result MD5 = {};
153
154 static PreambleFileHash createForFile(off_t Size, time_t ModTime);
155 static PreambleFileHash
156 createForMemoryBuffer(const llvm::MemoryBufferRef &Buffer);
157
158 friend bool operator==(const PreambleFileHash &LHS,
159 const PreambleFileHash &RHS) {
160 return LHS.Size == RHS.Size && LHS.ModTime == RHS.ModTime &&
161 LHS.MD5 == RHS.MD5;
162 }
163 friend bool operator!=(const PreambleFileHash &LHS,
164 const PreambleFileHash &RHS) {
165 return !(LHS == RHS);
166 }
167 };
168
169 /// Helper function to set up PCH for the preamble into \p CI and \p VFS to
170 /// with the specified \p Bounds.
171 void configurePreamble(PreambleBounds Bounds, CompilerInvocation &CI,
172 IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS,
173 llvm::MemoryBuffer *MainFileBuffer) const;
174
175 /// Sets up the PreprocessorOptions and changes VFS, so that PCH stored in \p
176 /// Storage is accessible to clang. This method is an implementation detail of
177 /// AddImplicitPreamble.
178 static void
179 setupPreambleStorage(const PCHStorage &Storage,
180 PreprocessorOptions &PreprocessorOpts,
181 IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS);
182
183 /// Manages the memory buffer or temporary file that stores the PCH.
184 std::unique_ptr<PCHStorage> Storage;
185 /// Keeps track of the files that were used when computing the
186 /// preamble, with both their buffer size and their modification time.
187 ///
188 /// If any of the files have changed from one compile to the next,
189 /// the preamble must be thrown away.
190 llvm::StringMap<PreambleFileHash> FilesInPreamble;
191 /// Files that were not found during preamble building. If any of these now
192 /// exist then the preamble should not be reused.
193 ///
194 /// Storing *all* the missing files that could invalidate the preamble would
195 /// make it too expensive to revalidate (when the include path has many
196 /// entries, each #include will miss half of them on average).
197 /// Instead, we track only files that could have satisfied an #include that
198 /// was ultimately not found.
199 llvm::StringSet<> MissingFiles;
200 /// The contents of the file that was used to precompile the preamble. Only
201 /// contains first PreambleBounds::Size bytes. Used to compare if the relevant
202 /// part of the file has not changed, so that preamble can be reused.
203 std::vector<char> PreambleBytes;
204 /// See PreambleBounds::PreambleEndsAtStartOfLine
205 bool PreambleEndsAtStartOfLine;
206};
207
208/// A set of callbacks to gather useful information while building a preamble.
210public:
211 virtual ~PreambleCallbacks() = default;
212
213 /// Called before FrontendAction::Execute.
214 /// Can be used to store references to various CompilerInstance fields
215 /// (e.g. SourceManager) that may be interesting to the consumers of other
216 /// callbacks.
217 virtual void BeforeExecute(CompilerInstance &CI);
218 /// Called after FrontendAction::Execute(), but before
219 /// FrontendAction::EndSourceFile(). Can be used to transfer ownership of
220 /// various CompilerInstance fields before they are destroyed.
221 virtual void AfterExecute(CompilerInstance &CI);
222 /// Called after PCH has been emitted. \p Writer may be used to retrieve
223 /// information about AST, serialized in PCH.
224 virtual void AfterPCHEmitted(ASTWriter &Writer);
225 /// Called for each TopLevelDecl.
226 /// NOTE: To allow more flexibility a custom ASTConsumer could probably be
227 /// used instead, but having only this method allows a simpler API.
228 virtual void HandleTopLevelDecl(DeclGroupRef DG);
229 /// Creates wrapper class for PPCallbacks so we can also process information
230 /// about includes that are inside of a preamble. Called after BeforeExecute.
231 virtual std::unique_ptr<PPCallbacks> createPPCallbacks();
232 /// The returned CommentHandler will be added to the preprocessor if not null.
234 /// Determines which function bodies are parsed, by default skips everything.
235 /// Only used if FrontendOpts::SkipFunctionBodies is true.
236 /// See ASTConsumer::shouldSkipFunctionBody.
237 virtual bool shouldSkipFunctionBody(Decl *D) { return true; }
238};
239
247
248class BuildPreambleErrorCategory final : public std::error_category {
249public:
250 const char *name() const noexcept override;
251 std::string message(int condition) const override;
252};
253
255} // namespace clang
256
257template <>
258struct std::is_error_code_enum<clang::BuildPreambleError> : std::true_type {};
259
260#endif
*collection of selector each with an associated kind and an ordered *collection of selectors A selector has a an optional score condition
Defines the clang::Preprocessor interface.
Writes an AST file containing the contents of a translation unit.
Definition ASTWriter.h:97
std::string message(int condition) const override
const char * name() const noexcept override
Abstract base class that describes a handler that will receive source ranges for each of the comments...
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Helper class for holding the data necessary to invoke the compiler.
Decl - This represents one declaration (or definition), e.g.
Definition DeclBase.h:86
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
A registry of PCHContainerWriter and -Reader objects for different formats.
A set of callbacks to gather useful information while building a preamble.
virtual void AfterPCHEmitted(ASTWriter &Writer)
Called after PCH has been emitted.
virtual void BeforeExecute(CompilerInstance &CI)
Called before FrontendAction::Execute.
virtual CommentHandler * getCommentHandler()
The returned CommentHandler will be added to the preprocessor if not null.
virtual ~PreambleCallbacks()=default
virtual void HandleTopLevelDecl(DeclGroupRef DG)
Called for each TopLevelDecl.
virtual std::unique_ptr< PPCallbacks > createPPCallbacks()
Creates wrapper class for PPCallbacks so we can also process information about includes that are insi...
virtual void AfterExecute(CompilerInstance &CI)
Called after FrontendAction::Execute(), but before FrontendAction::EndSourceFile().
virtual bool shouldSkipFunctionBody(Decl *D)
Determines which function bodies are parsed, by default skips everything.
void OverridePreamble(CompilerInvocation &CI, IntrusiveRefCntPtr< llvm::vfs::FileSystem > &VFS, llvm::MemoryBuffer *MainFileBuffer) const
Configure CI to use this preamble.
static llvm::ErrorOr< PrecompiledPreamble > Build(const CompilerInvocation &Invocation, const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, IntrusiveRefCntPtr< DiagnosticsEngine > Diagnostics, IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, std::shared_ptr< PCHContainerOperations > PCHContainerOps, bool StoreInMemory, StringRef StoragePath, PreambleCallbacks &Callbacks)
Try to build PrecompiledPreamble for Invocation.
llvm::StringRef getContents() const
Returned string is not null-terminated.
PrecompiledPreamble & operator=(PrecompiledPreamble &&)
bool CanReuse(const CompilerInvocation &Invocation, const llvm::MemoryBufferRef &MainFileBuffer, PreambleBounds Bounds, llvm::vfs::FileSystem &VFS) const
Check whether PrecompiledPreamble can be reused for the new contents(MainFileBuffer) of the main file...
void AddImplicitPreamble(CompilerInvocation &CI, IntrusiveRefCntPtr< llvm::vfs::FileSystem > &VFS, llvm::MemoryBuffer *MainFileBuffer) const
Changes options inside CI to use PCH from this preamble.
std::size_t getSize() const
Returns the size, in bytes, that preamble takes on disk or in memory.
PreambleBounds getBounds() const
PreambleBounds used to build the preamble.
PrecompiledPreamble(PrecompiledPreamble &&)
Top level wrappers for InstallAPI frontend operations.
std::error_code make_error_code(BuildPreambleError Error)
PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts, const llvm::MemoryBufferRef &Buffer, unsigned MaxLines)
Runs lexer to compute suggested preamble bounds.
Diagnostic wrappers for TextAPI types for error reporting.
Definition Dominators.h:30
Describes the bounds (start, size) of the preamble and a flag required by PreprocessorOptions::Precom...
Definition Lexer.h:61