clang  10.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/Support/AlignOf.h"
20 #include "llvm/Support/MD5.h"
21 #include <cstddef>
22 #include <memory>
23 #include <system_error>
24 #include <type_traits>
25 
26 namespace llvm {
27 class MemoryBuffer;
28 namespace vfs {
29 class FileSystem;
30 }
31 } // namespace llvm
32 
33 namespace clang {
34 class CompilerInstance;
35 class CompilerInvocation;
36 class DeclGroupRef;
37 class PCHContainerOperations;
38 
39 /// Runs lexer to compute suggested preamble bounds.
40 PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts,
41  llvm::MemoryBuffer *Buffer,
42  unsigned MaxLines);
43 
44 class PreambleCallbacks;
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 
53 public:
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 Callbacks A set of callbacks to be executed when building
77  /// the preamble.
78  static llvm::ErrorOr<PrecompiledPreamble>
79  Build(const CompilerInvocation &Invocation,
80  const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
81  DiagnosticsEngine &Diagnostics,
83  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
84  bool StoreInMemory, PreambleCallbacks &Callbacks);
85 
87  PrecompiledPreamble &operator=(PrecompiledPreamble &&) = default;
88 
89  /// PreambleBounds used to build the preamble.
90  PreambleBounds getBounds() const;
91 
92  /// Returns the size, in bytes, that preamble takes on disk or in memory.
93  /// For on-disk preambles returns 0 if filesystem operations fail. Intended to
94  /// be used for logging and debugging purposes only.
95  std::size_t getSize() const;
96 
97  /// Check whether PrecompiledPreamble can be reused for the new contents(\p
98  /// MainFileBuffer) of the main file.
99  bool CanReuse(const CompilerInvocation &Invocation,
100  const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
101  llvm::vfs::FileSystem *VFS) const;
102 
103  /// Changes options inside \p CI to use PCH from this preamble. Also remaps
104  /// main file to \p MainFileBuffer and updates \p VFS to ensure the preamble
105  /// is accessible.
106  /// Requires that CanReuse() is true.
107  /// For in-memory preambles, PrecompiledPreamble instance continues to own the
108  /// MemoryBuffer with the Preamble after this method returns. The caller is
109  /// responsible for making sure the PrecompiledPreamble instance outlives the
110  /// compiler run and the AST that will be using the PCH.
111  void AddImplicitPreamble(CompilerInvocation &CI,
113  llvm::MemoryBuffer *MainFileBuffer) const;
114 
115  /// Configure \p CI to use this preamble.
116  /// Like AddImplicitPreamble, but doesn't assume CanReuse() is true.
117  /// If this preamble does not match the file, it may parse differently.
118  void OverridePreamble(CompilerInvocation &CI,
120  llvm::MemoryBuffer *MainFileBuffer) const;
121 
122 private:
123  PrecompiledPreamble(PCHStorage Storage, std::vector<char> PreambleBytes,
124  bool PreambleEndsAtStartOfLine,
125  llvm::StringMap<PreambleFileHash> FilesInPreamble);
126 
127  /// A temp file that would be deleted on destructor call. If destructor is not
128  /// called for any reason, the file will be deleted at static objects'
129  /// destruction.
130  /// An assertion will fire if two TempPCHFiles are created with the same name,
131  /// so it's not intended to be used outside preamble-handling.
132  class TempPCHFile {
133  public:
134  // A main method used to construct TempPCHFile.
135  static llvm::ErrorOr<TempPCHFile> CreateNewPreamblePCHFile();
136 
137  private:
138  TempPCHFile(std::string FilePath);
139 
140  public:
141  TempPCHFile(TempPCHFile &&Other);
142  TempPCHFile &operator=(TempPCHFile &&Other);
143 
144  TempPCHFile(const TempPCHFile &) = delete;
145  ~TempPCHFile();
146 
147  /// A path where temporary file is stored.
148  llvm::StringRef getFilePath() const;
149 
150  private:
151  void RemoveFileIfPresent();
152 
153  private:
155  };
156 
157  class InMemoryPreamble {
158  public:
159  std::string Data;
160  };
161 
162  class PCHStorage {
163  public:
164  enum class Kind { Empty, InMemory, TempFile };
165 
166  PCHStorage() = default;
167  PCHStorage(TempPCHFile File);
168  PCHStorage(InMemoryPreamble Memory);
169 
170  PCHStorage(const PCHStorage &) = delete;
171  PCHStorage &operator=(const PCHStorage &) = delete;
172 
173  PCHStorage(PCHStorage &&Other);
174  PCHStorage &operator=(PCHStorage &&Other);
175 
176  ~PCHStorage();
177 
178  Kind getKind() const;
179 
180  TempPCHFile &asFile();
181  const TempPCHFile &asFile() const;
182 
183  InMemoryPreamble &asMemory();
184  const InMemoryPreamble &asMemory() const;
185 
186  private:
187  void destroy();
188  void setEmpty();
189 
190  private:
191  Kind StorageKind = Kind::Empty;
192  llvm::AlignedCharArrayUnion<TempPCHFile, InMemoryPreamble> Storage = {};
193  };
194 
195  /// Data used to determine if a file used in the preamble has been changed.
196  struct PreambleFileHash {
197  /// All files have size set.
198  off_t Size = 0;
199 
200  /// Modification time is set for files that are on disk. For memory
201  /// buffers it is zero.
202  time_t ModTime = 0;
203 
204  /// Memory buffers have MD5 instead of modification time. We don't
205  /// compute MD5 for on-disk files because we hope that modification time is
206  /// enough to tell if the file was changed.
207  llvm::MD5::MD5Result MD5 = {};
208 
209  static PreambleFileHash createForFile(off_t Size, time_t ModTime);
210  static PreambleFileHash
211  createForMemoryBuffer(const llvm::MemoryBuffer *Buffer);
212 
213  friend bool operator==(const PreambleFileHash &LHS,
214  const PreambleFileHash &RHS) {
215  return LHS.Size == RHS.Size && LHS.ModTime == RHS.ModTime &&
216  LHS.MD5 == RHS.MD5;
217  }
218  friend bool operator!=(const PreambleFileHash &LHS,
219  const PreambleFileHash &RHS) {
220  return !(LHS == RHS);
221  }
222  };
223 
224  /// Helper function to set up PCH for the preamble into \p CI and \p VFS to
225  /// with the specified \p Bounds.
226  void configurePreamble(PreambleBounds Bounds, CompilerInvocation &CI,
228  llvm::MemoryBuffer *MainFileBuffer) const;
229 
230  /// Sets up the PreprocessorOptions and changes VFS, so that PCH stored in \p
231  /// Storage is accessible to clang. This method is an implementation detail of
232  /// AddImplicitPreamble.
233  static void
234  setupPreambleStorage(const PCHStorage &Storage,
235  PreprocessorOptions &PreprocessorOpts,
237 
238  /// Manages the memory buffer or temporary file that stores the PCH.
239  PCHStorage Storage;
240  /// Keeps track of the files that were used when computing the
241  /// preamble, with both their buffer size and their modification time.
242  ///
243  /// If any of the files have changed from one compile to the next,
244  /// the preamble must be thrown away.
245  llvm::StringMap<PreambleFileHash> FilesInPreamble;
246  /// The contents of the file that was used to precompile the preamble. Only
247  /// contains first PreambleBounds::Size bytes. Used to compare if the relevant
248  /// part of the file has not changed, so that preamble can be reused.
249  std::vector<char> PreambleBytes;
250  /// See PreambleBounds::PreambleEndsAtStartOfLine
251  bool PreambleEndsAtStartOfLine;
252 };
253 
254 /// A set of callbacks to gather useful information while building a preamble.
256 public:
257  virtual ~PreambleCallbacks() = default;
258 
259  /// Called before FrontendAction::BeginSourceFile.
260  /// Can be used to store references to various CompilerInstance fields
261  /// (e.g. SourceManager) that may be interesting to the consumers of other
262  /// callbacks.
263  virtual void BeforeExecute(CompilerInstance &CI);
264  /// Called after FrontendAction::Execute(), but before
265  /// FrontendAction::EndSourceFile(). Can be used to transfer ownership of
266  /// various CompilerInstance fields before they are destroyed.
267  virtual void AfterExecute(CompilerInstance &CI);
268  /// Called after PCH has been emitted. \p Writer may be used to retrieve
269  /// information about AST, serialized in PCH.
270  virtual void AfterPCHEmitted(ASTWriter &Writer);
271  /// Called for each TopLevelDecl.
272  /// NOTE: To allow more flexibility a custom ASTConsumer could probably be
273  /// used instead, but having only this method allows a simpler API.
274  virtual void HandleTopLevelDecl(DeclGroupRef DG);
275  /// Creates wrapper class for PPCallbacks so we can also process information
276  /// about includes that are inside of a preamble
277  virtual std::unique_ptr<PPCallbacks> createPPCallbacks();
278  /// The returned CommentHandler will be added to the preprocessor if not null.
279  virtual CommentHandler *getCommentHandler();
280 };
281 
282 enum class BuildPreambleError {
287  BadInputs
288 };
289 
290 class BuildPreambleErrorCategory final : public std::error_category {
291 public:
292  const char *name() const noexcept override;
293  std::string message(int condition) const override;
294 };
295 
296 std::error_code make_error_code(BuildPreambleError Error);
297 } // namespace clang
298 
299 namespace std {
300 template <>
301 struct is_error_code_enum<clang::BuildPreambleError> : std::true_type {};
302 } // namespace std
303 
304 #endif
Describes the bounds (start, size) of the preamble and a flag required by PreprocessorOptions::Precom...
Definition: Lexer.h:58
bool operator==(CanQual< T > x, CanQual< U > y)
Specialize PointerLikeTypeTraits to allow LazyGenerationalUpdatePtr to be placed into a PointerUnion...
Definition: Dominators.h:30
PreprocessorOptions - This class is used for passing the various options used in preprocessor initial...
Definition: Format.h:2445
__SIZE_TYPE__ size_t
The unsigned integer type of the result of the sizeof operator.
Definition: opencl-c-base.h:40
std::error_code make_error_code(BuildPreambleError Error)
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:149
RangeSelector name(std::string ID)
Given a node with a "name", (like NamedDecl, DeclRefExpr or CxxCtorInitializer) selects the name&#39;s to...
llvm::Error Error
A set of callbacks to gather useful information while building a preamble.
Defines the clang::Preprocessor interface.
PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts, llvm::MemoryBuffer *Buffer, unsigned MaxLines)
Runs lexer to compute suggested preamble bounds.
Kind
CompilerInstance - Helper class for managing a single instance of the Clang compiler.
Dataflow Directional Tag Classes.
A class holding a PCH and all information to check whether it is valid to reuse the PCH for the subse...
Helper class for holding the data necessary to invoke the compiler.
bool operator!=(CanQual< T > x, CanQual< U > y)
Writes an AST file containing the contents of a translation unit.
Definition: ASTWriter.h:96
static Decl::Kind getKind(const Decl *D)
Definition: DeclBase.cpp:947
Abstract base class that describes a handler that will receive source ranges for each of the comments...