clang  13.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_PRECOMPILED_PREAMBLE_H
14 #define LLVM_CLANG_FRONTEND_PRECOMPILED_PREAMBLE_H
15 
16 #include "clang/Lex/Lexer.h"
17 #include "clang/Lex/Preprocessor.h"
18 #include "llvm/ADT/IntrusiveRefCntPtr.h"
19 #include "llvm/ADT/StringRef.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 
27 namespace llvm {
28 class MemoryBuffer;
29 class MemoryBufferRef;
30 namespace vfs {
31 class FileSystem;
32 }
33 } // namespace llvm
34 
35 namespace clang {
36 class CompilerInstance;
37 class CompilerInvocation;
38 class Decl;
39 class DeclGroupRef;
40 class PCHContainerOperations;
41 
42 /// Runs lexer to compute suggested preamble bounds.
43 PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts,
44  const llvm::MemoryBufferRef &Buffer,
45  unsigned MaxLines);
46 
47 class PreambleCallbacks;
48 
49 /// A class holding a PCH and all information to check whether it is valid to
50 /// reuse the PCH for the subsequent runs. Use BuildPreamble to create PCH and
51 /// CanReusePreamble + AddImplicitPreamble to make use of it.
53  class PCHStorage;
54  struct PreambleFileHash;
55 
56 public:
57  /// Try to build PrecompiledPreamble for \p Invocation. See
58  /// BuildPreambleError for possible error codes.
59  ///
60  /// \param Invocation Original CompilerInvocation with options to compile the
61  /// file.
62  ///
63  /// \param MainFileBuffer Buffer with the contents of the main file.
64  ///
65  /// \param Bounds Bounds of the preamble, result of calling
66  /// ComputePreambleBounds.
67  ///
68  /// \param Diagnostics Diagnostics engine to be used while building the
69  /// preamble.
70  ///
71  /// \param VFS An instance of vfs::FileSystem to be used for file
72  /// accesses.
73  ///
74  /// \param PCHContainerOps An instance of PCHContainerOperations.
75  ///
76  /// \param StoreInMemory Store PCH in memory. If false, PCH will be stored in
77  /// a temporary file.
78  ///
79  /// \param Callbacks A set of callbacks to be executed when building
80  /// the preamble.
81  static llvm::ErrorOr<PrecompiledPreamble>
82  Build(const CompilerInvocation &Invocation,
83  const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
84  DiagnosticsEngine &Diagnostics,
86  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
87  bool StoreInMemory, PreambleCallbacks &Callbacks);
88 
91 
92  /// PreambleBounds used to build the preamble.
93  PreambleBounds getBounds() const;
94 
95  /// Returns the size, in bytes, that preamble takes on disk or in memory.
96  /// For on-disk preambles returns 0 if filesystem operations fail. Intended to
97  /// be used for logging and debugging purposes only.
98  std::size_t getSize() const;
99 
100  /// Returned string is not null-terminated.
101  llvm::StringRef getContents() const {
102  return {PreambleBytes.data(), PreambleBytes.size()};
103  }
104 
105  /// Check whether PrecompiledPreamble can be reused for the new contents(\p
106  /// MainFileBuffer) of the main file.
107  bool CanReuse(const CompilerInvocation &Invocation,
108  const llvm::MemoryBufferRef &MainFileBuffer,
109  PreambleBounds Bounds, llvm::vfs::FileSystem &VFS) const;
110 
111  /// Changes options inside \p CI to use PCH from this preamble. Also remaps
112  /// main file to \p MainFileBuffer and updates \p VFS to ensure the preamble
113  /// is accessible.
114  /// Requires that CanReuse() is true.
115  /// For in-memory preambles, PrecompiledPreamble instance continues to own the
116  /// MemoryBuffer with the Preamble after this method returns. The caller is
117  /// responsible for making sure the PrecompiledPreamble instance outlives the
118  /// compiler run and the AST that will be using the PCH.
121  llvm::MemoryBuffer *MainFileBuffer) const;
122 
123  /// Configure \p CI to use this preamble.
124  /// Like AddImplicitPreamble, but doesn't assume CanReuse() is true.
125  /// If this preamble does not match the file, it may parse differently.
128  llvm::MemoryBuffer *MainFileBuffer) const;
129 
130 private:
131  PrecompiledPreamble(PCHStorage Storage, std::vector<char> PreambleBytes,
132  bool PreambleEndsAtStartOfLine,
133  llvm::StringMap<PreambleFileHash> FilesInPreamble,
134  llvm::StringSet<> MissingFiles);
135 
136  /// A temp file that would be deleted on destructor call. If destructor is not
137  /// called for any reason, the file will be deleted at static objects'
138  /// destruction.
139  /// An assertion will fire if two TempPCHFiles are created with the same name,
140  /// so it's not intended to be used outside preamble-handling.
141  class TempPCHFile {
142  public:
143  // A main method used to construct TempPCHFile.
144  static llvm::ErrorOr<TempPCHFile> CreateNewPreamblePCHFile();
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:
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::MemoryBufferRef &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<llvm::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
243  setupPreambleStorage(const PCHStorage &Storage,
244  PreprocessorOptions &PreprocessorOpts,
245  IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS);
246 
247  /// Manages the memory buffer or temporary file that stores the PCH.
248  PCHStorage Storage;
249  /// Keeps track of the files that were used when computing the
250  /// preamble, with both their buffer size and their modification time.
251  ///
252  /// If any of the files have changed from one compile to the next,
253  /// the preamble must be thrown away.
254  llvm::StringMap<PreambleFileHash> FilesInPreamble;
255  /// Files that were not found during preamble building. If any of these now
256  /// exist then the preamble should not be reused.
257  ///
258  /// Storing *all* the missing files that could invalidate the preamble would
259  /// make it too expensive to revalidate (when the include path has many
260  /// entries, each #include will miss half of them on average).
261  /// Instead, we track only files that could have satisfied an #include that
262  /// was ultimately not found.
263  llvm::StringSet<> MissingFiles;
264  /// The contents of the file that was used to precompile the preamble. Only
265  /// contains first PreambleBounds::Size bytes. Used to compare if the relevant
266  /// part of the file has not changed, so that preamble can be reused.
267  std::vector<char> PreambleBytes;
268  /// See PreambleBounds::PreambleEndsAtStartOfLine
269  bool PreambleEndsAtStartOfLine;
270 };
271 
272 /// A set of callbacks to gather useful information while building a preamble.
274 public:
275  virtual ~PreambleCallbacks() = default;
276 
277  /// Called before FrontendAction::BeginSourceFile.
278  /// Can be used to store references to various CompilerInstance fields
279  /// (e.g. SourceManager) that may be interesting to the consumers of other
280  /// callbacks.
281  virtual void BeforeExecute(CompilerInstance &CI);
282  /// Called after FrontendAction::Execute(), but before
283  /// FrontendAction::EndSourceFile(). Can be used to transfer ownership of
284  /// various CompilerInstance fields before they are destroyed.
285  virtual void AfterExecute(CompilerInstance &CI);
286  /// Called after PCH has been emitted. \p Writer may be used to retrieve
287  /// information about AST, serialized in PCH.
288  virtual void AfterPCHEmitted(ASTWriter &Writer);
289  /// Called for each TopLevelDecl.
290  /// NOTE: To allow more flexibility a custom ASTConsumer could probably be
291  /// used instead, but having only this method allows a simpler API.
292  virtual void HandleTopLevelDecl(DeclGroupRef DG);
293  /// Creates wrapper class for PPCallbacks so we can also process information
294  /// about includes that are inside of a preamble
295  virtual std::unique_ptr<PPCallbacks> createPPCallbacks();
296  /// The returned CommentHandler will be added to the preprocessor if not null.
298  /// Determines which function bodies are parsed, by default skips everything.
299  /// Only used if FrontendOpts::SkipFunctionBodies is true.
300  /// See ASTConsumer::shouldSkipFunctionBody.
301  virtual bool shouldSkipFunctionBody(Decl *D) { return true; }
302 };
303 
304 enum class BuildPreambleError {
309  BadInputs
310 };
311 
312 class BuildPreambleErrorCategory final : public std::error_category {
313 public:
314  const char *name() const noexcept override;
315  std::string message(int condition) const override;
316 };
317 
318 std::error_code make_error_code(BuildPreambleError Error);
319 } // namespace clang
320 
321 namespace std {
322 template <>
323 struct is_error_code_enum<clang::BuildPreambleError> : std::true_type {};
324 } // namespace std
325 
326 #endif
clang::operator!=
bool operator!=(CanQual< T > x, CanQual< U > y)
Definition: CanonicalType.h:207
clang::PreambleCallbacks
A set of callbacks to gather useful information while building a preamble.
Definition: PrecompiledPreamble.h:273
llvm
Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be placed into a PointerUnion.
Definition: Dominators.h:30
clang::PrecompiledPreamble
A class holding a PCH and all information to check whether it is valid to reuse the PCH for the subse...
Definition: PrecompiledPreamble.h:52
string
string(SUBSTRING ${CMAKE_CURRENT_BINARY_DIR} 0 ${PATH_LIB_START} PATH_HEAD) string(SUBSTRING $
Definition: CMakeLists.txt:22
clang::PreambleCallbacks::createPPCallbacks
virtual std::unique_ptr< PPCallbacks > createPPCallbacks()
Creates wrapper class for PPCallbacks so we can also process information about includes that are insi...
Definition: PrecompiledPreamble.cpp:853
clang::DiagnosticsEngine
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:191
clang::PreambleCallbacks::HandleTopLevelDecl
virtual void HandleTopLevelDecl(DeclGroupRef DG)
Called for each TopLevelDecl.
Definition: PrecompiledPreamble.cpp:852
llvm::Optional< std::string >
clang::make_error_code
std::error_code make_error_code(BuildPreambleError Error)
Definition: PrecompiledPreamble.cpp:860
clang::CommentHandler
Abstract base class that describes a handler that will receive source ranges for each of the comments...
Definition: Preprocessor.h:2398
clang::PreambleCallbacks::shouldSkipFunctionBody
virtual bool shouldSkipFunctionBody(Decl *D)
Determines which function bodies are parsed, by default skips everything.
Definition: PrecompiledPreamble.h:301
clang::PrecompiledPreamble::getSize
std::size_t getSize() const
Returns the size, in bytes, that preamble takes on disk or in memory.
Definition: PrecompiledPreamble.cpp:474
Preprocessor.h
clang::PreambleCallbacks::~PreambleCallbacks
virtual ~PreambleCallbacks()=default
clang::PrecompiledPreamble::getBounds
PreambleBounds getBounds() const
PreambleBounds used to build the preamble.
Definition: PrecompiledPreamble.cpp:470
clang::BuildPreambleErrorCategory::message
std::string message(int condition) const override
Definition: PrecompiledPreamble.cpp:868
clang::CodeGen::AlignmentSource::Decl
@ Decl
The l-value was an access to a declared entity or something equivalently strong, like the address of ...
size_t
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
Definition: opencl-c-base.h:70
clang::PrecompiledPreamble::AddImplicitPreamble
void AddImplicitPreamble(CompilerInvocation &CI, IntrusiveRefCntPtr< llvm::vfs::FileSystem > &VFS, llvm::MemoryBuffer *MainFileBuffer) const
Changes options inside CI to use PCH from this preamble.
Definition: PrecompiledPreamble.cpp:606
clang::PreambleBounds
Describes the bounds (start, size) of the preamble and a flag required by PreprocessorOptions::Precom...
Definition: Lexer.h:58
clang::PreambleCallbacks::getCommentHandler
virtual CommentHandler * getCommentHandler()
The returned CommentHandler will be added to the preprocessor if not null.
Definition: PrecompiledPreamble.cpp:856
clang::ASTWriter
Writes an AST file containing the contents of a translation unit.
Definition: ASTWriter.h:99
clang::PrecompiledPreamble::OverridePreamble
void OverridePreamble(CompilerInvocation &CI, IntrusiveRefCntPtr< llvm::vfs::FileSystem > &VFS, llvm::MemoryBuffer *MainFileBuffer) const
Configure CI to use this preamble.
Definition: PrecompiledPreamble.cpp:613
clang::CompilerInstance
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Definition: CompilerInstance.h:73
getKind
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:994
clang::BuildPreambleErrorCategory::name
const char * name() const noexcept override
Definition: PrecompiledPreamble.cpp:864
clang::PreambleCallbacks::AfterExecute
virtual void AfterExecute(CompilerInstance &CI)
Called after FrontendAction::Execute(), but before FrontendAction::EndSourceFile().
Definition: PrecompiledPreamble.cpp:850
clang::BuildPreambleError::BadInputs
@ BadInputs
clang::syntax::NodeRole::Size
@ Size
clang::BuildPreambleError::BeginSourceFileFailed
@ BeginSourceFileFailed
Lexer.h
clang::Decl
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:89
clang::BuildPreambleError
BuildPreambleError
Definition: PrecompiledPreamble.h:304
clang::DeclGroupRef
Definition: DeclGroup.h:51
clang::PreambleCallbacks::AfterPCHEmitted
virtual void AfterPCHEmitted(ASTWriter &Writer)
Called after PCH has been emitted.
Definition: PrecompiledPreamble.cpp:851
clang::ObjCPropertyAttribute::Kind
Kind
Definition: DeclObjCCommon.h:22
std
Definition: Format.h:3580
clang::BuildPreambleError::CouldntEmitPCH
@ CouldntEmitPCH
clang
Dataflow Directional Tag Classes.
Definition: CalledOnceCheck.h:17
clang::PrecompiledPreamble::getContents
llvm::StringRef getContents() const
Returned string is not null-terminated.
Definition: PrecompiledPreamble.h:101
clang::BuildPreambleError::CouldntCreateTargetInfo
@ CouldntCreateTargetInfo
clang::CompilerInvocation
Helper class for holding the data necessary to invoke the compiler.
Definition: CompilerInvocation.h:120
clang::PrecompiledPreamble::PrecompiledPreamble
PrecompiledPreamble(PrecompiledPreamble &&)=default
clang::PrecompiledPreamble::CanReuse
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...
Definition: PrecompiledPreamble.cpp:495
clang::PreambleCallbacks::BeforeExecute
virtual void BeforeExecute(CompilerInstance &CI)
Called before FrontendAction::BeginSourceFile.
Definition: PrecompiledPreamble.cpp:849
clang::ComputePreambleBounds
PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts, const llvm::MemoryBufferRef &Buffer, unsigned MaxLines)
Runs lexer to compute suggested preamble bounds.
Definition: PrecompiledPreamble.cpp:305
clang::BuildPreambleErrorCategory
Definition: PrecompiledPreamble.h:312
clang::PrecompiledPreamble::Build
static llvm::ErrorOr< PrecompiledPreamble > Build(const CompilerInvocation &Invocation, const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds, DiagnosticsEngine &Diagnostics, IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, std::shared_ptr< PCHContainerOperations > PCHContainerOps, bool StoreInMemory, PreambleCallbacks &Callbacks)
Try to build PrecompiledPreamble for Invocation.
Definition: PrecompiledPreamble.cpp:311
clang::operator==
bool operator==(const CallGraphNode::CallRecord &LHS, const CallGraphNode::CallRecord &RHS)
Definition: CallGraph.h:207
llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem >
clang::PrecompiledPreamble::operator=
PrecompiledPreamble & operator=(PrecompiledPreamble &&)=default
clang::BuildPreambleError::CouldntCreateTempFile
@ CouldntCreateTempFile