From bb165fb04db511d0f6927133662b74943f76cc39 Mon Sep 17 00:00:00 2001 From: Adrian Prantl Date: Sat, 20 Jun 2015 18:53:08 +0000 Subject: [PATCH] Introduce a PCHContainerOperations interface (NFC). A PCHContainerOperations abstract interface provides operations for creating and unwrapping containers for serialized ASTs (precompiled headers and clang modules). The default implementation is RawPCHContainerOperations, which uses a flat file for the output. The main application for this interface will be an ObjectFilePCHContainerOperations implementation that uses LLVM to wrap the module in an ELF/Mach-O/COFF container to store debug info alongside the AST. rdar://problem/20091852 llvm-svn: 240225 --- clang/include/clang/ARCMigrate/ARCMT.h | 36 ++++--- clang/include/clang/Frontend/ASTUnit.h | 52 +++++++--- clang/include/clang/Frontend/CompilerInstance.h | 14 ++- clang/include/clang/Frontend/FrontendActions.h | 15 ++- .../clang/Frontend/PCHContainerOperations.h | 76 ++++++++++++++ clang/include/clang/Frontend/Utils.h | 5 +- clang/include/clang/Serialization/ASTReader.h | 30 +++--- clang/include/clang/Serialization/ASTWriter.h | 13 ++- .../clang/Serialization/GlobalModuleIndex.h | 8 +- clang/include/clang/Serialization/ModuleManager.h | 11 ++- clang/include/clang/Tooling/Refactoring.h | 4 +- clang/include/clang/Tooling/Tooling.h | 63 +++++++++--- clang/lib/ARCMigrate/ARCMT.cpp | 82 ++++++++-------- clang/lib/ARCMigrate/ARCMTActions.cpp | 12 +-- clang/lib/AST/ASTConsumer.cpp | 1 + clang/lib/Frontend/ASTMerge.cpp | 6 +- clang/lib/Frontend/ASTUnit.cpp | 109 +++++++++++++-------- clang/lib/Frontend/CMakeLists.txt | 1 + clang/lib/Frontend/ChainedIncludesSource.cpp | 22 +++-- clang/lib/Frontend/CompilerInstance.cpp | 56 ++++++----- clang/lib/Frontend/FrontendAction.cpp | 16 +-- clang/lib/Frontend/FrontendActions.cpp | 59 +++++++---- clang/lib/Frontend/InitPreprocessor.cpp | 15 +-- clang/lib/Frontend/PCHContainerOperations.cpp | 70 +++++++++++++ clang/lib/Serialization/ASTReader.cpp | 55 ++++++----- clang/lib/Serialization/GeneratePCH.cpp | 33 +++---- clang/lib/Serialization/GlobalModuleIndex.cpp | 17 ++-- clang/lib/Serialization/ModuleManager.cpp | 14 +-- .../lib/StaticAnalyzer/Frontend/ModelInjector.cpp | 2 +- clang/lib/Tooling/Refactoring.cpp | 7 +- clang/lib/Tooling/Tooling.cpp | 95 ++++++++++-------- clang/tools/arcmt-test/arcmt-test.cpp | 7 +- clang/tools/driver/cc1_main.cpp | 4 +- clang/tools/libclang/CIndex.cpp | 9 +- clang/tools/libclang/CIndexCodeCompletion.cpp | 12 +-- clang/tools/libclang/CIndexer.h | 15 ++- clang/tools/libclang/Indexing.cpp | 21 ++-- clang/unittests/ASTMatchers/ASTMatchersTest.h | 1 + 38 files changed, 694 insertions(+), 374 deletions(-) create mode 100644 clang/include/clang/Frontend/PCHContainerOperations.h create mode 100644 clang/lib/Frontend/PCHContainerOperations.cpp diff --git a/clang/include/clang/ARCMigrate/ARCMT.h b/clang/include/clang/ARCMigrate/ARCMT.h index ad4f23c..7408186 100644 --- a/clang/include/clang/ARCMigrate/ARCMT.h +++ b/clang/include/clang/ARCMigrate/ARCMT.h @@ -17,6 +17,7 @@ namespace clang { class ASTContext; class DiagnosticConsumer; + class PCHContainerOperations; namespace arcmt { class MigrationPass; @@ -37,19 +38,22 @@ namespace arcmt { /// the pre-migration ARC diagnostics. /// /// \returns false if no error is produced, true otherwise. -bool checkForManualIssues(CompilerInvocation &CI, - const FrontendInputFile &Input, - DiagnosticConsumer *DiagClient, - bool emitPremigrationARCErrors = false, - StringRef plistOut = StringRef()); +bool +checkForManualIssues(CompilerInvocation &CI, const FrontendInputFile &Input, + std::shared_ptr PCHContainerOps, + DiagnosticConsumer *DiagClient, + bool emitPremigrationARCErrors = false, + StringRef plistOut = StringRef()); /// \brief Works similar to checkForManualIssues but instead of checking, it /// applies automatic modifications to source files to conform to ARC. /// /// \returns false if no error is produced, true otherwise. -bool applyTransformations(CompilerInvocation &origCI, - const FrontendInputFile &Input, - DiagnosticConsumer *DiagClient); +bool +applyTransformations(CompilerInvocation &origCI, + const FrontendInputFile &Input, + std::shared_ptr PCHContainerOps, + DiagnosticConsumer *DiagClient); /// \brief Applies automatic modifications and produces temporary files /// and metadata into the \p outputDir path. @@ -62,12 +66,11 @@ bool applyTransformations(CompilerInvocation &origCI, /// the pre-migration ARC diagnostics. /// /// \returns false if no error is produced, true otherwise. -bool migrateWithTemporaryFiles(CompilerInvocation &origCI, - const FrontendInputFile &Input, - DiagnosticConsumer *DiagClient, - StringRef outputDir, - bool emitPremigrationARCErrors, - StringRef plistOut); +bool migrateWithTemporaryFiles( + CompilerInvocation &origCI, const FrontendInputFile &Input, + std::shared_ptr PCHContainerOps, + DiagnosticConsumer *DiagClient, StringRef outputDir, + bool emitPremigrationARCErrors, StringRef plistOut); /// \brief Get the set of file remappings from the \p outputDir path that /// migrateWithTemporaryFiles produced. @@ -93,13 +96,16 @@ std::vector getAllTransformations(LangOptions::GCMode OrigGCMode, class MigrationProcess { CompilerInvocation OrigCI; + std::shared_ptr PCHContainerOps; DiagnosticConsumer *DiagClient; FileRemapper Remapper; public: bool HadARCErrors; - MigrationProcess(const CompilerInvocation &CI, DiagnosticConsumer *diagClient, + MigrationProcess(const CompilerInvocation &CI, + std::shared_ptr PCHContainerOps, + DiagnosticConsumer *diagClient, StringRef outputDir = StringRef()); class RewriteListener { diff --git a/clang/include/clang/Frontend/ASTUnit.h b/clang/include/clang/Frontend/ASTUnit.h index 405774b..2d38352 100644 --- a/clang/include/clang/Frontend/ASTUnit.h +++ b/clang/include/clang/Frontend/ASTUnit.h @@ -56,6 +56,7 @@ class FileEntry; class FileManager; class HeaderSearch; class Preprocessor; +class PCHContainerOperations; class SourceManager; class TargetInfo; class ASTFrontendAction; @@ -422,7 +423,8 @@ private: explicit ASTUnit(bool MainFileIsAST); void CleanTemporaryFiles(); - bool Parse(std::unique_ptr OverrideMainBuffer); + bool Parse(std::shared_ptr PCHContainerOps, + std::unique_ptr OverrideMainBuffer); struct ComputedPreamble { llvm::MemoryBuffer *Buffer; @@ -442,6 +444,7 @@ private: unsigned MaxLines); std::unique_ptr getMainBufferWithPrecompiledPreamble( + std::shared_ptr PCHContainerOps, const CompilerInvocation &PreambleInvocationIn, bool AllowRebuild = true, unsigned MaxLines = 0); void RealizeTopLevelDeclsFromPreamble(); @@ -715,12 +718,16 @@ public: /// /// \param Filename - The AST file to load. /// + /// \param PCHContainerOps - The PCHContainerOperations to use for loading and + /// creating modules. /// \param Diags - The diagnostics engine to use for reporting errors; its /// lifetime is expected to extend past that of the returned ASTUnit. /// /// \returns - The initialized ASTUnit or null if the AST failed to load. static std::unique_ptr LoadFromASTFile( - const std::string &Filename, IntrusiveRefCntPtr Diags, + const std::string &Filename, + std::shared_ptr PCHContainerOps, + IntrusiveRefCntPtr Diags, const FileSystemOptions &FileSystemOpts, bool OnlyLocalDecls = false, ArrayRef RemappedFiles = None, bool CaptureDiagnostics = false, bool AllowPCHWithCompilerErrors = false, @@ -735,8 +742,10 @@ private: /// /// \returns \c true if a catastrophic failure occurred (which means that the /// \c ASTUnit itself is invalid), or \c false otherwise. - bool LoadFromCompilerInvocation(bool PrecompilePreamble); - + bool LoadFromCompilerInvocation( + std::shared_ptr PCHContainerOps, + bool PrecompilePreamble); + public: /// \brief Create an ASTUnit from a source file, via a CompilerInvocation @@ -745,6 +754,9 @@ public: /// \param CI - The compiler invocation to use; it must have exactly one input /// source file. The ASTUnit takes ownership of the CompilerInvocation object. /// + /// \param PCHContainerOps - The PCHContainerOperations to use for loading and + /// creating modules. + /// /// \param Diags - The diagnostics engine to use for reporting errors; its /// lifetime is expected to extend past that of the returned ASTUnit. /// @@ -765,7 +777,9 @@ public: /// created ASTUnit was passed in \p Unit then the caller can check that. /// static ASTUnit *LoadFromCompilerInvocationAction( - CompilerInvocation *CI, IntrusiveRefCntPtr Diags, + CompilerInvocation *CI, + std::shared_ptr PCHContainerOps, + IntrusiveRefCntPtr Diags, ASTFrontendAction *Action = nullptr, ASTUnit *Unit = nullptr, bool Persistent = true, StringRef ResourceFilesPath = StringRef(), bool OnlyLocalDecls = false, bool CaptureDiagnostics = false, @@ -780,15 +794,20 @@ public: /// \param CI - The compiler invocation to use; it must have exactly one input /// source file. The ASTUnit takes ownership of the CompilerInvocation object. /// + /// \param PCHContainerOps - The PCHContainerOperations to use for loading and + /// creating modules. + /// /// \param Diags - The diagnostics engine to use for reporting errors; its /// lifetime is expected to extend past that of the returned ASTUnit. // // FIXME: Move OnlyLocalDecls, UseBumpAllocator to setters on the ASTUnit, we // shouldn't need to specify them at construction time. static std::unique_ptr LoadFromCompilerInvocation( - CompilerInvocation *CI, IntrusiveRefCntPtr Diags, - bool OnlyLocalDecls = false, bool CaptureDiagnostics = false, - bool PrecompilePreamble = false, TranslationUnitKind TUKind = TU_Complete, + CompilerInvocation *CI, + std::shared_ptr PCHContainerOps, + IntrusiveRefCntPtr Diags, bool OnlyLocalDecls = false, + bool CaptureDiagnostics = false, bool PrecompilePreamble = false, + TranslationUnitKind TUKind = TU_Complete, bool CacheCodeCompletionResults = false, bool IncludeBriefCommentsInCodeCompletion = false, bool UserFilesAreVolatile = false); @@ -800,6 +819,9 @@ public: /// /// \param ArgEnd - The end of the argument vector. /// + /// \param PCHContainerOps - The PCHContainerOperations to use for loading and + /// creating modules. + /// /// \param Diags - The diagnostics engine to use for reporting errors; its /// lifetime is expected to extend past that of the returned ASTUnit. /// @@ -813,6 +835,7 @@ public: // shouldn't need to specify them at construction time. static ASTUnit *LoadFromCommandLine( const char **ArgBegin, const char **ArgEnd, + std::shared_ptr PCHContainerOps, IntrusiveRefCntPtr Diags, StringRef ResourceFilesPath, bool OnlyLocalDecls = false, bool CaptureDiagnostics = false, ArrayRef RemappedFiles = None, @@ -828,8 +851,9 @@ public: /// were originally used to produce this translation unit. /// /// \returns True if a failure occurred that causes the ASTUnit not to - /// contain any translation-unit information, false otherwise. - bool Reparse(ArrayRef RemappedFiles = None); + /// contain any translation-unit information, false otherwise. + bool Reparse(std::shared_ptr PCHContainerOps, + ArrayRef RemappedFiles = None); /// \brief Perform code completion at the given file, line, and /// column within this translation unit. @@ -852,14 +876,14 @@ public: /// FIXME: The Diag, LangOpts, SourceMgr, FileMgr, StoredDiagnostics, and /// OwnedBuffers parameters are all disgusting hacks. They will go away. void CodeComplete(StringRef File, unsigned Line, unsigned Column, - ArrayRef RemappedFiles, - bool IncludeMacros, bool IncludeCodePatterns, - bool IncludeBriefComments, + ArrayRef RemappedFiles, bool IncludeMacros, + bool IncludeCodePatterns, bool IncludeBriefComments, CodeCompleteConsumer &Consumer, + std::shared_ptr PCHContainerOps, DiagnosticsEngine &Diag, LangOptions &LangOpts, SourceManager &SourceMgr, FileManager &FileMgr, SmallVectorImpl &StoredDiagnostics, - SmallVectorImpl &OwnedBuffers); + SmallVectorImpl &OwnedBuffers); /// \brief Save this translation unit to a file with the given name. /// diff --git a/clang/include/clang/Frontend/CompilerInstance.h b/clang/include/clang/Frontend/CompilerInstance.h index 8d0d939..9cd806c 100644 --- a/clang/include/clang/Frontend/CompilerInstance.h +++ b/clang/include/clang/Frontend/CompilerInstance.h @@ -11,6 +11,7 @@ #define LLVM_CLANG_FRONTEND_COMPILERINSTANCE_H_ #include "clang/AST/ASTConsumer.h" +#include "clang/Frontend/PCHContainerOperations.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/SourceManager.h" #include "clang/Frontend/CompilerInvocation.h" @@ -109,6 +110,9 @@ class CompilerInstance : public ModuleLoader { /// \brief The module dependency collector for crashdumps std::shared_ptr ModuleDepCollector; + /// \brief The module provider. + std::shared_ptr ThePCHContainerOperations; + /// \brief The dependency file generator. std::unique_ptr TheDependencyFileGenerator; @@ -172,7 +176,10 @@ class CompilerInstance : public ModuleLoader { CompilerInstance(const CompilerInstance &) = delete; void operator=(const CompilerInstance &) = delete; public: - explicit CompilerInstance(bool BuildingModule = false); + explicit CompilerInstance( + std::shared_ptr PCHContainerOps = + std::make_shared(), + bool BuildingModule = false); ~CompilerInstance() override; /// @name High-Level Operations @@ -492,6 +499,10 @@ public: void setModuleDepCollector( std::shared_ptr Collector); + std::shared_ptr getPCHContainerOperations() const { + return ThePCHContainerOperations; + } + /// } /// @name Code Completion /// { @@ -605,6 +616,7 @@ public: static IntrusiveRefCntPtr createPCHExternalASTSource( StringRef Path, const std::string &Sysroot, bool DisablePCHValidation, bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context, + const PCHContainerOperations &PCHContainerOps, void *DeserializationListener, bool OwnDeserializationListener, bool Preamble, bool UseGlobalModuleIndex); diff --git a/clang/include/clang/Frontend/FrontendActions.h b/clang/include/clang/Frontend/FrontendActions.h index b150828..f61775f 100644 --- a/clang/include/clang/Frontend/FrontendActions.h +++ b/clang/include/clang/Frontend/FrontendActions.h @@ -85,10 +85,9 @@ public: /// create the PCHGenerator instance returned by CreateASTConsumer. /// /// \returns true if an error occurred, false otherwise. - static raw_ostream *ComputeASTConsumerArguments(CompilerInstance &CI, - StringRef InFile, - std::string &Sysroot, - std::string &OutputFile); + static raw_pwrite_stream * + ComputeASTConsumerArguments(CompilerInstance &CI, StringRef InFile, + std::string &Sysroot, std::string &OutputFile); }; class GenerateModuleAction : public ASTFrontendAction { @@ -118,10 +117,10 @@ public: /// create the PCHGenerator instance returned by CreateASTConsumer. /// /// \returns true if an error occurred, false otherwise. - raw_ostream *ComputeASTConsumerArguments(CompilerInstance &CI, - StringRef InFile, - std::string &Sysroot, - std::string &OutputFile); + raw_pwrite_stream *ComputeASTConsumerArguments(CompilerInstance &CI, + StringRef InFile, + std::string &Sysroot, + std::string &OutputFile); }; class SyntaxOnlyAction : public ASTFrontendAction { diff --git a/clang/include/clang/Frontend/PCHContainerOperations.h b/clang/include/clang/Frontend/PCHContainerOperations.h new file mode 100644 index 0000000..949ee63 --- /dev/null +++ b/clang/include/clang/Frontend/PCHContainerOperations.h @@ -0,0 +1,76 @@ +//===--- Frontend/PCHContainerOperations.h - PCH Containers -----*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_PCH_CONTAINER_OPERATIONS_H +#define LLVM_CLANG_PCH_CONTAINER_OPERATIONS_H + +#include "llvm/ADT/SmallVector.h" +#include "llvm/Support/MemoryBuffer.h" +#include + +namespace llvm { +class raw_pwrite_stream; +class BitstreamReader; +} + +namespace clang { + +class ASTConsumer; +class CodeGenOptions; +class DiagnosticsEngine; +class HeaderSearchOptions; +class LangOptions; +class PreprocessorOptions; +class TargetOptions; + +struct PCHBuffer { + bool IsComplete; + llvm::SmallVector Data; +}; + +/// \brief This abstract interface provides operations for creating +/// and unwrapping containers for serialized ASTs (precompiled headers +/// and clang modules). +class PCHContainerOperations { +public: + virtual ~PCHContainerOperations(); + /// \brief Return an ASTConsumer that can be chained with a + /// PCHGenerator that produces a wrapper file format containing a + /// serialized AST bitstream. + virtual std::unique_ptr CreatePCHContainerGenerator( + DiagnosticsEngine &Diags, const HeaderSearchOptions &HSO, + const PreprocessorOptions &PPO, const TargetOptions &TO, + const LangOptions &LO, const std::string &MainFileName, + const std::string &OutputFileName, llvm::raw_pwrite_stream *OS, + std::shared_ptr Buffer) const = 0; + + /// \brief Initialize an llvm::BitstreamReader with the serialized AST inside + /// the PCH container Buffer. + virtual void ExtractPCH(llvm::MemoryBufferRef Buffer, + llvm::BitstreamReader &StreamFile) const = 0; +}; + +/// \brief Implements a raw pass-through PCH container. +class RawPCHContainerOperations : public PCHContainerOperations { + /// \brief Return an ASTConsumer that can be chained with a + /// PCHGenerator that writes the module to a flat file. + std::unique_ptr CreatePCHContainerGenerator( + DiagnosticsEngine &Diags, const HeaderSearchOptions &HSO, + const PreprocessorOptions &PPO, const TargetOptions &TO, + const LangOptions &LO, const std::string &MainFileName, + const std::string &OutputFileName, llvm::raw_pwrite_stream *OS, + std::shared_ptr Buffer) const override; + + /// \brief Initialize an llvm::BitstreamReader with Buffer. + void ExtractPCH(llvm::MemoryBufferRef Buffer, + llvm::BitstreamReader &StreamFile) const override; +}; +} + +#endif diff --git a/clang/include/clang/Frontend/Utils.h b/clang/include/clang/Frontend/Utils.h index cd0ebf6..6399653 100644 --- a/clang/include/clang/Frontend/Utils.h +++ b/clang/include/clang/Frontend/Utils.h @@ -45,6 +45,7 @@ class HeaderSearch; class HeaderSearchOptions; class IdentifierTable; class LangOptions; +class PCHContainerOperations; class Preprocessor; class PreprocessorOptions; class PreprocessorOutputOptions; @@ -61,8 +62,8 @@ void ApplyHeaderSearchOptions(HeaderSearch &HS, /// InitializePreprocessor - Initialize the preprocessor getting it and the /// environment ready to process a single file. -void InitializePreprocessor(Preprocessor &PP, - const PreprocessorOptions &PPOpts, +void InitializePreprocessor(Preprocessor &PP, const PreprocessorOptions &PPOpts, + const PCHContainerOperations &PCHContainerOps, const FrontendOptions &FEOpts); /// DoPrintPreprocessedInput - Implement -E mode. diff --git a/clang/include/clang/Serialization/ASTReader.h b/clang/include/clang/Serialization/ASTReader.h index c7cc1be..429f00f 100644 --- a/clang/include/clang/Serialization/ASTReader.h +++ b/clang/include/clang/Serialization/ASTReader.h @@ -362,6 +362,7 @@ private: SourceManager &SourceMgr; FileManager &FileMgr; + const PCHContainerOperations &PCHContainerOps; DiagnosticsEngine &Diags; /// \brief The semantic analysis object that will be processing the @@ -1237,6 +1238,9 @@ public: /// \param Context the AST context that this precompiled header will be /// loaded into. /// + /// \param PCHContainerOps the PCHContainerOperations to use for loading and + /// creating modules. + /// /// \param isysroot If non-NULL, the system include path specified by the /// user. This is only used with relocatable PCH files. If non-NULL, /// a relocatable PCH file will use the default path "/". @@ -1258,12 +1262,12 @@ public: /// /// \param UseGlobalIndex If true, the AST reader will try to load and use /// the global module index. - ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot = "", - bool DisableValidation = false, + ASTReader(Preprocessor &PP, ASTContext &Context, + const PCHContainerOperations &PCHContainerOps, + StringRef isysroot = "", bool DisableValidation = false, bool AllowASTWithCompilerErrors = false, bool AllowConfigurationMismatch = false, - bool ValidateSystemInputs = false, - bool UseGlobalIndex = true); + bool ValidateSystemInputs = false, bool UseGlobalIndex = true); ~ASTReader() override; @@ -1425,21 +1429,23 @@ public: /// \brief Retrieve the name of the original source file name directly from /// the AST file, without actually loading the AST file. - static std::string getOriginalSourceFile(const std::string &ASTFileName, - FileManager &FileMgr, - DiagnosticsEngine &Diags); + static std::string + getOriginalSourceFile(const std::string &ASTFileName, FileManager &FileMgr, + const PCHContainerOperations &PCHContainerOps, + DiagnosticsEngine &Diags); /// \brief Read the control block for the named AST file. /// /// \returns true if an error occurred, false otherwise. - static bool readASTFileControlBlock(StringRef Filename, - FileManager &FileMgr, - ASTReaderListener &Listener); + static bool + readASTFileControlBlock(StringRef Filename, FileManager &FileMgr, + const PCHContainerOperations &PCHContainerOps, + ASTReaderListener &Listener); /// \brief Determine whether the given AST file is acceptable to load into a /// translation unit with the given language and target options. - static bool isAcceptableASTFile(StringRef Filename, - FileManager &FileMgr, + static bool isAcceptableASTFile(StringRef Filename, FileManager &FileMgr, + const PCHContainerOperations &PCHContainerOps, const LangOptions &LangOpts, const TargetOptions &TargetOpts, const PreprocessorOptions &PPOpts, diff --git a/clang/include/clang/Serialization/ASTWriter.h b/clang/include/clang/Serialization/ASTWriter.h index 297ee22..decd07a 100644 --- a/clang/include/clang/Serialization/ASTWriter.h +++ b/clang/include/clang/Serialization/ASTWriter.h @@ -17,6 +17,7 @@ #include "clang/AST/ASTMutationListener.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclarationName.h" +#include "clang/Frontend/PCHContainerOperations.h" #include "clang/AST/TemplateBase.h" #include "clang/Sema/SemaConsumer.h" #include "clang/Serialization/ASTBitCodes.h" @@ -868,30 +869,28 @@ class PCHGenerator : public SemaConsumer { std::string OutputFile; clang::Module *Module; std::string isysroot; - raw_ostream *Out; Sema *SemaPtr; - SmallVector Buffer; + std::shared_ptr Buffer; llvm::BitstreamWriter Stream; ASTWriter Writer; bool AllowASTWithErrors; - bool HasEmittedPCH; protected: ASTWriter &getWriter() { return Writer; } const ASTWriter &getWriter() const { return Writer; } + SmallVectorImpl &getPCH() const { return Buffer->Data; } public: PCHGenerator(const Preprocessor &PP, StringRef OutputFile, - clang::Module *Module, - StringRef isysroot, raw_ostream *Out, + clang::Module *Module, StringRef isysroot, + std::shared_ptr Buffer, bool AllowASTWithErrors = false); ~PCHGenerator() override; void InitializeSema(Sema &S) override { SemaPtr = &S; } void HandleTranslationUnit(ASTContext &Ctx) override; ASTMutationListener *GetASTMutationListener() override; ASTDeserializationListener *GetASTDeserializationListener() override; - - bool hasEmittedPCH() const { return HasEmittedPCH; } + bool hasEmittedPCH() const { return Buffer->IsComplete; } }; } // end namespace clang diff --git a/clang/include/clang/Serialization/GlobalModuleIndex.h b/clang/include/clang/Serialization/GlobalModuleIndex.h index 640c7bb..7e20510 100644 --- a/clang/include/clang/Serialization/GlobalModuleIndex.h +++ b/clang/include/clang/Serialization/GlobalModuleIndex.h @@ -35,6 +35,7 @@ class DirectoryEntry; class FileEntry; class FileManager; class IdentifierIterator; +class PCHContainerOperations; namespace serialization { class ModuleFile; @@ -192,10 +193,13 @@ public: /// \brief Write a global index into the given /// /// \param FileMgr The file manager to use to load module files. - /// + /// \param PCHContainerOps - The PCHContainerOperations to use for loading and + /// creating modules. /// \param Path The path to the directory containing module files, into /// which the global index will be written. - static ErrorCode writeIndex(FileManager &FileMgr, StringRef Path); + static ErrorCode writeIndex(FileManager &FileMgr, + const PCHContainerOperations &PCHContainerOps, + StringRef Path); }; } diff --git a/clang/include/clang/Serialization/ModuleManager.h b/clang/include/clang/Serialization/ModuleManager.h index 3de86fe..ea4b57f 100644 --- a/clang/include/clang/Serialization/ModuleManager.h +++ b/clang/include/clang/Serialization/ModuleManager.h @@ -24,6 +24,7 @@ namespace clang { class GlobalModuleIndex; class ModuleMap; +class PCHContainerOperations; namespace serialization { @@ -49,7 +50,10 @@ class ModuleManager { /// \brief FileManager that handles translating between filenames and /// FileEntry *. FileManager &FileMgr; - + + /// \brief Knows how to unwrap module containers. + const PCHContainerOperations &PCHContainerOps; + /// \brief A lookup of in-memory (virtual file) buffers llvm::DenseMap> InMemoryBuffers; @@ -112,8 +116,9 @@ public: typedef SmallVectorImpl::const_iterator ModuleConstIterator; typedef SmallVectorImpl::reverse_iterator ModuleReverseIterator; typedef std::pair ModuleOffset; - - explicit ModuleManager(FileManager &FileMgr); + + explicit ModuleManager(FileManager &FileMgr, + const PCHContainerOperations &PCHContainerOps); ~ModuleManager(); /// \brief Forward iterator to traverse all loaded modules. This is reverse diff --git a/clang/include/clang/Tooling/Refactoring.h b/clang/include/clang/Tooling/Refactoring.h index e3e7f83..944fd41 100644 --- a/clang/include/clang/Tooling/Refactoring.h +++ b/clang/include/clang/Tooling/Refactoring.h @@ -38,7 +38,9 @@ class RefactoringTool : public ClangTool { public: /// \see ClangTool::ClangTool. RefactoringTool(const CompilationDatabase &Compilations, - ArrayRef SourcePaths); + ArrayRef SourcePaths, + std::shared_ptr PCHContainerOps = + std::make_shared()); /// \brief Returns the set of replacements to which replacements should /// be added during the run of the tool. diff --git a/clang/include/clang/Tooling/Tooling.h b/clang/include/clang/Tooling/Tooling.h index ca187b1..fb887e1 100644 --- a/clang/include/clang/Tooling/Tooling.h +++ b/clang/include/clang/Tooling/Tooling.h @@ -31,11 +31,13 @@ #define LLVM_CLANG_TOOLING_TOOLING_H #include "clang/AST/ASTConsumer.h" +#include "clang/Frontend/PCHContainerOperations.h" #include "clang/Basic/Diagnostic.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/LLVM.h" #include "clang/Driver/Util.h" #include "clang/Frontend/FrontendAction.h" +#include "clang/Lex/ModuleLoader.h" #include "clang/Tooling/ArgumentsAdjusters.h" #include "clang/Tooling/CompilationDatabase.h" #include "llvm/ADT/StringMap.h" @@ -66,9 +68,10 @@ public: virtual ~ToolAction(); /// \brief Perform an action for an invocation. - virtual bool runInvocation(clang::CompilerInvocation *Invocation, - FileManager *Files, - DiagnosticConsumer *DiagConsumer) = 0; + virtual bool + runInvocation(clang::CompilerInvocation *Invocation, FileManager *Files, + std::shared_ptr PCHContainerOps, + DiagnosticConsumer *DiagConsumer) = 0; }; /// \brief Interface to generate clang::FrontendActions. @@ -83,6 +86,7 @@ public: /// \brief Invokes the compiler with a FrontendAction created by create(). bool runInvocation(clang::CompilerInvocation *Invocation, FileManager *Files, + std::shared_ptr PCHContainerOps, DiagnosticConsumer *DiagConsumer) override; /// \brief Returns a new clang::FrontendAction. @@ -139,10 +143,14 @@ inline std::unique_ptr newFrontendActionFactory( /// \param ToolAction The action to run over the code. /// \param Code C++ code. /// \param FileName The file name which 'Code' will be mapped as. +/// \param PCHContainerOps The PCHContainerOperations for loading and creating +/// clang modules. /// /// \return - True if 'ToolAction' was successfully executed. bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code, - const Twine &FileName = "input.cc"); + const Twine &FileName = "input.cc", + std::shared_ptr PCHContainerOps = + std::make_shared()); /// The first part of the pair is the filename, the second part the /// file-content. @@ -155,37 +163,48 @@ typedef std::vector> FileContentMappings; /// \param Code C++ code. /// \param Args Additional flags to pass on. /// \param FileName The file name which 'Code' will be mapped as. +/// \param PCHContainerOps The PCHContainerOperations for loading and creating +/// clang modules. /// /// \return - True if 'ToolAction' was successfully executed. bool runToolOnCodeWithArgs( clang::FrontendAction *ToolAction, const Twine &Code, const std::vector &Args, const Twine &FileName = "input.cc", + std::shared_ptr PCHContainerOps = + std::make_shared(), const FileContentMappings &VirtualMappedFiles = FileContentMappings()); /// \brief Builds an AST for 'Code'. /// /// \param Code C++ code. /// \param FileName The file name which 'Code' will be mapped as. +/// \param PCHContainerOps The PCHContainerOperations for loading and creating +/// clang modules. /// /// \return The resulting AST or null if an error occurred. -std::unique_ptr buildASTFromCode(const Twine &Code, - const Twine &FileName = "input.cc"); +std::unique_ptr +buildASTFromCode(const Twine &Code, const Twine &FileName = "input.cc", + std::shared_ptr PCHContainerOps = + std::make_shared()); /// \brief Builds an AST for 'Code' with additional flags. /// /// \param Code C++ code. /// \param Args Additional flags to pass on. /// \param FileName The file name which 'Code' will be mapped as. +/// \param PCHContainerOps The PCHContainerOperations for loading and creating +/// clang modules. /// /// \return The resulting AST or null if an error occurred. -std::unique_ptr -buildASTFromCodeWithArgs(const Twine &Code, - const std::vector &Args, - const Twine &FileName = "input.cc"); +std::unique_ptr buildASTFromCodeWithArgs( + const Twine &Code, const std::vector &Args, + const Twine &FileName = "input.cc", + std::shared_ptr PCHContainerOps = + std::make_shared()); /// \brief Utility to run a FrontendAction in a single clang invocation. class ToolInvocation { - public: +public: /// \brief Create a tool invocation. /// /// \param CommandLine The command line arguments to clang. Note that clang @@ -195,16 +214,23 @@ class ToolInvocation { /// \param FAction The action to be executed. Class takes ownership. /// \param Files The FileManager used for the execution. Class does not take /// ownership. + /// \param PCHContainerOps The PCHContainerOperations for loading and creating + /// clang modules. ToolInvocation(std::vector CommandLine, FrontendAction *FAction, - FileManager *Files); + FileManager *Files, + std::shared_ptr PCHContainerOps = + std::make_shared()); /// \brief Create a tool invocation. /// /// \param CommandLine The command line arguments to clang. /// \param Action The action to be executed. /// \param Files The FileManager used for the execution. + /// \param PCHContainerOps The PCHContainerOperations for loading and creating + /// clang modules. ToolInvocation(std::vector CommandLine, ToolAction *Action, - FileManager *Files); + FileManager *Files, + std::shared_ptr PCHContainerOps); ~ToolInvocation(); @@ -229,12 +255,14 @@ class ToolInvocation { bool runInvocation(const char *BinaryName, clang::driver::Compilation *Compilation, - clang::CompilerInvocation *Invocation); + clang::CompilerInvocation *Invocation, + std::shared_ptr PCHContainerOps); std::vector CommandLine; ToolAction *Action; bool OwnsAction; FileManager *Files; + std::shared_ptr PCHContainerOps; // Maps -> . llvm::StringMap MappedFileContents; DiagnosticConsumer *DiagConsumer; @@ -255,8 +283,12 @@ class ClangTool { /// command lines for the given source paths. /// \param SourcePaths The source files to run over. If a source files is /// not found in Compilations, it is skipped. + /// \param PCHContainerOps The PCHContainerOperations for loading and creating + /// clang modules. ClangTool(const CompilationDatabase &Compilations, - ArrayRef SourcePaths); + ArrayRef SourcePaths, + std::shared_ptr PCHContainerOps = + std::make_shared()); ~ClangTool(); @@ -297,6 +329,7 @@ class ClangTool { private: const CompilationDatabase &Compilations; std::vector SourcePaths; + std::shared_ptr PCHContainerOps; llvm::IntrusiveRefCntPtr Files; // Contains a list of pairs (, ). diff --git a/clang/lib/ARCMigrate/ARCMT.cpp b/clang/lib/ARCMigrate/ARCMT.cpp index f266eaf..f33ad21 100644 --- a/clang/lib/ARCMigrate/ARCMT.cpp +++ b/clang/lib/ARCMigrate/ARCMT.cpp @@ -166,7 +166,8 @@ static bool HasARCRuntime(CompilerInvocation &origCI) { } static CompilerInvocation * -createInvocationForMigration(CompilerInvocation &origCI) { +createInvocationForMigration(CompilerInvocation &origCI, + const PCHContainerOperations &PCHContainerOps) { std::unique_ptr CInvok; CInvok.reset(new CompilerInvocation(origCI)); PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts(); @@ -178,9 +179,8 @@ createInvocationForMigration(CompilerInvocation &origCI) { IntrusiveRefCntPtr Diags( new DiagnosticsEngine(DiagID, &origCI.getDiagnosticOpts(), new IgnoringDiagConsumer())); - std::string OriginalFile = - ASTReader::getOriginalSourceFile(PPOpts.ImplicitPCHInclude, - FileMgr, *Diags); + std::string OriginalFile = ASTReader::getOriginalSourceFile( + PPOpts.ImplicitPCHInclude, FileMgr, PCHContainerOps, *Diags); if (!OriginalFile.empty()) PPOpts.Includes.insert(PPOpts.Includes.begin(), OriginalFile); PPOpts.ImplicitPCHInclude.clear(); @@ -230,11 +230,11 @@ static void emitPremigrationErrors(const CapturedDiagList &arcDiags, // checkForManualIssues. //===----------------------------------------------------------------------===// -bool arcmt::checkForManualIssues(CompilerInvocation &origCI, - const FrontendInputFile &Input, - DiagnosticConsumer *DiagClient, - bool emitPremigrationARCErrors, - StringRef plistOut) { +bool arcmt::checkForManualIssues( + CompilerInvocation &origCI, const FrontendInputFile &Input, + std::shared_ptr PCHContainerOps, + DiagnosticConsumer *DiagClient, bool emitPremigrationARCErrors, + StringRef plistOut) { if (!origCI.getLangOpts()->ObjC1) return false; @@ -247,7 +247,7 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI, assert(!transforms.empty()); std::unique_ptr CInvok; - CInvok.reset(createInvocationForMigration(origCI)); + CInvok.reset(createInvocationForMigration(origCI, *PCHContainerOps)); CInvok->getFrontendOpts().Inputs.clear(); CInvok->getFrontendOpts().Inputs.push_back(Input); @@ -263,8 +263,8 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI, CaptureDiagnosticConsumer errRec(*Diags, *DiagClient, capturedDiags); Diags->setClient(&errRec, /*ShouldOwnClient=*/false); - std::unique_ptr Unit( - ASTUnit::LoadFromCompilerInvocationAction(CInvok.release(), Diags)); + std::unique_ptr Unit(ASTUnit::LoadFromCompilerInvocationAction( + CInvok.release(), PCHContainerOps, Diags)); if (!Unit) { errRec.FinishCapture(); return true; @@ -330,12 +330,11 @@ bool arcmt::checkForManualIssues(CompilerInvocation &origCI, // applyTransformations. //===----------------------------------------------------------------------===// -static bool applyTransforms(CompilerInvocation &origCI, - const FrontendInputFile &Input, - DiagnosticConsumer *DiagClient, - StringRef outputDir, - bool emitPremigrationARCErrors, - StringRef plistOut) { +static bool +applyTransforms(CompilerInvocation &origCI, const FrontendInputFile &Input, + std::shared_ptr PCHContainerOps, + DiagnosticConsumer *DiagClient, StringRef outputDir, + bool emitPremigrationARCErrors, StringRef plistOut) { if (!origCI.getLangOpts()->ObjC1) return false; @@ -343,15 +342,16 @@ static bool applyTransforms(CompilerInvocation &origCI, // Make sure checking is successful first. CompilerInvocation CInvokForCheck(origCI); - if (arcmt::checkForManualIssues(CInvokForCheck, Input, DiagClient, - emitPremigrationARCErrors, plistOut)) + if (arcmt::checkForManualIssues(CInvokForCheck, Input, PCHContainerOps, + DiagClient, emitPremigrationARCErrors, + plistOut)) return true; CompilerInvocation CInvok(origCI); CInvok.getFrontendOpts().Inputs.clear(); CInvok.getFrontendOpts().Inputs.push_back(Input); - - MigrationProcess migration(CInvok, DiagClient, outputDir); + + MigrationProcess migration(CInvok, PCHContainerOps, DiagClient, outputDir); bool NoFinalizeRemoval = origCI.getMigratorOpts().NoFinalizeRemoval; std::vector transforms = arcmt::getAllTransformations(OrigGCMode, @@ -376,22 +376,22 @@ static bool applyTransforms(CompilerInvocation &origCI, } } -bool arcmt::applyTransformations(CompilerInvocation &origCI, - const FrontendInputFile &Input, - DiagnosticConsumer *DiagClient) { - return applyTransforms(origCI, Input, DiagClient, +bool arcmt::applyTransformations( + CompilerInvocation &origCI, const FrontendInputFile &Input, + std::shared_ptr PCHContainerOps, + DiagnosticConsumer *DiagClient) { + return applyTransforms(origCI, Input, PCHContainerOps, DiagClient, StringRef(), false, StringRef()); } -bool arcmt::migrateWithTemporaryFiles(CompilerInvocation &origCI, - const FrontendInputFile &Input, - DiagnosticConsumer *DiagClient, - StringRef outputDir, - bool emitPremigrationARCErrors, - StringRef plistOut) { +bool arcmt::migrateWithTemporaryFiles( + CompilerInvocation &origCI, const FrontendInputFile &Input, + std::shared_ptr PCHContainerOps, + DiagnosticConsumer *DiagClient, StringRef outputDir, + bool emitPremigrationARCErrors, StringRef plistOut) { assert(!outputDir.empty() && "Expected output directory path"); - return applyTransforms(origCI, Input, DiagClient, - outputDir, emitPremigrationARCErrors, plistOut); + return applyTransforms(origCI, Input, PCHContainerOps, DiagClient, outputDir, + emitPremigrationARCErrors, plistOut); } bool arcmt::getFileRemappings(std::vector > & @@ -499,10 +499,12 @@ public: /// \brief Anchor for VTable. MigrationProcess::RewriteListener::~RewriteListener() { } -MigrationProcess::MigrationProcess(const CompilerInvocation &CI, - DiagnosticConsumer *diagClient, - StringRef outputDir) - : OrigCI(CI), DiagClient(diagClient), HadARCErrors(false) { +MigrationProcess::MigrationProcess( + const CompilerInvocation &CI, + std::shared_ptr PCHContainerOps, + DiagnosticConsumer *diagClient, StringRef outputDir) + : OrigCI(CI), PCHContainerOps(PCHContainerOps), DiagClient(diagClient), + HadARCErrors(false) { if (!outputDir.empty()) { IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); IntrusiveRefCntPtr Diags( @@ -515,7 +517,7 @@ MigrationProcess::MigrationProcess(const CompilerInvocation &CI, bool MigrationProcess::applyTransform(TransformFn trans, RewriteListener *listener) { std::unique_ptr CInvok; - CInvok.reset(createInvocationForMigration(OrigCI)); + CInvok.reset(createInvocationForMigration(OrigCI, *PCHContainerOps)); CInvok->getDiagnosticOpts().IgnoreWarnings = true; Remapper.applyMappings(CInvok->getPreprocessorOpts()); @@ -537,7 +539,7 @@ bool MigrationProcess::applyTransform(TransformFn trans, ASTAction.reset(new ARCMTMacroTrackerAction(ARCMTMacroLocs)); std::unique_ptr Unit(ASTUnit::LoadFromCompilerInvocationAction( - CInvok.release(), Diags, ASTAction.get())); + CInvok.release(), PCHContainerOps, Diags, ASTAction.get())); if (!Unit) { errRec.FinishCapture(); return true; diff --git a/clang/lib/ARCMigrate/ARCMTActions.cpp b/clang/lib/ARCMigrate/ARCMTActions.cpp index 0ed36dd..39a922f 100644 --- a/clang/lib/ARCMigrate/ARCMTActions.cpp +++ b/clang/lib/ARCMigrate/ARCMTActions.cpp @@ -16,6 +16,7 @@ using namespace arcmt; bool CheckAction::BeginInvocation(CompilerInstance &CI) { if (arcmt::checkForManualIssues(CI.getInvocation(), getCurrentInput(), + CI.getPCHContainerOperations(), CI.getDiagnostics().getClient())) return false; // errors, stop the action. @@ -29,6 +30,7 @@ CheckAction::CheckAction(FrontendAction *WrappedAction) bool ModifyAction::BeginInvocation(CompilerInstance &CI) { return !arcmt::applyTransformations(CI.getInvocation(), getCurrentInput(), + CI.getPCHContainerOperations(), CI.getDiagnostics().getClient()); } @@ -36,12 +38,10 @@ ModifyAction::ModifyAction(FrontendAction *WrappedAction) : WrapperFrontendAction(WrappedAction) {} bool MigrateAction::BeginInvocation(CompilerInstance &CI) { - if (arcmt::migrateWithTemporaryFiles(CI.getInvocation(), - getCurrentInput(), - CI.getDiagnostics().getClient(), - MigrateDir, - EmitPremigrationARCErros, - PlistOut)) + if (arcmt::migrateWithTemporaryFiles( + CI.getInvocation(), getCurrentInput(), CI.getPCHContainerOperations(), + CI.getDiagnostics().getClient(), MigrateDir, EmitPremigrationARCErros, + PlistOut)) return false; // errors, stop the action. // We only want to see diagnostics emitted by migrateWithTemporaryFiles. diff --git a/clang/lib/AST/ASTConsumer.cpp b/clang/lib/AST/ASTConsumer.cpp index 55033b23..cff82e9 100644 --- a/clang/lib/AST/ASTConsumer.cpp +++ b/clang/lib/AST/ASTConsumer.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "clang/AST/ASTConsumer.h" +#include "llvm/Bitcode/BitstreamReader.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclGroup.h" using namespace clang; diff --git a/clang/lib/Frontend/ASTMerge.cpp b/clang/lib/Frontend/ASTMerge.cpp index b84df94..f6f1551 100644 --- a/clang/lib/Frontend/ASTMerge.cpp +++ b/clang/lib/Frontend/ASTMerge.cpp @@ -45,8 +45,10 @@ void ASTMergeAction::ExecuteAction() { new ForwardingDiagnosticConsumer( *CI.getDiagnostics().getClient()), /*ShouldOwnClient=*/true)); - std::unique_ptr Unit = ASTUnit::LoadFromASTFile( - ASTFiles[I], Diags, CI.getFileSystemOpts(), false); + std::unique_ptr Unit = + ASTUnit::LoadFromASTFile(ASTFiles[I], CI.getPCHContainerOperations(), + Diags, CI.getFileSystemOpts(), false); + if (!Unit) continue; diff --git a/clang/lib/Frontend/ASTUnit.cpp b/clang/lib/Frontend/ASTUnit.cpp index 4fd330d..01c56bd 100644 --- a/clang/lib/Frontend/ASTUnit.cpp +++ b/clang/lib/Frontend/ASTUnit.cpp @@ -648,7 +648,9 @@ void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr Diags, } std::unique_ptr ASTUnit::LoadFromASTFile( - const std::string &Filename, IntrusiveRefCntPtr Diags, + const std::string &Filename, + std::shared_ptr PCHContainerOps, + IntrusiveRefCntPtr Diags, const FileSystemOptions &FileSystemOpts, bool OnlyLocalDecls, ArrayRef RemappedFiles, bool CaptureDiagnostics, bool AllowPCHWithCompilerErrors, bool UserFilesAreVolatile) { @@ -705,10 +707,10 @@ std::unique_ptr ASTUnit::LoadFromASTFile( bool disableValid = false; if (::getenv("LIBCLANG_DISABLE_PCH_VALIDATION")) disableValid = true; - AST->Reader = new ASTReader(PP, Context, - /*isysroot=*/"", - /*DisableValidation=*/disableValid, - AllowPCHWithCompilerErrors); + AST->Reader = new ASTReader(PP, Context, *PCHContainerOps, + /*isysroot=*/"", + /*DisableValidation=*/disableValid, + AllowPCHWithCompilerErrors); AST->Reader->setListener(llvm::make_unique( *AST->PP, Context, AST->ASTFileLangOpts, AST->TargetOpts, AST->Target, @@ -916,13 +918,16 @@ class PrecompilePreambleConsumer : public PCHGenerator { unsigned &Hash; std::vector TopLevelDecls; PrecompilePreambleAction *Action; + raw_ostream *Out; public: PrecompilePreambleConsumer(ASTUnit &Unit, PrecompilePreambleAction *Action, const Preprocessor &PP, StringRef isysroot, raw_ostream *Out) - : PCHGenerator(PP, "", nullptr, isysroot, Out, /*AllowASTWithErrors=*/true), - Unit(Unit), Hash(Unit.getCurrentTopLevelHashValue()), Action(Action) { + : PCHGenerator(PP, "", nullptr, isysroot, std::make_shared(), + /*AllowASTWithErrors=*/true), + Unit(Unit), Hash(Unit.getCurrentTopLevelHashValue()), Action(Action), + Out(Out) { Hash = 0; } @@ -943,6 +948,14 @@ public: void HandleTranslationUnit(ASTContext &Ctx) override { PCHGenerator::HandleTranslationUnit(Ctx); if (hasEmittedPCH()) { + // Write the generated bitstream to "Out". + *Out << getPCH(); + // Make sure it hits disk now. + Out->flush(); + // Free the buffer. + llvm::SmallVector Empty; + getPCH() = std::move(Empty); + // Translate the top-level declarations we captured during // parsing into declaration IDs in the precompiled // preamble. This will allow us to deserialize those top-level @@ -1015,14 +1028,16 @@ static void checkAndSanitizeDiags(SmallVectorImpl & /// /// \returns True if a failure occurred that causes the ASTUnit not to /// contain any translation-unit information, false otherwise. -bool ASTUnit::Parse(std::unique_ptr OverrideMainBuffer) { +bool ASTUnit::Parse(std::shared_ptr PCHContainerOps, + std::unique_ptr OverrideMainBuffer) { SavedMainFileBuffer.reset(); if (!Invocation) return true; // Create the compiler instance to use for building the AST. - std::unique_ptr Clang(new CompilerInstance()); + std::unique_ptr Clang( + new CompilerInstance(PCHContainerOps)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar @@ -1323,6 +1338,7 @@ makeStandaloneDiagnostic(const LangOptions &LangOpts, /// Otherwise, returns a NULL pointer. std::unique_ptr ASTUnit::getMainBufferWithPrecompiledPreamble( + std::shared_ptr PCHContainerOps, const CompilerInvocation &PreambleInvocationIn, bool AllowRebuild, unsigned MaxLines) { @@ -1487,7 +1503,8 @@ ASTUnit::getMainBufferWithPrecompiledPreamble( PreprocessorOpts.PrecompiledPreambleBytes.second = false; // Create the compiler instance to use for building the precompiled preamble. - std::unique_ptr Clang(new CompilerInstance()); + std::unique_ptr Clang( + new CompilerInstance(PCHContainerOps)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar @@ -1702,12 +1719,13 @@ ASTUnit *ASTUnit::create(CompilerInvocation *CI, } ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( - CompilerInvocation *CI, IntrusiveRefCntPtr Diags, - ASTFrontendAction *Action, ASTUnit *Unit, bool Persistent, - StringRef ResourceFilesPath, bool OnlyLocalDecls, bool CaptureDiagnostics, - bool PrecompilePreamble, bool CacheCodeCompletionResults, - bool IncludeBriefCommentsInCodeCompletion, bool UserFilesAreVolatile, - std::unique_ptr *ErrAST) { + CompilerInvocation *CI, + std::shared_ptr PCHContainerOps, + IntrusiveRefCntPtr Diags, ASTFrontendAction *Action, + ASTUnit *Unit, bool Persistent, StringRef ResourceFilesPath, + bool OnlyLocalDecls, bool CaptureDiagnostics, bool PrecompilePreamble, + bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion, + bool UserFilesAreVolatile, std::unique_ptr *ErrAST) { assert(CI && "A CompilerInvocation is required"); std::unique_ptr OwnAST; @@ -1746,7 +1764,8 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( ProcessWarningOptions(AST->getDiagnostics(), CI->getDiagnosticOpts()); // Create the compiler instance to use for building the AST. - std::unique_ptr Clang(new CompilerInstance()); + std::unique_ptr Clang( + new CompilerInstance(PCHContainerOps)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar @@ -1841,7 +1860,9 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction( return AST; } -bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) { +bool ASTUnit::LoadFromCompilerInvocation( + std::shared_ptr PCHContainerOps, + bool PrecompilePreamble) { if (!Invocation) return true; @@ -1853,7 +1874,8 @@ bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) { std::unique_ptr OverrideMainBuffer; if (PrecompilePreamble) { PreambleRebuildCounter = 2; - OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation); + OverrideMainBuffer = + getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation); } SimpleTimer ParsingTimer(WantTiming); @@ -1863,12 +1885,14 @@ bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) { llvm::CrashRecoveryContextCleanupRegistrar MemBufferCleanup(OverrideMainBuffer.get()); - return Parse(std::move(OverrideMainBuffer)); + return Parse(PCHContainerOps, std::move(OverrideMainBuffer)); } std::unique_ptr ASTUnit::LoadFromCompilerInvocation( - CompilerInvocation *CI, IntrusiveRefCntPtr Diags, - bool OnlyLocalDecls, bool CaptureDiagnostics, bool PrecompilePreamble, + CompilerInvocation *CI, + std::shared_ptr PCHContainerOps, + IntrusiveRefCntPtr Diags, bool OnlyLocalDecls, + bool CaptureDiagnostics, bool PrecompilePreamble, TranslationUnitKind TUKind, bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion, bool UserFilesAreVolatile) { // Create the AST unit. @@ -1897,13 +1921,14 @@ std::unique_ptr ASTUnit::LoadFromCompilerInvocation( llvm::CrashRecoveryContextReleaseRefCleanup > DiagCleanup(Diags.get()); - if (AST->LoadFromCompilerInvocation(PrecompilePreamble)) + if (AST->LoadFromCompilerInvocation(PCHContainerOps, PrecompilePreamble)) return nullptr; return AST; } ASTUnit *ASTUnit::LoadFromCommandLine( const char **ArgBegin, const char **ArgEnd, + std::shared_ptr PCHContainerOps, IntrusiveRefCntPtr Diags, StringRef ResourceFilesPath, bool OnlyLocalDecls, bool CaptureDiagnostics, ArrayRef RemappedFiles, bool RemappedFilesKeepOriginalName, @@ -1975,7 +2000,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine( llvm::CrashRecoveryContextCleanupRegistrar ASTUnitCleanup(AST.get()); - if (AST->LoadFromCompilerInvocation(PrecompilePreamble)) { + if (AST->LoadFromCompilerInvocation(PCHContainerOps, PrecompilePreamble)) { // Some error occurred, if caller wants to examine diagnostics, pass it the // ASTUnit. if (ErrAST) { @@ -1988,7 +2013,8 @@ ASTUnit *ASTUnit::LoadFromCommandLine( return AST.release(); } -bool ASTUnit::Reparse(ArrayRef RemappedFiles) { +bool ASTUnit::Reparse(std::shared_ptr PCHContainerOps, + ArrayRef RemappedFiles) { if (!Invocation) return true; @@ -2012,8 +2038,9 @@ bool ASTUnit::Reparse(ArrayRef RemappedFiles) { // build a precompiled preamble, do so now. std::unique_ptr OverrideMainBuffer; if (!getPreambleFile(this).empty() || PreambleRebuildCounter > 0) - OverrideMainBuffer = getMainBufferWithPrecompiledPreamble(*Invocation); - + OverrideMainBuffer = + getMainBufferWithPrecompiledPreamble(PCHContainerOps, *Invocation); + // Clear out the diagnostics state. getDiagnostics().Reset(); ProcessWarningOptions(getDiagnostics(), Invocation->getDiagnosticOpts()); @@ -2021,7 +2048,7 @@ bool ASTUnit::Reparse(ArrayRef RemappedFiles) { getDiagnostics().setNumWarnings(NumWarningsInPreamble); // Parse the sources - bool Result = Parse(std::move(OverrideMainBuffer)); + bool Result = Parse(PCHContainerOps, std::move(OverrideMainBuffer)); // If we're caching global code-completion results, and the top-level // declarations have changed, clear out the code-completion cache. @@ -2273,18 +2300,15 @@ void AugmentedCodeCompleteConsumer::ProcessCodeCompleteResults(Sema &S, AllResults.size()); } - - -void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column, - ArrayRef RemappedFiles, - bool IncludeMacros, - bool IncludeCodePatterns, - bool IncludeBriefComments, - CodeCompleteConsumer &Consumer, - DiagnosticsEngine &Diag, LangOptions &LangOpts, - SourceManager &SourceMgr, FileManager &FileMgr, - SmallVectorImpl &StoredDiagnostics, - SmallVectorImpl &OwnedBuffers) { +void ASTUnit::CodeComplete( + StringRef File, unsigned Line, unsigned Column, + ArrayRef RemappedFiles, bool IncludeMacros, + bool IncludeCodePatterns, bool IncludeBriefComments, + CodeCompleteConsumer &Consumer, + std::shared_ptr PCHContainerOps, + DiagnosticsEngine &Diag, LangOptions &LangOpts, SourceManager &SourceMgr, + FileManager &FileMgr, SmallVectorImpl &StoredDiagnostics, + SmallVectorImpl &OwnedBuffers) { if (!Invocation) return; @@ -2318,7 +2342,8 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column, LangOpts.SpellChecking = false; CCInvocation->getDiagnosticOpts().IgnoreWarnings = true; - std::unique_ptr Clang(new CompilerInstance()); + std::unique_ptr Clang( + new CompilerInstance(PCHContainerOps)); // Recover resources if we crash before exiting this method. llvm::CrashRecoveryContextCleanupRegistrar @@ -2389,7 +2414,7 @@ void ASTUnit::CodeComplete(StringRef File, unsigned Line, unsigned Column, if (!llvm::sys::fs::getUniqueID(MainPath, MainID)) { if (CompleteFileID == MainID && Line > 1) OverrideMainBuffer = getMainBufferWithPrecompiledPreamble( - *CCInvocation, false, Line - 1); + PCHContainerOps, *CCInvocation, false, Line - 1); } } } diff --git a/clang/lib/Frontend/CMakeLists.txt b/clang/lib/Frontend/CMakeLists.txt index 7c5fca5..9a3e459 100644 --- a/clang/lib/Frontend/CMakeLists.txt +++ b/clang/lib/Frontend/CMakeLists.txt @@ -31,6 +31,7 @@ add_clang_library(clangFrontend LogDiagnosticPrinter.cpp ModuleDependencyCollector.cpp MultiplexConsumer.cpp + PCHContainerOperations.cpp PrintPreprocessedOutput.cpp SerializedDiagnosticPrinter.cpp SerializedDiagnosticReader.cpp diff --git a/clang/lib/Frontend/ChainedIncludesSource.cpp b/clang/lib/Frontend/ChainedIncludesSource.cpp index f3677f8..be30d43 100644 --- a/clang/lib/Frontend/ChainedIncludesSource.cpp +++ b/clang/lib/Frontend/ChainedIncludesSource.cpp @@ -80,8 +80,9 @@ createASTReader(CompilerInstance &CI, StringRef pchFile, ASTDeserializationListener *deserialListener = nullptr) { Preprocessor &PP = CI.getPreprocessor(); std::unique_ptr Reader; - Reader.reset(new ASTReader(PP, CI.getASTContext(), /*isysroot=*/"", - /*DisableValidation=*/true)); + Reader.reset(new ASTReader(PP, CI.getASTContext(), + *CI.getPCHContainerOperations(), + /*isysroot=*/"", /*DisableValidation=*/true)); for (unsigned ti = 0; ti < bufNames.size(); ++ti) { StringRef sr(bufNames[ti]); Reader->addInMemoryBuffer(sr, std::move(MemBufs[ti])); @@ -145,7 +146,8 @@ IntrusiveRefCntPtr clang::createChainedIncludesSource( IntrusiveRefCntPtr Diags( new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient)); - std::unique_ptr Clang(new CompilerInstance()); + std::unique_ptr Clang( + new CompilerInstance(CI.getPCHContainerOperations())); Clang->setInvocation(CInvok.release()); Clang->setDiagnostics(Diags.get()); Clang->setTarget(TargetInfo::CreateTargetInfo( @@ -157,11 +159,9 @@ IntrusiveRefCntPtr clang::createChainedIncludesSource( &Clang->getPreprocessor()); Clang->createASTContext(); - SmallVector serialAST; - llvm::raw_svector_ostream OS(serialAST); - auto consumer = - llvm::make_unique(Clang->getPreprocessor(), "-", nullptr, - /*isysroot=*/"", &OS); + auto Buffer = std::make_shared(); + auto consumer = llvm::make_unique( + Clang->getPreprocessor(), "-", nullptr, /*isysroot=*/"", Buffer); Clang->getASTContext().setASTMutationListener( consumer->GetASTMutationListener()); Clang->setASTConsumer(std::move(consumer)); @@ -198,7 +198,11 @@ IntrusiveRefCntPtr clang::createChainedIncludesSource( ParseAST(Clang->getSema()); Clang->getDiagnosticClient().EndSourceFile(); - SerialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy(OS.str())); + assert(Buffer->IsComplete && "serialization did not complete"); + auto &serialAST = Buffer->Data; + SerialBufs.push_back(llvm::MemoryBuffer::getMemBufferCopy( + StringRef(serialAST.data(), serialAST.size()))); + serialAST.clear(); source->CIs.push_back(Clang.release()); } diff --git a/clang/lib/Frontend/CompilerInstance.cpp b/clang/lib/Frontend/CompilerInstance.cpp index aef3905..6b0fed6 100644 --- a/clang/lib/Frontend/CompilerInstance.cpp +++ b/clang/lib/Frontend/CompilerInstance.cpp @@ -51,12 +51,13 @@ using namespace clang; -CompilerInstance::CompilerInstance(bool BuildingModule) - : ModuleLoader(BuildingModule), - Invocation(new CompilerInvocation()), ModuleManager(nullptr), - BuildGlobalModuleIndex(false), HaveFullGlobalModuleIndex(false), - ModuleBuildFailed(false) { -} +CompilerInstance::CompilerInstance( + std::shared_ptr PCHContainerOps, + bool BuildingModule) + : ModuleLoader(BuildingModule), Invocation(new CompilerInvocation()), + ModuleManager(nullptr), ThePCHContainerOperations(PCHContainerOps), + BuildGlobalModuleIndex(false), HaveFullGlobalModuleIndex(false), + ModuleBuildFailed(false) {} CompilerInstance::~CompilerInstance() { assert(OutputFiles.empty() && "Still output files in flight?"); @@ -321,7 +322,8 @@ void CompilerInstance::createPreprocessor(TranslationUnitKind TUKind) { PP->getFileManager(), PPOpts); // Predefine macros and configure the preprocessor. - InitializePreprocessor(*PP, PPOpts, getFrontendOpts()); + InitializePreprocessor(*PP, PPOpts, *getPCHContainerOperations(), + getFrontendOpts()); // Initialize the header search object. ApplyHeaderSearchOptions(PP->getHeaderSearchInfo(), getHeaderSearchOpts(), @@ -397,22 +399,24 @@ void CompilerInstance::createPCHExternalASTSource( ModuleManager = createPCHExternalASTSource( Path, getHeaderSearchOpts().Sysroot, DisablePCHValidation, AllowPCHWithCompilerErrors, getPreprocessor(), getASTContext(), - DeserializationListener, OwnDeserializationListener, Preamble, + *getPCHContainerOperations(), DeserializationListener, + OwnDeserializationListener, Preamble, getFrontendOpts().UseGlobalModuleIndex); } IntrusiveRefCntPtr CompilerInstance::createPCHExternalASTSource( StringRef Path, const std::string &Sysroot, bool DisablePCHValidation, bool AllowPCHWithCompilerErrors, Preprocessor &PP, ASTContext &Context, + const PCHContainerOperations &PCHContainerOps, void *DeserializationListener, bool OwnDeserializationListener, bool Preamble, bool UseGlobalModuleIndex) { HeaderSearchOptions &HSOpts = PP.getHeaderSearchInfo().getHeaderSearchOpts(); - IntrusiveRefCntPtr Reader( - new ASTReader(PP, Context, Sysroot.empty() ? "" : Sysroot.c_str(), - DisablePCHValidation, AllowPCHWithCompilerErrors, - /*AllowConfigurationMismatch*/ false, - HSOpts.ModulesValidateSystemHeaders, UseGlobalModuleIndex)); + IntrusiveRefCntPtr Reader(new ASTReader( + PP, Context, PCHContainerOps, Sysroot.empty() ? "" : Sysroot.c_str(), + DisablePCHValidation, AllowPCHWithCompilerErrors, + /*AllowConfigurationMismatch*/ false, HSOpts.ModulesValidateSystemHeaders, + UseGlobalModuleIndex)); // We need the external source to be set up before we read the AST, because // eagerly-deserialized declarations may use it. @@ -918,7 +922,8 @@ static bool compileModuleImpl(CompilerInstance &ImportingInstance, // Construct a compiler instance that will be used to actually create the // module. - CompilerInstance Instance(/*BuildingModule=*/true); + CompilerInstance Instance(ImportingInstance.getPCHContainerOperations(), + /*BuildingModule=*/true); Instance.setInvocation(&*Invocation); Instance.createDiagnostics(new ForwardingDiagnosticConsumer( @@ -1232,13 +1237,13 @@ void CompilerInstance::createModuleManager() { HeaderSearchOptions &HSOpts = getHeaderSearchOpts(); std::string Sysroot = HSOpts.Sysroot; const PreprocessorOptions &PPOpts = getPreprocessorOpts(); - ModuleManager = new ASTReader(getPreprocessor(), *Context, - Sysroot.empty() ? "" : Sysroot.c_str(), - PPOpts.DisablePCHValidation, - /*AllowASTWithCompilerErrors=*/false, - /*AllowConfigurationMismatch=*/false, - HSOpts.ModulesValidateSystemHeaders, - getFrontendOpts().UseGlobalModuleIndex); + ModuleManager = new ASTReader( + getPreprocessor(), *Context, *getPCHContainerOperations(), + Sysroot.empty() ? "" : Sysroot.c_str(), PPOpts.DisablePCHValidation, + /*AllowASTWithCompilerErrors=*/false, + /*AllowConfigurationMismatch=*/false, + HSOpts.ModulesValidateSystemHeaders, + getFrontendOpts().UseGlobalModuleIndex); if (hasASTConsumer()) { ModuleManager->setDeserializationListener( getASTConsumer().GetASTDeserializationListener()); @@ -1279,6 +1284,7 @@ bool CompilerInstance::loadModuleFile(StringRef FileName) { ModuleFileStack.push_back(FileName); ModuleNameStack.push_back(StringRef()); if (ASTReader::readASTFileControlBlock(FileName, CI.getFileManager(), + *CI.getPCHContainerOperations(), *this)) { CI.getDiagnostics().Report( SourceLocation(), CI.getFileManager().getBufferForFile(FileName) @@ -1644,8 +1650,8 @@ GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex( llvm::sys::fs::create_directories( getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); GlobalModuleIndex::writeIndex( - getFileManager(), - getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); + getFileManager(), *getPCHContainerOperations(), + getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); ModuleManager->resetForReload(); ModuleManager->loadGlobalIndex(); GlobalIndex = ModuleManager->getGlobalIndex(); @@ -1672,8 +1678,8 @@ GlobalModuleIndex *CompilerInstance::loadGlobalModuleIndex( } if (RecreateIndex) { GlobalModuleIndex::writeIndex( - getFileManager(), - getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); + getFileManager(), *getPCHContainerOperations(), + getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); ModuleManager->resetForReload(); ModuleManager->loadGlobalIndex(); GlobalIndex = ModuleManager->getGlobalIndex(); diff --git a/clang/lib/Frontend/FrontendAction.cpp b/clang/lib/Frontend/FrontendAction.cpp index 9bba755..db9dd3b 100644 --- a/clang/lib/Frontend/FrontendAction.cpp +++ b/clang/lib/Frontend/FrontendAction.cpp @@ -191,7 +191,8 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, IntrusiveRefCntPtr Diags(&CI.getDiagnostics()); std::unique_ptr AST = - ASTUnit::LoadFromASTFile(InputFile, Diags, CI.getFileSystemOpts()); + ASTUnit::LoadFromASTFile(InputFile, CI.getPCHContainerOperations(), + Diags, CI.getFileSystemOpts()); if (!AST) goto failure; @@ -271,11 +272,10 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI, for (llvm::sys::fs::directory_iterator Dir(DirNative, EC), DirEnd; Dir != DirEnd && !EC; Dir.increment(EC)) { // Check whether this is an acceptable AST file. - if (ASTReader::isAcceptableASTFile(Dir->path(), FileMgr, - CI.getLangOpts(), - CI.getTargetOpts(), - CI.getPreprocessorOpts(), - SpecificModuleCachePath)) { + if (ASTReader::isAcceptableASTFile( + Dir->path(), FileMgr, *CI.getPCHContainerOperations(), + CI.getLangOpts(), CI.getTargetOpts(), CI.getPreprocessorOpts(), + SpecificModuleCachePath)) { PPOpts.ImplicitPCHInclude = Dir->path(); Found = true; break; @@ -443,8 +443,8 @@ bool FrontendAction::Execute() { if (CI.shouldBuildGlobalModuleIndex() && CI.hasFileManager() && CI.hasPreprocessor()) { GlobalModuleIndex::writeIndex( - CI.getFileManager(), - CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); + CI.getFileManager(), *CI.getPCHContainerOperations(), + CI.getPreprocessor().getHeaderSearchInfo().getModuleCachePath()); } return true; diff --git a/clang/lib/Frontend/FrontendActions.cpp b/clang/lib/Frontend/FrontendActions.cpp index 46cdeeb..6f202a15 100644 --- a/clang/lib/Frontend/FrontendActions.cpp +++ b/clang/lib/Frontend/FrontendActions.cpp @@ -14,6 +14,7 @@ #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/CompilerInstance.h" #include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/MultiplexConsumer.h" #include "clang/Frontend/Utils.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/Pragma.h" @@ -79,18 +80,28 @@ std::unique_ptr GeneratePCHAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { std::string Sysroot; std::string OutputFile; - raw_ostream *OS = + raw_pwrite_stream *OS = ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile); if (!OS) return nullptr; if (!CI.getFrontendOpts().RelocatablePCH) Sysroot.clear(); - return llvm::make_unique(CI.getPreprocessor(), OutputFile, - nullptr, Sysroot, OS); + + auto Buffer = std::make_shared(); + std::vector> Consumers; + Consumers.push_back(llvm::make_unique( + CI.getPreprocessor(), OutputFile, nullptr, Sysroot, Buffer)); + Consumers.push_back( + CI.getPCHContainerOperations()->CreatePCHContainerGenerator( + CI.getDiagnostics(), CI.getHeaderSearchOpts(), + CI.getPreprocessorOpts(), CI.getTargetOpts(), CI.getLangOpts(), + InFile, OutputFile, OS, Buffer)); + + return llvm::make_unique(std::move(Consumers)); } -raw_ostream *GeneratePCHAction::ComputeASTConsumerArguments( +raw_pwrite_stream *GeneratePCHAction::ComputeASTConsumerArguments( CompilerInstance &CI, StringRef InFile, std::string &Sysroot, std::string &OutputFile) { Sysroot = CI.getHeaderSearchOpts().Sysroot; @@ -102,7 +113,7 @@ raw_ostream *GeneratePCHAction::ComputeASTConsumerArguments( // We use createOutputFile here because this is exposed via libclang, and we // must disable the RemoveFileOnSignal behavior. // We use a temporary to avoid race conditions. - raw_ostream *OS = + raw_pwrite_stream *OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, /*RemoveFileOnSignal=*/false, InFile, /*Extension=*/"", /*useTemporary=*/true); @@ -118,13 +129,21 @@ GenerateModuleAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { std::string Sysroot; std::string OutputFile; - raw_ostream *OS = + raw_pwrite_stream *OS = ComputeASTConsumerArguments(CI, InFile, Sysroot, OutputFile); if (!OS) return nullptr; - return llvm::make_unique(CI.getPreprocessor(), OutputFile, - Module, Sysroot, OS); + auto Buffer = std::make_shared(); + std::vector> Consumers; + Consumers.push_back(llvm::make_unique( + CI.getPreprocessor(), OutputFile, Module, Sysroot, Buffer)); + Consumers.push_back( + CI.getPCHContainerOperations()->CreatePCHContainerGenerator( + CI.getDiagnostics(), CI.getHeaderSearchOpts(), + CI.getPreprocessorOpts(), CI.getTargetOpts(), CI.getLangOpts(), + InFile, OutputFile, OS, Buffer)); + return llvm::make_unique(std::move(Consumers)); } static SmallVectorImpl & @@ -348,7 +367,7 @@ bool GenerateModuleAction::BeginSourceFileAction(CompilerInstance &CI, return true; } -raw_ostream *GenerateModuleAction::ComputeASTConsumerArguments( +raw_pwrite_stream *GenerateModuleAction::ComputeASTConsumerArguments( CompilerInstance &CI, StringRef InFile, std::string &Sysroot, std::string &OutputFile) { // If no output file was provided, figure out where this module would go @@ -363,7 +382,7 @@ raw_ostream *GenerateModuleAction::ComputeASTConsumerArguments( // We use createOutputFile here because this is exposed via libclang, and we // must disable the RemoveFileOnSignal behavior. // We use a temporary to avoid race conditions. - raw_ostream *OS = + raw_pwrite_stream *OS = CI.createOutputFile(CI.getFrontendOpts().OutputFile, /*Binary=*/true, /*RemoveFileOnSignal=*/false, InFile, /*Extension=*/"", /*useTemporary=*/true, @@ -395,13 +414,13 @@ void VerifyPCHAction::ExecuteAction() { CompilerInstance &CI = getCompilerInstance(); bool Preamble = CI.getPreprocessorOpts().PrecompiledPreambleBytes.first != 0; const std::string &Sysroot = CI.getHeaderSearchOpts().Sysroot; - std::unique_ptr Reader( - new ASTReader(CI.getPreprocessor(), CI.getASTContext(), - Sysroot.empty() ? "" : Sysroot.c_str(), - /*DisableValidation*/ false, - /*AllowPCHWithCompilerErrors*/ false, - /*AllowConfigurationMismatch*/ true, - /*ValidateSystemInputs*/ true)); + std::unique_ptr Reader(new ASTReader( + CI.getPreprocessor(), CI.getASTContext(), *CI.getPCHContainerOperations(), + Sysroot.empty() ? "" : Sysroot.c_str(), + /*DisableValidation*/ false, + /*AllowPCHWithCompilerErrors*/ false, + /*AllowConfigurationMismatch*/ true, + /*ValidateSystemInputs*/ true)); Reader->ReadAST(getCurrentFile(), Preamble ? serialization::MK_Preamble @@ -550,9 +569,9 @@ void DumpModuleInfoAction::ExecuteAction() { Out << "Information for module file '" << getCurrentFile() << "':\n"; DumpModuleInfoListener Listener(Out); - ASTReader::readASTFileControlBlock(getCurrentFile(), - getCompilerInstance().getFileManager(), - Listener); + ASTReader::readASTFileControlBlock( + getCurrentFile(), getCompilerInstance().getFileManager(), + *getCompilerInstance().getPCHContainerOperations(), Listener); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index dfc46f4..2417146 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -97,10 +97,11 @@ static void AddImplicitIncludePTH(MacroBuilder &Builder, Preprocessor &PP, /// \brief Add an implicit \#include using the original file used to generate /// a PCH file. static void AddImplicitIncludePCH(MacroBuilder &Builder, Preprocessor &PP, + const PCHContainerOperations &PCHContainerOps, StringRef ImplicitIncludePCH) { std::string OriginalFile = - ASTReader::getOriginalSourceFile(ImplicitIncludePCH, PP.getFileManager(), - PP.getDiagnostics()); + ASTReader::getOriginalSourceFile(ImplicitIncludePCH, PP.getFileManager(), + PCHContainerOps, PP.getDiagnostics()); if (OriginalFile.empty()) return; @@ -891,9 +892,10 @@ static void InitializePredefinedMacros(const TargetInfo &TI, /// InitializePreprocessor - Initialize the preprocessor getting it and the /// environment ready to process a single file. This returns true on error. /// -void clang::InitializePreprocessor(Preprocessor &PP, - const PreprocessorOptions &InitOpts, - const FrontendOptions &FEOpts) { +void clang::InitializePreprocessor( + Preprocessor &PP, const PreprocessorOptions &InitOpts, + const PCHContainerOperations &PCHContainerOps, + const FrontendOptions &FEOpts) { const LangOptions &LangOpts = PP.getLangOpts(); std::string PredefineBuffer; PredefineBuffer.reserve(4080); @@ -952,7 +954,8 @@ void clang::InitializePreprocessor(Preprocessor &PP, // Process -include-pch/-include-pth directives. if (!InitOpts.ImplicitPCHInclude.empty()) - AddImplicitIncludePCH(Builder, PP, InitOpts.ImplicitPCHInclude); + AddImplicitIncludePCH(Builder, PP, PCHContainerOps, + InitOpts.ImplicitPCHInclude); if (!InitOpts.ImplicitPTHInclude.empty()) AddImplicitIncludePTH(Builder, PP, InitOpts.ImplicitPTHInclude); diff --git a/clang/lib/Frontend/PCHContainerOperations.cpp b/clang/lib/Frontend/PCHContainerOperations.cpp new file mode 100644 index 0000000..fd3278b --- /dev/null +++ b/clang/lib/Frontend/PCHContainerOperations.cpp @@ -0,0 +1,70 @@ +//===--- Frontend/PCHContainerOperations.cpp - PCH Containers ---*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines PCHContainerOperations and RawPCHContainerOperation. +// +//===----------------------------------------------------------------------===// + +#include "clang/Frontend/PCHContainerOperations.h" +#include "clang/AST/ASTConsumer.h" +#include "llvm/Bitcode/BitstreamReader.h" +#include "llvm/Support/raw_ostream.h" +#include "clang/Lex/ModuleLoader.h" +using namespace clang; + +PCHContainerOperations::~PCHContainerOperations() {} + +namespace { + +/// \brief A PCHContainerGenerator that writes out the PCH to a flat file. +class PCHContainerGenerator : public ASTConsumer { + std::shared_ptr Buffer; + raw_pwrite_stream *OS; + +public: + PCHContainerGenerator(DiagnosticsEngine &Diags, + const HeaderSearchOptions &HSO, + const PreprocessorOptions &PPO, const TargetOptions &TO, + const LangOptions &LO, const std::string &MainFileName, + const std::string &OutputFileName, + llvm::raw_pwrite_stream *OS, + std::shared_ptr Buffer) + : Buffer(Buffer), OS(OS) {} + + virtual ~PCHContainerGenerator() {} + + void HandleTranslationUnit(ASTContext &Ctx) override { + if (Buffer->IsComplete) { + // Make sure it hits disk now. + *OS << Buffer->Data; + OS->flush(); + } + // Free the space of the temporary buffer. + llvm::SmallVector Empty; + Buffer->Data = std::move(Empty); + } +}; +} + +std::unique_ptr +RawPCHContainerOperations::CreatePCHContainerGenerator( + DiagnosticsEngine &Diags, const HeaderSearchOptions &HSO, + const PreprocessorOptions &PPO, const TargetOptions &TO, + const LangOptions &LO, const std::string &MainFileName, + const std::string &OutputFileName, llvm::raw_pwrite_stream *OS, + std::shared_ptr Buffer) const { + return llvm::make_unique( + Diags, HSO, PPO, TO, LO, MainFileName, OutputFileName, OS, Buffer); +} + +void RawPCHContainerOperations::ExtractPCH( + llvm::MemoryBufferRef Buffer, llvm::BitstreamReader &StreamFile) const { + StreamFile.init((const unsigned char *)Buffer.getBufferStart(), + (const unsigned char *)Buffer.getBufferEnd()); +} diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp index 609c25d..d75b5eb7 100644 --- a/clang/lib/Serialization/ASTReader.cpp +++ b/clang/lib/Serialization/ASTReader.cpp @@ -19,6 +19,7 @@ #include "clang/AST/DeclTemplate.h" #include "clang/AST/Expr.h" #include "clang/AST/ExprCXX.h" +#include "clang/Frontend/PCHContainerOperations.h" #include "clang/AST/NestedNameSpecifier.h" #include "clang/AST/Type.h" #include "clang/AST/TypeLocVisitor.h" @@ -3590,6 +3591,7 @@ ASTReader::ReadASTCore(StringRef FileName, ModuleFile &F = *M; BitstreamCursor &Stream = F.Stream; + PCHContainerOps.ExtractPCH(F.Buffer->getMemBufferRef(), F.StreamFile); Stream.init(&F.StreamFile); F.SizeInBits = F.Buffer->getBufferSize() * 8; @@ -3858,9 +3860,9 @@ static ASTFileSignature readASTFileSignature(llvm::BitstreamReader &StreamFile){ /// \brief Retrieve the name of the original source file name /// directly from the AST file, without actually loading the AST /// file. -std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName, - FileManager &FileMgr, - DiagnosticsEngine &Diags) { +std::string ASTReader::getOriginalSourceFile( + const std::string &ASTFileName, FileManager &FileMgr, + const PCHContainerOperations &PCHContainerOps, DiagnosticsEngine &Diags) { // Open the AST file. auto Buffer = FileMgr.getBufferForFile(ASTFileName); if (!Buffer) { @@ -3871,8 +3873,7 @@ std::string ASTReader::getOriginalSourceFile(const std::string &ASTFileName, // Initialize the stream llvm::BitstreamReader StreamFile; - StreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(), - (const unsigned char *)(*Buffer)->getBufferEnd()); + PCHContainerOps.ExtractPCH((*Buffer)->getMemBufferRef(), StreamFile); BitstreamCursor Stream(StreamFile); // Sniff for the signature. @@ -3954,9 +3955,10 @@ namespace { }; } -bool ASTReader::readASTFileControlBlock(StringRef Filename, - FileManager &FileMgr, - ASTReaderListener &Listener) { +bool ASTReader::readASTFileControlBlock( + StringRef Filename, FileManager &FileMgr, + const PCHContainerOperations &PCHContainerOps, + ASTReaderListener &Listener) { // Open the AST file. // FIXME: This allows use of the VFS; we do not allow use of the // VFS when actually loading a module. @@ -4147,16 +4149,15 @@ bool ASTReader::readASTFileControlBlock(StringRef Filename, } } - -bool ASTReader::isAcceptableASTFile(StringRef Filename, - FileManager &FileMgr, - const LangOptions &LangOpts, - const TargetOptions &TargetOpts, - const PreprocessorOptions &PPOpts, - std::string ExistingModuleCachePath) { +bool ASTReader::isAcceptableASTFile( + StringRef Filename, FileManager &FileMgr, + const PCHContainerOperations &PCHContainerOps, const LangOptions &LangOpts, + const TargetOptions &TargetOpts, const PreprocessorOptions &PPOpts, + std::string ExistingModuleCachePath) { SimplePCHValidator validator(LangOpts, TargetOpts, PPOpts, ExistingModuleCachePath, FileMgr); - return !readASTFileControlBlock(Filename, FileMgr, validator); + return !readASTFileControlBlock(Filename, FileMgr, PCHContainerOps, + validator); } ASTReader::ASTReadResult @@ -8407,24 +8408,26 @@ void ASTReader::pushExternalDeclIntoScope(NamedDecl *D, DeclarationName Name) { } } -ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, StringRef isysroot, - bool DisableValidation, bool AllowASTWithCompilerErrors, +ASTReader::ASTReader(Preprocessor &PP, ASTContext &Context, + const PCHContainerOperations &PCHContainerOps, + StringRef isysroot, bool DisableValidation, + bool AllowASTWithCompilerErrors, bool AllowConfigurationMismatch, bool ValidateSystemInputs, bool UseGlobalIndex) : Listener(new PCHValidator(PP, *this)), DeserializationListener(nullptr), OwnsDeserializationListener(false), SourceMgr(PP.getSourceManager()), - FileMgr(PP.getFileManager()), Diags(PP.getDiagnostics()), - SemaObj(nullptr), PP(PP), Context(Context), Consumer(nullptr), - ModuleMgr(PP.getFileManager()), isysroot(isysroot), - DisableValidation(DisableValidation), + FileMgr(PP.getFileManager()), PCHContainerOps(PCHContainerOps), + Diags(PP.getDiagnostics()), SemaObj(nullptr), PP(PP), Context(Context), + Consumer(nullptr), ModuleMgr(PP.getFileManager(), PCHContainerOps), + isysroot(isysroot), DisableValidation(DisableValidation), AllowASTWithCompilerErrors(AllowASTWithCompilerErrors), AllowConfigurationMismatch(AllowConfigurationMismatch), ValidateSystemInputs(ValidateSystemInputs), UseGlobalIndex(UseGlobalIndex), TriedLoadingGlobalIndex(false), - CurrSwitchCaseStmts(&SwitchCaseStmts), - NumSLocEntriesRead(0), TotalNumSLocEntries(0), NumStatementsRead(0), - TotalNumStatements(0), NumMacrosRead(0), TotalNumMacros(0), - NumIdentifierLookups(0), NumIdentifierLookupHits(0), NumSelectorsRead(0), + CurrSwitchCaseStmts(&SwitchCaseStmts), NumSLocEntriesRead(0), + TotalNumSLocEntries(0), NumStatementsRead(0), TotalNumStatements(0), + NumMacrosRead(0), TotalNumMacros(0), NumIdentifierLookups(0), + NumIdentifierLookupHits(0), NumSelectorsRead(0), NumMethodPoolEntriesRead(0), NumMethodPoolLookups(0), NumMethodPoolHits(0), NumMethodPoolTableLookups(0), NumMethodPoolTableHits(0), TotalNumMethodPoolEntries(0), diff --git a/clang/lib/Serialization/GeneratePCH.cpp b/clang/lib/Serialization/GeneratePCH.cpp index b5031fd..c50b3f9 100644 --- a/clang/lib/Serialization/GeneratePCH.cpp +++ b/clang/lib/Serialization/GeneratePCH.cpp @@ -24,16 +24,14 @@ using namespace clang; -PCHGenerator::PCHGenerator(const Preprocessor &PP, - StringRef OutputFile, - clang::Module *Module, - StringRef isysroot, - raw_ostream *OS, bool AllowASTWithErrors) - : PP(PP), OutputFile(OutputFile), Module(Module), - isysroot(isysroot.str()), Out(OS), - SemaPtr(nullptr), Stream(Buffer), Writer(Stream), - AllowASTWithErrors(AllowASTWithErrors), - HasEmittedPCH(false) { +PCHGenerator::PCHGenerator(const Preprocessor &PP, StringRef OutputFile, + clang::Module *Module, StringRef isysroot, + std::shared_ptr Buffer, + bool AllowASTWithErrors) + : PP(PP), OutputFile(OutputFile), Module(Module), isysroot(isysroot.str()), + SemaPtr(nullptr), Buffer(Buffer), Stream(Buffer->Data), Writer(Stream), + AllowASTWithErrors(AllowASTWithErrors) { + Buffer->IsComplete = false; } PCHGenerator::~PCHGenerator() { @@ -47,21 +45,12 @@ void PCHGenerator::HandleTranslationUnit(ASTContext &Ctx) { bool hasErrors = PP.getDiagnostics().hasErrorOccurred(); if (hasErrors && !AllowASTWithErrors) return; - - // Emit the PCH file + + // Emit the PCH file to the Buffer. assert(SemaPtr && "No Sema?"); Writer.WriteAST(*SemaPtr, OutputFile, Module, isysroot, hasErrors); - // Write the generated bitstream to "Out". - Out->write((char *)&Buffer.front(), Buffer.size()); - - // Make sure it hits disk now. - Out->flush(); - - // Free up some memory, in case the process is kept alive. - Buffer.clear(); - - HasEmittedPCH = true; + Buffer->IsComplete = true; } ASTMutationListener *PCHGenerator::GetASTMutationListener() { diff --git a/clang/lib/Serialization/GlobalModuleIndex.cpp b/clang/lib/Serialization/GlobalModuleIndex.cpp index 1b52b44..2c7da3e8 100644 --- a/clang/lib/Serialization/GlobalModuleIndex.cpp +++ b/clang/lib/Serialization/GlobalModuleIndex.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "ASTReaderInternals.h" +#include "clang/Frontend/PCHContainerOperations.h" #include "clang/Basic/FileManager.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Serialization/ASTBitCodes.h" @@ -384,6 +385,7 @@ namespace { /// \brief Builder that generates the global module index file. class GlobalModuleIndexBuilder { FileManager &FileMgr; + const PCHContainerOperations &PCHContainerOps; /// \brief Mapping from files to module file information. typedef llvm::MapVector ModuleFilesMap; @@ -416,7 +418,9 @@ namespace { } public: - explicit GlobalModuleIndexBuilder(FileManager &FileMgr) : FileMgr(FileMgr){} + explicit GlobalModuleIndexBuilder( + FileManager &FileMgr, const PCHContainerOperations &PCHContainerOps) + : FileMgr(FileMgr), PCHContainerOps(PCHContainerOps) {} /// \brief Load the contents of the given module file into the builder. /// @@ -501,8 +505,7 @@ bool GlobalModuleIndexBuilder::loadModuleFile(const FileEntry *File) { // Initialize the input stream llvm::BitstreamReader InStreamFile; - InStreamFile.init((const unsigned char *)(*Buffer)->getBufferStart(), - (const unsigned char *)(*Buffer)->getBufferEnd()); + PCHContainerOps.ExtractPCH((*Buffer)->getMemBufferRef(), InStreamFile); llvm::BitstreamCursor InStream(InStreamFile); // Sniff for the signature. @@ -764,7 +767,9 @@ void GlobalModuleIndexBuilder::writeIndex(llvm::BitstreamWriter &Stream) { } GlobalModuleIndex::ErrorCode -GlobalModuleIndex::writeIndex(FileManager &FileMgr, StringRef Path) { +GlobalModuleIndex::writeIndex(FileManager &FileMgr, + const PCHContainerOperations &PCHContainerOps, + StringRef Path) { llvm::SmallString<128> IndexPath; IndexPath += Path; llvm::sys::path::append(IndexPath, IndexFileName); @@ -787,8 +792,8 @@ GlobalModuleIndex::writeIndex(FileManager &FileMgr, StringRef Path) { } // The module index builder. - GlobalModuleIndexBuilder Builder(FileMgr); - + GlobalModuleIndexBuilder Builder(FileMgr, PCHContainerOps); + // Load each of the module files. std::error_code EC; for (llvm::sys::fs::directory_iterator D(Path, EC), DEnd; diff --git a/clang/lib/Serialization/ModuleManager.cpp b/clang/lib/Serialization/ModuleManager.cpp index 30d9c89..03d8ed0 100644 --- a/clang/lib/Serialization/ModuleManager.cpp +++ b/clang/lib/Serialization/ModuleManager.cpp @@ -11,6 +11,7 @@ // modules for the ASTReader. // //===----------------------------------------------------------------------===// +#include "clang/Frontend/PCHContainerOperations.h" #include "clang/Lex/HeaderSearch.h" #include "clang/Lex/ModuleMap.h" #include "clang/Serialization/GlobalModuleIndex.h" @@ -136,10 +137,9 @@ ModuleManager::addModule(StringRef FileName, ModuleKind Type, New->Buffer = std::move(*Buf); } - - // Initialize the stream - New->StreamFile.init((const unsigned char *)New->Buffer->getBufferStart(), - (const unsigned char *)New->Buffer->getBufferEnd()); + + // Initialize the stream. + PCHContainerOps.ExtractPCH(New->Buffer->getMemBufferRef(), New->StreamFile); } if (ExpectedSignature) { @@ -289,8 +289,10 @@ void ModuleManager::moduleFileAccepted(ModuleFile *MF) { ModulesInCommonWithGlobalIndex.push_back(MF); } -ModuleManager::ModuleManager(FileManager &FileMgr) - : FileMgr(FileMgr), GlobalIndex(), FirstVisitState(nullptr) {} +ModuleManager::ModuleManager(FileManager &FileMgr, + const PCHContainerOperations &PCHContainerOps) + : FileMgr(FileMgr), PCHContainerOps(PCHContainerOps), GlobalIndex(), + FirstVisitState(nullptr) {} ModuleManager::~ModuleManager() { for (unsigned i = 0, e = Chain.size(); i != e; ++i) diff --git a/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp b/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp index 699549f..ee2c3f5 100644 --- a/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp +++ b/clang/lib/StaticAnalyzer/Frontend/ModelInjector.cpp @@ -76,7 +76,7 @@ void ModelInjector::onBodySynthesis(const NamedDecl *D) { // Modules are parsed by a separate CompilerInstance, so this code mimics that // behavior for models - CompilerInstance Instance; + CompilerInstance Instance(CI.getPCHContainerOperations()); Instance.setInvocation(&*Invocation); Instance.createDiagnostics( new ForwardingDiagnosticConsumer(CI.getDiagnosticClient()), diff --git a/clang/lib/Tooling/Refactoring.cpp b/clang/lib/Tooling/Refactoring.cpp index c817306..d32452f 100644 --- a/clang/lib/Tooling/Refactoring.cpp +++ b/clang/lib/Tooling/Refactoring.cpp @@ -25,9 +25,10 @@ namespace clang { namespace tooling { -RefactoringTool::RefactoringTool(const CompilationDatabase &Compilations, - ArrayRef SourcePaths) - : ClangTool(Compilations, SourcePaths) {} +RefactoringTool::RefactoringTool( + const CompilationDatabase &Compilations, ArrayRef SourcePaths, + std::shared_ptr PCHContainerOps) + : ClangTool(Compilations, SourcePaths, PCHContainerOps) {} Replacements &RefactoringTool::getReplacements() { return Replace; } diff --git a/clang/lib/Tooling/Tooling.cpp b/clang/lib/Tooling/Tooling.cpp index e100003..f9cb7c6 100644 --- a/clang/lib/Tooling/Tooling.cpp +++ b/clang/lib/Tooling/Tooling.cpp @@ -105,9 +105,10 @@ clang::CompilerInvocation *newInvocation( } bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code, - const Twine &FileName) { - return runToolOnCodeWithArgs( - ToolAction, Code, std::vector(), FileName); + const Twine &FileName, + std::shared_ptr PCHContainerOps) { + return runToolOnCodeWithArgs(ToolAction, Code, std::vector(), + FileName, PCHContainerOps); } static std::vector @@ -121,17 +122,18 @@ getSyntaxOnlyToolArgs(const std::vector &ExtraArgs, return Args; } -bool runToolOnCodeWithArgs(clang::FrontendAction *ToolAction, const Twine &Code, - const std::vector &Args, - const Twine &FileName, - const FileContentMappings &VirtualMappedFiles) { +bool runToolOnCodeWithArgs( + clang::FrontendAction *ToolAction, const Twine &Code, + const std::vector &Args, const Twine &FileName, + std::shared_ptr PCHContainerOps, + const FileContentMappings &VirtualMappedFiles) { SmallString<16> FileNameStorage; StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage); llvm::IntrusiveRefCntPtr Files( new FileManager(FileSystemOptions())); ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), - ToolAction, Files.get()); + ToolAction, Files.get(), PCHContainerOps); SmallString<1024> CodeStorage; Invocation.mapVirtualFile(FileNameRef, @@ -173,21 +175,18 @@ public: } -ToolInvocation::ToolInvocation(std::vector CommandLine, - ToolAction *Action, FileManager *Files) - : CommandLine(std::move(CommandLine)), - Action(Action), - OwnsAction(false), - Files(Files), - DiagConsumer(nullptr) {} +ToolInvocation::ToolInvocation( + std::vector CommandLine, ToolAction *Action, + FileManager *Files, std::shared_ptr PCHContainerOps) + : CommandLine(std::move(CommandLine)), Action(Action), OwnsAction(false), + Files(Files), PCHContainerOps(PCHContainerOps), DiagConsumer(nullptr) {} -ToolInvocation::ToolInvocation(std::vector CommandLine, - FrontendAction *FAction, FileManager *Files) +ToolInvocation::ToolInvocation( + std::vector CommandLine, FrontendAction *FAction, + FileManager *Files, std::shared_ptr PCHContainerOps) : CommandLine(std::move(CommandLine)), - Action(new SingleFrontendActionFactory(FAction)), - OwnsAction(true), - Files(Files), - DiagConsumer(nullptr) {} + Action(new SingleFrontendActionFactory(FAction)), OwnsAction(true), + Files(Files), PCHContainerOps(PCHContainerOps), DiagConsumer(nullptr) {} ToolInvocation::~ToolInvocation() { if (OwnsAction) @@ -232,13 +231,14 @@ bool ToolInvocation::run() { Invocation->getPreprocessorOpts().addRemappedFile(It.getKey(), Input.release()); } - return runInvocation(BinaryName, Compilation.get(), Invocation.release()); + return runInvocation(BinaryName, Compilation.get(), Invocation.release(), + PCHContainerOps); } bool ToolInvocation::runInvocation( - const char *BinaryName, - clang::driver::Compilation *Compilation, - clang::CompilerInvocation *Invocation) { + const char *BinaryName, clang::driver::Compilation *Compilation, + clang::CompilerInvocation *Invocation, + std::shared_ptr PCHContainerOps) { // Show the invocation, with -v. if (Invocation->getHeaderSearchOpts().Verbose) { llvm::errs() << "clang Invocation:\n"; @@ -246,14 +246,16 @@ bool ToolInvocation::runInvocation( llvm::errs() << "\n"; } - return Action->runInvocation(Invocation, Files, DiagConsumer); + return Action->runInvocation(Invocation, Files, PCHContainerOps, + DiagConsumer); } -bool FrontendActionFactory::runInvocation(CompilerInvocation *Invocation, - FileManager *Files, - DiagnosticConsumer *DiagConsumer) { +bool FrontendActionFactory::runInvocation( + CompilerInvocation *Invocation, FileManager *Files, + std::shared_ptr PCHContainerOps, + DiagnosticConsumer *DiagConsumer) { // Create a compiler instance to handle the actual work. - clang::CompilerInstance Compiler; + clang::CompilerInstance Compiler(PCHContainerOps); Compiler.setInvocation(Invocation); Compiler.setFileManager(Files); @@ -276,8 +278,10 @@ bool FrontendActionFactory::runInvocation(CompilerInvocation *Invocation, } ClangTool::ClangTool(const CompilationDatabase &Compilations, - ArrayRef SourcePaths) + ArrayRef SourcePaths, + std::shared_ptr PCHContainerOps) : Compilations(Compilations), SourcePaths(SourcePaths), + PCHContainerOps(PCHContainerOps), Files(new FileManager(FileSystemOptions())), DiagConsumer(nullptr) { appendArgumentsAdjuster(getClangStripOutputAdjuster()); appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster()); @@ -357,7 +361,8 @@ int ClangTool::run(ToolAction *Action) { // FIXME: We need a callback mechanism for the tool writer to output a // customized message for each file. DEBUG({ llvm::dbgs() << "Processing: " << File << ".\n"; }); - ToolInvocation Invocation(std::move(CommandLine), Action, Files.get()); + ToolInvocation Invocation(std::move(CommandLine), Action, Files.get(), + PCHContainerOps); Invocation.setDiagnosticConsumer(DiagConsumer); for (const auto &MappedFile : MappedFileContents) Invocation.mapVirtualFile(MappedFile.first, MappedFile.second); @@ -385,12 +390,14 @@ public: ASTBuilderAction(std::vector> &ASTs) : ASTs(ASTs) {} bool runInvocation(CompilerInvocation *Invocation, FileManager *Files, + std::shared_ptr PCHContainerOps, DiagnosticConsumer *DiagConsumer) override { // FIXME: This should use the provided FileManager. std::unique_ptr AST = ASTUnit::LoadFromCompilerInvocation( - Invocation, CompilerInstance::createDiagnostics( - &Invocation->getDiagnosticOpts(), DiagConsumer, - /*ShouldOwnClient=*/false)); + Invocation, PCHContainerOps, + CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts(), + DiagConsumer, + /*ShouldOwnClient=*/false)); if (!AST) return false; @@ -406,22 +413,24 @@ int ClangTool::buildASTs(std::vector> &ASTs) { return run(&Action); } -std::unique_ptr buildASTFromCode(const Twine &Code, - const Twine &FileName) { - return buildASTFromCodeWithArgs(Code, std::vector(), FileName); +std::unique_ptr +buildASTFromCode(const Twine &Code, const Twine &FileName, + std::shared_ptr PCHContainerOps) { + return buildASTFromCodeWithArgs(Code, std::vector(), FileName, + PCHContainerOps); } -std::unique_ptr -buildASTFromCodeWithArgs(const Twine &Code, - const std::vector &Args, - const Twine &FileName) { +std::unique_ptr buildASTFromCodeWithArgs( + const Twine &Code, const std::vector &Args, + const Twine &FileName, + std::shared_ptr PCHContainerOps) { SmallString<16> FileNameStorage; StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage); std::vector> ASTs; ASTBuilderAction Action(ASTs); ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), &Action, - nullptr); + nullptr, PCHContainerOps); SmallString<1024> CodeStorage; Invocation.mapVirtualFile(FileNameRef, diff --git a/clang/tools/arcmt-test/arcmt-test.cpp b/clang/tools/arcmt-test/arcmt-test.cpp index 7be4ed6..c269e01 100644 --- a/clang/tools/arcmt-test/arcmt-test.cpp +++ b/clang/tools/arcmt-test/arcmt-test.cpp @@ -7,6 +7,7 @@ // //===----------------------------------------------------------------------===// +#include "clang/Frontend/PCHContainerOperations.h" #include "clang/ARCMigrate/ARCMT.h" #include "clang/Frontend/ASTUnit.h" #include "clang/Frontend/TextDiagnosticPrinter.h" @@ -130,7 +131,8 @@ static bool checkForMigration(StringRef resourcesPath, if (!CI.getLangOpts()->ObjC1) return false; - arcmt::checkForManualIssues(CI, CI.getFrontendOpts().Inputs[0], + arcmt::checkForManualIssues(CI, CI.getFrontendOpts().Inputs[0], + std::make_shared(), Diags->getClient()); return Diags->getClient()->getNumErrors() > 0; } @@ -169,7 +171,8 @@ static bool performTransformations(StringRef resourcesPath, if (!origCI.getLangOpts()->ObjC1) return false; - MigrationProcess migration(origCI, DiagClient); + MigrationProcess migration( + origCI, std::make_shared(), DiagClient); std::vector transforms = arcmt::getAllTransformations(origCI.getLangOpts()->getGC(), diff --git a/clang/tools/driver/cc1_main.cpp b/clang/tools/driver/cc1_main.cpp index fa1a10e..972bf5b 100644 --- a/clang/tools/driver/cc1_main.cpp +++ b/clang/tools/driver/cc1_main.cpp @@ -14,6 +14,7 @@ //===----------------------------------------------------------------------===// #include "llvm/Option/Arg.h" +#include "clang/Frontend/PCHContainerOperations.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Options.h" #include "clang/Frontend/CompilerInstance.h" @@ -64,7 +65,8 @@ void initializePollyPasses(llvm::PassRegistry &Registry); #endif int cc1_main(ArrayRef Argv, const char *Argv0, void *MainAddr) { - std::unique_ptr Clang(new CompilerInstance()); + std::unique_ptr Clang( + new CompilerInstance(std::make_shared())); IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); // Initialize targets first, so that --version shows registered targets. diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index bdefa9b..2216ec6 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2889,7 +2889,8 @@ enum CXErrorCode clang_createTranslationUnit2(CXIndex CIdx, IntrusiveRefCntPtr Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions()); std::unique_ptr AU = ASTUnit::LoadFromASTFile( - ast_filename, Diags, FileSystemOpts, CXXIdx->getOnlyLocalDecls(), None, + ast_filename, CXXIdx->getPCHContainerOperations(), Diags, FileSystemOpts, + CXXIdx->getOnlyLocalDecls(), None, /*CaptureDiagnostics=*/true, /*AllowPCHWithCompilerErrors=*/true, /*UserFilesAreVolatile=*/true); @@ -3027,7 +3028,8 @@ static void clang_parseTranslationUnit_Impl(void *UserData) { unsigned NumErrors = Diags->getClient()->getNumErrors(); std::unique_ptr ErrUnit; std::unique_ptr Unit(ASTUnit::LoadFromCommandLine( - Args->data(), Args->data() + Args->size(), Diags, + Args->data(), Args->data() + Args->size(), + CXXIdx->getPCHContainerOperations(), Diags, CXXIdx->getClangResourcesPath(), CXXIdx->getOnlyLocalDecls(), /*CaptureDiagnostics=*/true, *RemappedFiles.get(), /*RemappedFilesKeepOriginalName=*/true, PrecompilePreamble, TUKind, @@ -3268,7 +3270,8 @@ static void clang_reparseTranslationUnit_Impl(void *UserData) { RemappedFiles->push_back(std::make_pair(UF.Filename, MB.release())); } - if (!CXXUnit->Reparse(*RemappedFiles.get())) + if (!CXXUnit->Reparse(CXXIdx->getPCHContainerOperations(), + *RemappedFiles.get())) RTUI->result = CXError_Success; else if (isASTReadError(CXXUnit)) RTUI->result = CXError_ASTReadError; diff --git a/clang/tools/libclang/CIndexCodeCompletion.cpp b/clang/tools/libclang/CIndexCodeCompletion.cpp index ca167e8..a7b8e29 100644 --- a/clang/tools/libclang/CIndexCodeCompletion.cpp +++ b/clang/tools/libclang/CIndexCodeCompletion.cpp @@ -715,14 +715,12 @@ static void clang_codeCompleteAt_Impl(void *UserData) { // Perform completion. AST->CodeComplete(complete_filename, complete_line, complete_column, - RemappedFiles, - (options & CXCodeComplete_IncludeMacros), + RemappedFiles, (options & CXCodeComplete_IncludeMacros), (options & CXCodeComplete_IncludeCodePatterns), - IncludeBriefComments, - Capture, - *Results->Diag, Results->LangOpts, *Results->SourceMgr, - *Results->FileMgr, Results->Diagnostics, - Results->TemporaryBuffers); + IncludeBriefComments, Capture, + CXXIdx->getPCHContainerOperations(), *Results->Diag, + Results->LangOpts, *Results->SourceMgr, *Results->FileMgr, + Results->Diagnostics, Results->TemporaryBuffers); Results->DiagnosticsWrappers.resize(Results->Diagnostics.size()); diff --git a/clang/tools/libclang/CIndexer.h b/clang/tools/libclang/CIndexer.h index cb7c62e..8a306cd 100644 --- a/clang/tools/libclang/CIndexer.h +++ b/clang/tools/libclang/CIndexer.h @@ -16,6 +16,8 @@ #define LLVM_CLANG_TOOLS_LIBCLANG_CINDEXER_H #include "clang-c/Index.h" +#include "clang/Frontend/PCHContainerOperations.h" +#include "clang/Lex/ModuleLoader.h" #include "llvm/ADT/StringRef.h" #include "llvm/Support/Path.h" #include @@ -38,11 +40,14 @@ class CIndexer { unsigned Options; // CXGlobalOptFlags. std::string ResourcesPath; + std::shared_ptr PCHContainerOps; public: - CIndexer() : OnlyLocalDecls(false), DisplayDiagnostics(false), - Options(CXGlobalOpt_None) { } - + CIndexer(std::shared_ptr PCHContainerOps = + std::make_shared()) + : OnlyLocalDecls(false), DisplayDiagnostics(false), + Options(CXGlobalOpt_None), PCHContainerOps(PCHContainerOps) {} + /// \brief Whether we only want to see "local" declarations (that did not /// come from a previous precompiled header). If false, we want to see all /// declarations. @@ -54,6 +59,10 @@ public: DisplayDiagnostics = Display; } + std::shared_ptr getPCHContainerOperations() const { + return PCHContainerOps; + } + unsigned getCXGlobalOptFlags() const { return Options; } void setCXGlobalOptFlags(unsigned options) { Options = options; } diff --git a/clang/tools/libclang/Indexing.cpp b/clang/tools/libclang/Indexing.cpp index 0ede684..e356400 100644 --- a/clang/tools/libclang/Indexing.cpp +++ b/clang/tools/libclang/Indexing.cpp @@ -590,8 +590,7 @@ static void clang_indexSourceFile_Impl(void *UserData) { if (index_options & CXIndexOpt_SuppressWarnings) CInvok->getDiagnosticOpts().IgnoreWarnings = true; - ASTUnit *Unit = ASTUnit::create(CInvok.get(), Diags, - CaptureDiagnostics, + ASTUnit *Unit = ASTUnit::create(CInvok.get(), Diags, CaptureDiagnostics, /*UserFilesAreVolatile=*/true); if (!Unit) { ITUI->result = CXError_InvalidArguments; @@ -644,17 +643,13 @@ static void clang_indexSourceFile_Impl(void *UserData) { PPOpts.DetailedRecord = false; DiagnosticErrorTrap DiagTrap(*Diags); - bool Success = ASTUnit::LoadFromCompilerInvocationAction(CInvok.get(), Diags, - IndexAction.get(), - Unit, - Persistent, - CXXIdx->getClangResourcesPath(), - OnlyLocalDecls, - CaptureDiagnostics, - PrecompilePreamble, - CacheCodeCompletionResults, - /*IncludeBriefCommentsInCodeCompletion=*/false, - /*UserFilesAreVolatile=*/true); + bool Success = ASTUnit::LoadFromCompilerInvocationAction( + CInvok.get(), CXXIdx->getPCHContainerOperations(), Diags, + IndexAction.get(), Unit, Persistent, CXXIdx->getClangResourcesPath(), + OnlyLocalDecls, CaptureDiagnostics, PrecompilePreamble, + CacheCodeCompletionResults, + /*IncludeBriefCommentsInCodeCompletion=*/false, + /*UserFilesAreVolatile=*/true); if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics()) printDiagsToStderr(Unit); diff --git a/clang/unittests/ASTMatchers/ASTMatchersTest.h b/clang/unittests/ASTMatchers/ASTMatchersTest.h index e555e63..17b69da 100644 --- a/clang/unittests/ASTMatchers/ASTMatchersTest.h +++ b/clang/unittests/ASTMatchers/ASTMatchersTest.h @@ -80,6 +80,7 @@ testing::AssertionResult matchesConditionally( Args.push_back("-frtti"); Args.push_back("-fexceptions"); if (!runToolOnCodeWithArgs(Factory->create(), Code, Args, Filename, + std::make_shared(), VirtualMappedFiles)) { return testing::AssertionFailure() << "Parsing error in \"" << Code << "\""; } -- 2.7.4