summaryrefslogtreecommitdiff
path: root/clang-r353983/include/clang/Frontend/PrecompiledPreamble.h
diff options
context:
space:
mode:
Diffstat (limited to 'clang-r353983/include/clang/Frontend/PrecompiledPreamble.h')
-rw-r--r--clang-r353983/include/clang/Frontend/PrecompiledPreamble.h311
1 files changed, 311 insertions, 0 deletions
diff --git a/clang-r353983/include/clang/Frontend/PrecompiledPreamble.h b/clang-r353983/include/clang/Frontend/PrecompiledPreamble.h
new file mode 100644
index 00000000..b1d55d80
--- /dev/null
+++ b/clang-r353983/include/clang/Frontend/PrecompiledPreamble.h
@@ -0,0 +1,311 @@
+//===--- 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_PRECOMPILED_PREAMBLE_H
+#define LLVM_CLANG_FRONTEND_PRECOMPILED_PREAMBLE_H
+
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/ADT/IntrusiveRefCntPtr.h"
+#include "llvm/Support/AlignOf.h"
+#include "llvm/Support/MD5.h"
+#include <cstddef>
+#include <memory>
+#include <system_error>
+#include <type_traits>
+
+namespace llvm {
+class MemoryBuffer;
+namespace vfs {
+class FileSystem;
+}
+} // namespace llvm
+
+namespace clang {
+class CompilerInstance;
+class CompilerInvocation;
+class DeclGroupRef;
+class PCHContainerOperations;
+
+/// Runs lexer to compute suggested preamble bounds.
+PreambleBounds ComputePreambleBounds(const LangOptions &LangOpts,
+ llvm::MemoryBuffer *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 &&) = default;
+ PrecompiledPreamble &operator=(PrecompiledPreamble &&) = default;
+
+ /// 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;
+
+ /// Check whether PrecompiledPreamble can be reused for the new contents(\p
+ /// MainFileBuffer) of the main file.
+ bool CanReuse(const CompilerInvocation &Invocation,
+ const llvm::MemoryBuffer *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(PCHStorage Storage, std::vector<char> PreambleBytes,
+ bool PreambleEndsAtStartOfLine,
+ llvm::StringMap<PreambleFileHash> FilesInPreamble);
+
+ /// A temp file that would be deleted on destructor call. If destructor is not
+ /// called for any reason, the file will be deleted at static objects'
+ /// destruction.
+ /// An assertion will fire if two TempPCHFiles are created with the same name,
+ /// so it's not intended to be used outside preamble-handling.
+ class TempPCHFile {
+ public:
+ // A main method used to construct TempPCHFile.
+ static llvm::ErrorOr<TempPCHFile> CreateNewPreamblePCHFile();
+
+ /// Call llvm::sys::fs::createTemporaryFile to create a new temporary file.
+ static llvm::ErrorOr<TempPCHFile> createInSystemTempDir(const Twine &Prefix,
+ StringRef Suffix);
+ /// Create a new instance of TemporaryFile for file at \p Path. Use with
+ /// extreme caution, there's an assertion checking that there's only a
+ /// single instance of TempPCHFile alive for each path.
+ static llvm::ErrorOr<TempPCHFile> createFromCustomPath(const Twine &Path);
+
+ private:
+ TempPCHFile(std::string FilePath);
+
+ public:
+ TempPCHFile(TempPCHFile &&Other);
+ TempPCHFile &operator=(TempPCHFile &&Other);
+
+ TempPCHFile(const TempPCHFile &) = delete;
+ ~TempPCHFile();
+
+ /// A path where temporary file is stored.
+ llvm::StringRef getFilePath() const;
+
+ private:
+ void RemoveFileIfPresent();
+
+ private:
+ llvm::Optional<std::string> FilePath;
+ };
+
+ class InMemoryPreamble {
+ public:
+ std::string Data;
+ };
+
+ class PCHStorage {
+ public:
+ enum class Kind { Empty, InMemory, TempFile };
+
+ PCHStorage() = default;
+ PCHStorage(TempPCHFile File);
+ PCHStorage(InMemoryPreamble Memory);
+
+ PCHStorage(const PCHStorage &) = delete;
+ PCHStorage &operator=(const PCHStorage &) = delete;
+
+ PCHStorage(PCHStorage &&Other);
+ PCHStorage &operator=(PCHStorage &&Other);
+
+ ~PCHStorage();
+
+ Kind getKind() const;
+
+ TempPCHFile &asFile();
+ const TempPCHFile &asFile() const;
+
+ InMemoryPreamble &asMemory();
+ const InMemoryPreamble &asMemory() const;
+
+ private:
+ void destroy();
+ void setEmpty();
+
+ private:
+ Kind StorageKind = Kind::Empty;
+ llvm::AlignedCharArrayUnion<TempPCHFile, InMemoryPreamble> Storage = {};
+ };
+
+ /// 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::MemoryBuffer *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.
+ 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;
+ /// 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::BeginSourceFile.
+ /// 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
+ virtual std::unique_ptr<PPCallbacks> createPPCallbacks();
+ /// The returned CommentHandler will be added to the preprocessor if not null.
+ virtual CommentHandler *getCommentHandler();
+};
+
+enum class BuildPreambleError {
+ CouldntCreateTempFile = 1,
+ CouldntCreateTargetInfo,
+ BeginSourceFileFailed,
+ CouldntEmitPCH
+};
+
+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