- //===--- PrecompiledPreamble.h - Build precompiled preambles ----*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- // 
- // Helper class to build precompiled preamble. 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_CLANG_FRONTEND_PRECOMPILEDPREAMBLE_H 
- #define LLVM_CLANG_FRONTEND_PRECOMPILEDPREAMBLE_H 
-   
- #include "clang/Lex/Lexer.h" 
- #include "clang/Lex/Preprocessor.h" 
- #include "llvm/ADT/IntrusiveRefCntPtr.h" 
- #include "llvm/ADT/StringRef.h" 
- #include "llvm/Support/MD5.h" 
- #include <cstddef> 
- #include <memory> 
- #include <system_error> 
- #include <type_traits> 
-   
- namespace llvm { 
- class MemoryBuffer; 
- class MemoryBufferRef; 
- namespace vfs { 
- class FileSystem; 
- } 
- } // namespace llvm 
-   
- namespace clang { 
- class CompilerInstance; 
- class CompilerInvocation; 
- class Decl; 
- class DeclGroupRef; 
- class PCHContainerOperations; 
-   
- /// Runs lexer to compute suggested preamble bounds. 
- PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts, 
-                                      const llvm::MemoryBufferRef &Buffer, 
-                                      unsigned MaxLines); 
-   
- class PreambleCallbacks; 
-   
- /// A class holding a PCH and all information to check whether it is valid to 
- /// reuse the PCH for the subsequent runs. Use BuildPreamble to create PCH and 
- /// CanReusePreamble + AddImplicitPreamble to make use of it. 
- class PrecompiledPreamble { 
-   class PCHStorage; 
-   struct PreambleFileHash; 
-   
- public: 
-   /// Try to build PrecompiledPreamble for \p Invocation. See 
-   /// BuildPreambleError for possible error codes. 
-   /// 
-   /// \param Invocation Original CompilerInvocation with options to compile the 
-   /// file. 
-   /// 
-   /// \param MainFileBuffer Buffer with the contents of the main file. 
-   /// 
-   /// \param Bounds Bounds of the preamble, result of calling 
-   /// ComputePreambleBounds. 
-   /// 
-   /// \param Diagnostics Diagnostics engine to be used while building the 
-   /// preamble. 
-   /// 
-   /// \param VFS An instance of vfs::FileSystem to be used for file 
-   /// accesses. 
-   /// 
-   /// \param PCHContainerOps An instance of PCHContainerOperations. 
-   /// 
-   /// \param StoreInMemory Store PCH in memory. If false, PCH will be stored in 
-   /// a temporary file. 
-   /// 
-   /// \param Callbacks A set of callbacks to be executed when building 
-   /// the preamble. 
-   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); 
-   
-   PrecompiledPreamble(PrecompiledPreamble &&); 
-   PrecompiledPreamble &operator=(PrecompiledPreamble &&); 
-   ~PrecompiledPreamble(); 
-   
-   /// PreambleBounds used to build the preamble. 
-   PreambleBounds getBounds() const; 
-   
-   /// Returns the size, in bytes, that preamble takes on disk or in memory. 
-   /// For on-disk preambles returns 0 if filesystem operations fail. Intended to 
-   /// be used for logging and debugging purposes only. 
-   std::size_t getSize() const; 
-   
-   /// Returned string is not null-terminated. 
-   llvm::StringRef getContents() const { 
-     return {PreambleBytes.data(), PreambleBytes.size()}; 
-   } 
-   
-   /// Check whether PrecompiledPreamble can be reused for the new contents(\p 
-   /// MainFileBuffer) of the main file. 
-   bool CanReuse(const CompilerInvocation &Invocation, 
-                 const llvm::MemoryBufferRef &MainFileBuffer, 
-                 PreambleBounds Bounds, llvm::vfs::FileSystem &VFS) const; 
-   
-   /// Changes options inside \p CI to use PCH from this preamble. Also remaps 
-   /// main file to \p MainFileBuffer and updates \p VFS to ensure the preamble 
-   /// is accessible. 
-   /// Requires that CanReuse() is true. 
-   /// For in-memory preambles, PrecompiledPreamble instance continues to own the 
-   /// MemoryBuffer with the Preamble after this method returns. The caller is 
-   /// responsible for making sure the PrecompiledPreamble instance outlives the 
-   /// compiler run and the AST that will be using the PCH. 
-   void AddImplicitPreamble(CompilerInvocation &CI, 
-                            IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS, 
-                            llvm::MemoryBuffer *MainFileBuffer) const; 
-   
-   /// Configure \p CI to use this preamble. 
-   /// Like AddImplicitPreamble, but doesn't assume CanReuse() is true. 
-   /// If this preamble does not match the file, it may parse differently. 
-   void OverridePreamble(CompilerInvocation &CI, 
-                         IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS, 
-                         llvm::MemoryBuffer *MainFileBuffer) const; 
-   
- private: 
-   PrecompiledPreamble(std::unique_ptr<PCHStorage> Storage, 
-                       std::vector<char> PreambleBytes, 
-                       bool PreambleEndsAtStartOfLine, 
-                       llvm::StringMap<PreambleFileHash> FilesInPreamble, 
-                       llvm::StringSet<> MissingFiles); 
-   
-   /// Data used to determine if a file used in the preamble has been changed. 
-   struct PreambleFileHash { 
-     /// All files have size set. 
-     off_t Size = 0; 
-   
-     /// Modification time is set for files that are on disk.  For memory 
-     /// buffers it is zero. 
-     time_t ModTime = 0; 
-   
-     /// Memory buffers have MD5 instead of modification time.  We don't 
-     /// compute MD5 for on-disk files because we hope that modification time is 
-     /// enough to tell if the file was changed. 
-     llvm::MD5::MD5Result MD5 = {}; 
-   
-     static PreambleFileHash createForFile(off_t Size, time_t ModTime); 
-     static PreambleFileHash 
-     createForMemoryBuffer(const llvm::MemoryBufferRef &Buffer); 
-   
-     friend bool operator==(const PreambleFileHash &LHS, 
-                            const PreambleFileHash &RHS) { 
-       return LHS.Size == RHS.Size && LHS.ModTime == RHS.ModTime && 
-              LHS.MD5 == RHS.MD5; 
-     } 
-     friend bool operator!=(const PreambleFileHash &LHS, 
-                            const PreambleFileHash &RHS) { 
-       return !(LHS == RHS); 
-     } 
-   }; 
-   
-   /// Helper function to set up PCH for the preamble into \p CI and \p VFS to 
-   /// with the specified \p Bounds. 
-   void configurePreamble(PreambleBounds Bounds, CompilerInvocation &CI, 
-                          IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS, 
-                          llvm::MemoryBuffer *MainFileBuffer) const; 
-   
-   /// Sets up the PreprocessorOptions and changes VFS, so that PCH stored in \p 
-   /// Storage is accessible to clang. This method is an implementation detail of 
-   /// AddImplicitPreamble. 
-   static void 
-   setupPreambleStorage(const PCHStorage &Storage, 
-                        PreprocessorOptions &PreprocessorOpts, 
-                        IntrusiveRefCntPtr<llvm::vfs::FileSystem> &VFS); 
-   
-   /// Manages the memory buffer or temporary file that stores the PCH. 
-   std::unique_ptr<PCHStorage> Storage; 
-   /// Keeps track of the files that were used when computing the 
-   /// preamble, with both their buffer size and their modification time. 
-   /// 
-   /// If any of the files have changed from one compile to the next, 
-   /// the preamble must be thrown away. 
-   llvm::StringMap<PreambleFileHash> FilesInPreamble; 
-   /// Files that were not found during preamble building. If any of these now 
-   /// exist then the preamble should not be reused. 
-   /// 
-   /// Storing *all* the missing files that could invalidate the preamble would 
-   /// make it too expensive to revalidate (when the include path has many 
-   /// entries, each #include will miss half of them on average). 
-   /// Instead, we track only files that could have satisfied an #include that 
-   /// was ultimately not found. 
-   llvm::StringSet<> MissingFiles; 
-   /// The contents of the file that was used to precompile the preamble. Only 
-   /// contains first PreambleBounds::Size bytes. Used to compare if the relevant 
-   /// part of the file has not changed, so that preamble can be reused. 
-   std::vector<char> PreambleBytes; 
-   /// See PreambleBounds::PreambleEndsAtStartOfLine 
-   bool PreambleEndsAtStartOfLine; 
- }; 
-   
- /// A set of callbacks to gather useful information while building a preamble. 
- class PreambleCallbacks { 
- public: 
-   virtual ~PreambleCallbacks() = default; 
-   
-   /// Called before FrontendAction::Execute. 
-   /// Can be used to store references to various CompilerInstance fields 
-   /// (e.g. SourceManager) that may be interesting to the consumers of other 
-   /// callbacks. 
-   virtual void BeforeExecute(CompilerInstance &CI); 
-   /// Called after FrontendAction::Execute(), but before 
-   /// FrontendAction::EndSourceFile(). Can be used to transfer ownership of 
-   /// various CompilerInstance fields before they are destroyed. 
-   virtual void AfterExecute(CompilerInstance &CI); 
-   /// Called after PCH has been emitted. \p Writer may be used to retrieve 
-   /// information about AST, serialized in PCH. 
-   virtual void AfterPCHEmitted(ASTWriter &Writer); 
-   /// Called for each TopLevelDecl. 
-   /// NOTE: To allow more flexibility a custom ASTConsumer could probably be 
-   /// used instead, but having only this method allows a simpler API. 
-   virtual void HandleTopLevelDecl(DeclGroupRef DG); 
-   /// Creates wrapper class for PPCallbacks so we can also process information 
-   /// about includes that are inside of a preamble. Called after BeforeExecute. 
-   virtual std::unique_ptr<PPCallbacks> createPPCallbacks(); 
-   /// The returned CommentHandler will be added to the preprocessor if not null. 
-   virtual CommentHandler *getCommentHandler(); 
-   /// Determines which function bodies are parsed, by default skips everything. 
-   /// Only used if FrontendOpts::SkipFunctionBodies is true. 
-   /// See ASTConsumer::shouldSkipFunctionBody. 
-   virtual bool shouldSkipFunctionBody(Decl *D) { return true; } 
- }; 
-   
- enum class BuildPreambleError { 
-   CouldntCreateTempFile = 1, 
-   CouldntCreateTargetInfo, 
-   BeginSourceFileFailed, 
-   CouldntEmitPCH, 
-   BadInputs 
- }; 
-   
- class BuildPreambleErrorCategory final : public std::error_category { 
- public: 
-   const char *name() const noexcept override; 
-   std::string message(int condition) const override; 
- }; 
-   
- std::error_code make_error_code(BuildPreambleError Error); 
- } // namespace clang 
-   
- namespace std { 
- template <> 
- struct is_error_code_enum<clang::BuildPreambleError> : std::true_type {}; 
- } // namespace std 
-   
- #endif 
-