clang  6.0.0svn
PrecompiledPreamble.h
Go to the documentation of this file.
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/MD5.h"
21 #include <memory>
22 #include <system_error>
23 #include <type_traits>
24 
25 namespace llvm {
26 class MemoryBuffer;
27 }
28 
29 namespace clang {
30 namespace vfs {
31 class FileSystem;
32 }
33 
34 class CompilerInstance;
35 class CompilerInvocation;
36 class DeclGroupRef;
37 class PCHContainerOperations;
38 
39 /// \brief 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 TempPCHFile;
51  struct PreambleFileHash;
52 
53 public:
54  /// \brief 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 Callbacks A set of callbacks to be executed when building
74  /// the preamble.
75  static llvm::ErrorOr<PrecompiledPreamble>
76  Build(const CompilerInvocation &Invocation,
77  const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
79  std::shared_ptr<PCHContainerOperations> PCHContainerOps,
80  PreambleCallbacks &Callbacks);
81 
83  PrecompiledPreamble &operator=(PrecompiledPreamble &&) = default;
84 
85  /// PreambleBounds used to build the preamble.
86  PreambleBounds getBounds() const;
87 
88  /// The temporary file path at which the preamble PCH was placed.
89  StringRef GetPCHPath() const { return PCHFile.getFilePath(); }
90 
91  /// Check whether PrecompiledPreamble can be reused for the new contents(\p
92  /// MainFileBuffer) of the main file.
93  bool CanReuse(const CompilerInvocation &Invocation,
94  const llvm::MemoryBuffer *MainFileBuffer, PreambleBounds Bounds,
95  vfs::FileSystem *VFS) const;
96 
97  /// Changes options inside \p CI to use PCH from this preamble. Also remaps
98  /// main file to \p MainFileBuffer.
99  void AddImplicitPreamble(CompilerInvocation &CI,
100  llvm::MemoryBuffer *MainFileBuffer) const;
101 
102 private:
103  PrecompiledPreamble(TempPCHFile PCHFile, std::vector<char> PreambleBytes,
104  bool PreambleEndsAtStartOfLine,
105  llvm::StringMap<PreambleFileHash> FilesInPreamble);
106 
107  /// A temp file that would be deleted on destructor call. If destructor is not
108  /// called for any reason, the file will be deleted at static objects'
109  /// destruction.
110  /// An assertion will fire if two TempPCHFiles are created with the same name,
111  /// so it's not intended to be used outside preamble-handling.
112  class TempPCHFile {
113  public:
114  // A main method used to construct TempPCHFile.
115  static llvm::ErrorOr<TempPCHFile> CreateNewPreamblePCHFile();
116 
117  /// Call llvm::sys::fs::createTemporaryFile to create a new temporary file.
118  static llvm::ErrorOr<TempPCHFile> createInSystemTempDir(const Twine &Prefix,
119  StringRef Suffix);
120  /// Create a new instance of TemporaryFile for file at \p Path. Use with
121  /// extreme caution, there's an assertion checking that there's only a
122  /// single instance of TempPCHFile alive for each path.
123  static llvm::ErrorOr<TempPCHFile> createFromCustomPath(const Twine &Path);
124 
125  private:
126  TempPCHFile(std::string FilePath);
127 
128  public:
129  TempPCHFile(TempPCHFile &&Other);
130  TempPCHFile &operator=(TempPCHFile &&Other);
131 
132  TempPCHFile(const TempPCHFile &) = delete;
133  ~TempPCHFile();
134 
135  /// A path where temporary file is stored.
136  llvm::StringRef getFilePath() const;
137 
138  private:
139  void RemoveFileIfPresent();
140 
141  private:
143  };
144 
145  /// Data used to determine if a file used in the preamble has been changed.
146  struct PreambleFileHash {
147  /// All files have size set.
148  off_t Size = 0;
149 
150  /// Modification time is set for files that are on disk. For memory
151  /// buffers it is zero.
152  time_t ModTime = 0;
153 
154  /// Memory buffers have MD5 instead of modification time. We don't
155  /// compute MD5 for on-disk files because we hope that modification time is
156  /// enough to tell if the file was changed.
157  llvm::MD5::MD5Result MD5 = {};
158 
159  static PreambleFileHash createForFile(off_t Size, time_t ModTime);
160  static PreambleFileHash
161  createForMemoryBuffer(const llvm::MemoryBuffer *Buffer);
162 
163  friend bool operator==(const PreambleFileHash &LHS,
164  const PreambleFileHash &RHS) {
165  return LHS.Size == RHS.Size && LHS.ModTime == RHS.ModTime &&
166  LHS.MD5 == RHS.MD5;
167  }
168  friend bool operator!=(const PreambleFileHash &LHS,
169  const PreambleFileHash &RHS) {
170  return !(LHS == RHS);
171  }
172  };
173 
174  /// Manages the lifetime of temporary file that stores a PCH.
175  TempPCHFile PCHFile;
176  /// Keeps track of the files that were used when computing the
177  /// preamble, with both their buffer size and their modification time.
178  ///
179  /// If any of the files have changed from one compile to the next,
180  /// the preamble must be thrown away.
181  llvm::StringMap<PreambleFileHash> FilesInPreamble;
182  /// The contents of the file that was used to precompile the preamble. Only
183  /// contains first PreambleBounds::Size bytes. Used to compare if the relevant
184  /// part of the file has not changed, so that preamble can be reused.
185  std::vector<char> PreambleBytes;
186  /// See PreambleBounds::PreambleEndsAtStartOfLine
187  bool PreambleEndsAtStartOfLine;
188 };
189 
190 /// A set of callbacks to gather useful information while building a preamble.
192 public:
193  virtual ~PreambleCallbacks() = default;
194 
195  /// Called after FrontendAction::Execute(), but before
196  /// FrontendAction::EndSourceFile(). Can be used to transfer ownership of
197  /// various CompilerInstance fields before they are destroyed.
198  virtual void AfterExecute(CompilerInstance &CI);
199  /// Called after PCH has been emitted. \p Writer may be used to retrieve
200  /// information about AST, serialized in PCH.
201  virtual void AfterPCHEmitted(ASTWriter &Writer);
202  /// Called for each TopLevelDecl.
203  /// NOTE: To allow more flexibility a custom ASTConsumer could probably be
204  /// used instead, but having only this method allows a simpler API.
205  virtual void HandleTopLevelDecl(DeclGroupRef DG);
206  /// Called for each macro defined in the Preamble.
207  /// NOTE: To allow more flexibility a custom PPCallbacks could probably be
208  /// used instead, but having only this method allows a simpler API.
209  virtual void HandleMacroDefined(const Token &MacroNameTok,
210  const MacroDirective *MD);
211 };
212 
213 enum class BuildPreambleError {
214  PreambleIsEmpty = 1,
220 };
221 
222 class BuildPreambleErrorCategory final : public std::error_category {
223 public:
224  const char *name() const noexcept override;
225  std::string message(int condition) const override;
226 };
227 
228 std::error_code make_error_code(BuildPreambleError Error);
229 } // namespace clang
230 
231 namespace std {
232 template <>
233 struct is_error_code_enum<clang::BuildPreambleError> : std::true_type {};
234 } // namespace std
235 
236 #endif
Describes the bounds (start, size) of the preamble and a flag required by PreprocessorOptions::Precom...
Definition: Lexer.h:45
bool operator==(CanQual< T > x, CanQual< U > y)
DominatorTree GraphTraits specialization so the DominatorTree can be iterable by generic graph iterat...
Definition: Dominators.h:26
The virtual file system interface.
Definition: Format.h:1821
Token - This structure provides full information about a lexed token.
Definition: Token.h:35
std::error_code make_error_code(BuildPreambleError Error)
Concrete class used by the front-end to report problems and issues.
Definition: Diagnostic.h:147
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.
StringRef GetPCHPath() const
The temporary file path at which the preamble PCH was placed.
Encapsulates changes to the "macros namespace" (the location where the macro name became active...
Definition: MacroInfo.h:286
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:82