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
This commit is contained in:
Adrian Prantl
2015-06-20 18:53:08 +00:00
parent 6ed81cbcdb
commit bb165fb04d
38 changed files with 694 additions and 374 deletions

View File

@@ -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<PCHContainerOperations> 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<PCHContainerOperations> 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<PCHContainerOperations> 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<TransformFn> getAllTransformations(LangOptions::GCMode OrigGCMode,
class MigrationProcess {
CompilerInvocation OrigCI;
std::shared_ptr<PCHContainerOperations> PCHContainerOps;
DiagnosticConsumer *DiagClient;
FileRemapper Remapper;
public:
bool HadARCErrors;
MigrationProcess(const CompilerInvocation &CI, DiagnosticConsumer *diagClient,
MigrationProcess(const CompilerInvocation &CI,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *diagClient,
StringRef outputDir = StringRef());
class RewriteListener {

View File

@@ -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<llvm::MemoryBuffer> OverrideMainBuffer);
bool Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer);
struct ComputedPreamble {
llvm::MemoryBuffer *Buffer;
@@ -442,6 +444,7 @@ private:
unsigned MaxLines);
std::unique_ptr<llvm::MemoryBuffer> getMainBufferWithPrecompiledPreamble(
std::shared_ptr<PCHContainerOperations> 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<ASTUnit> LoadFromASTFile(
const std::string &Filename, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
const std::string &Filename,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
const FileSystemOptions &FileSystemOpts, bool OnlyLocalDecls = false,
ArrayRef<RemappedFile> 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<PCHContainerOperations> 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<DiagnosticsEngine> Diags,
CompilerInvocation *CI,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
IntrusiveRefCntPtr<DiagnosticsEngine> 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<ASTUnit> LoadFromCompilerInvocation(
CompilerInvocation *CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
bool OnlyLocalDecls = false, bool CaptureDiagnostics = false,
bool PrecompilePreamble = false, TranslationUnitKind TUKind = TU_Complete,
CompilerInvocation *CI,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
IntrusiveRefCntPtr<DiagnosticsEngine> 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<PCHContainerOperations> PCHContainerOps,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
bool OnlyLocalDecls = false, bool CaptureDiagnostics = false,
ArrayRef<RemappedFile> 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<RemappedFile> RemappedFiles = None);
/// contain any translation-unit information, false otherwise.
bool Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
ArrayRef<RemappedFile> 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<RemappedFile> RemappedFiles,
bool IncludeMacros, bool IncludeCodePatterns,
bool IncludeBriefComments,
ArrayRef<RemappedFile> RemappedFiles, bool IncludeMacros,
bool IncludeCodePatterns, bool IncludeBriefComments,
CodeCompleteConsumer &Consumer,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticsEngine &Diag, LangOptions &LangOpts,
SourceManager &SourceMgr, FileManager &FileMgr,
SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers);
SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers);
/// \brief Save this translation unit to a file with the given name.
///

View File

@@ -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<ModuleDependencyCollector> ModuleDepCollector;
/// \brief The module provider.
std::shared_ptr<PCHContainerOperations> ThePCHContainerOperations;
/// \brief The dependency file generator.
std::unique_ptr<DependencyFileGenerator> 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<PCHContainerOperations> PCHContainerOps =
std::make_shared<RawPCHContainerOperations>(),
bool BuildingModule = false);
~CompilerInstance() override;
/// @name High-Level Operations
@@ -492,6 +499,10 @@ public:
void setModuleDepCollector(
std::shared_ptr<ModuleDependencyCollector> Collector);
std::shared_ptr<PCHContainerOperations> getPCHContainerOperations() const {
return ThePCHContainerOperations;
}
/// }
/// @name Code Completion
/// {
@@ -605,6 +616,7 @@ public:
static IntrusiveRefCntPtr<ASTReader> 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);

View File

@@ -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 {

View File

@@ -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 <memory>
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<char, 0> 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<ASTConsumer> 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<PCHBuffer> 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<ASTConsumer> 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<PCHBuffer> Buffer) const override;
/// \brief Initialize an llvm::BitstreamReader with Buffer.
void ExtractPCH(llvm::MemoryBufferRef Buffer,
llvm::BitstreamReader &StreamFile) const override;
};
}
#endif

View File

@@ -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.

View File

@@ -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,

View File

@@ -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<char, 128> Buffer;
std::shared_ptr<PCHBuffer> Buffer;
llvm::BitstreamWriter Stream;
ASTWriter Writer;
bool AllowASTWithErrors;
bool HasEmittedPCH;
protected:
ASTWriter &getWriter() { return Writer; }
const ASTWriter &getWriter() const { return Writer; }
SmallVectorImpl<char> &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<PCHBuffer> 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

View File

@@ -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);
};
}

View File

@@ -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<const FileEntry *, std::unique_ptr<llvm::MemoryBuffer>>
InMemoryBuffers;
@@ -112,8 +116,9 @@ public:
typedef SmallVectorImpl<ModuleFile*>::const_iterator ModuleConstIterator;
typedef SmallVectorImpl<ModuleFile*>::reverse_iterator ModuleReverseIterator;
typedef std::pair<uint32_t, StringRef> ModuleOffset;
explicit ModuleManager(FileManager &FileMgr);
explicit ModuleManager(FileManager &FileMgr,
const PCHContainerOperations &PCHContainerOps);
~ModuleManager();
/// \brief Forward iterator to traverse all loaded modules. This is reverse

View File

@@ -38,7 +38,9 @@ class RefactoringTool : public ClangTool {
public:
/// \see ClangTool::ClangTool.
RefactoringTool(const CompilationDatabase &Compilations,
ArrayRef<std::string> SourcePaths);
ArrayRef<std::string> SourcePaths,
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<RawPCHContainerOperations>());
/// \brief Returns the set of replacements to which replacements should
/// be added during the run of the tool.

View File

@@ -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<PCHContainerOperations> 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<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *DiagConsumer) override;
/// \brief Returns a new clang::FrontendAction.
@@ -139,10 +143,14 @@ inline std::unique_ptr<FrontendActionFactory> 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<PCHContainerOperations> PCHContainerOps =
std::make_shared<RawPCHContainerOperations>());
/// The first part of the pair is the filename, the second part the
/// file-content.
@@ -155,37 +163,48 @@ typedef std::vector<std::pair<std::string, std::string>> 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<std::string> &Args, const Twine &FileName = "input.cc",
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<RawPCHContainerOperations>(),
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<ASTUnit> buildASTFromCode(const Twine &Code,
const Twine &FileName = "input.cc");
std::unique_ptr<ASTUnit>
buildASTFromCode(const Twine &Code, const Twine &FileName = "input.cc",
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<RawPCHContainerOperations>());
/// \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<ASTUnit>
buildASTFromCodeWithArgs(const Twine &Code,
const std::vector<std::string> &Args,
const Twine &FileName = "input.cc");
std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
const Twine &Code, const std::vector<std::string> &Args,
const Twine &FileName = "input.cc",
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<RawPCHContainerOperations>());
/// \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<std::string> CommandLine, FrontendAction *FAction,
FileManager *Files);
FileManager *Files,
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<RawPCHContainerOperations>());
/// \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<std::string> CommandLine, ToolAction *Action,
FileManager *Files);
FileManager *Files,
std::shared_ptr<PCHContainerOperations> 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<PCHContainerOperations> PCHContainerOps);
std::vector<std::string> CommandLine;
ToolAction *Action;
bool OwnsAction;
FileManager *Files;
std::shared_ptr<PCHContainerOperations> PCHContainerOps;
// Maps <file name> -> <file content>.
llvm::StringMap<StringRef> 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<std::string> SourcePaths);
ArrayRef<std::string> SourcePaths,
std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<RawPCHContainerOperations>());
~ClangTool();
@@ -297,6 +329,7 @@ class ClangTool {
private:
const CompilationDatabase &Compilations;
std::vector<std::string> SourcePaths;
std::shared_ptr<PCHContainerOperations> PCHContainerOps;
llvm::IntrusiveRefCntPtr<FileManager> Files;
// Contains a list of pairs (<file name>, <file content>).

View File

@@ -166,7 +166,8 @@ static bool HasARCRuntime(CompilerInvocation &origCI) {
}
static CompilerInvocation *
createInvocationForMigration(CompilerInvocation &origCI) {
createInvocationForMigration(CompilerInvocation &origCI,
const PCHContainerOperations &PCHContainerOps) {
std::unique_ptr<CompilerInvocation> CInvok;
CInvok.reset(new CompilerInvocation(origCI));
PreprocessorOptions &PPOpts = CInvok->getPreprocessorOpts();
@@ -178,9 +179,8 @@ createInvocationForMigration(CompilerInvocation &origCI) {
IntrusiveRefCntPtr<DiagnosticsEngine> 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<PCHContainerOperations> 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<CompilerInvocation> 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<ASTUnit> Unit(
ASTUnit::LoadFromCompilerInvocationAction(CInvok.release(), Diags));
std::unique_ptr<ASTUnit> 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<PCHContainerOperations> 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<TransformFn> 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<PCHContainerOperations> 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<PCHContainerOperations> 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<std::pair<std::string,std::string> > &
@@ -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<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *diagClient, StringRef outputDir)
: OrigCI(CI), PCHContainerOps(PCHContainerOps), DiagClient(diagClient),
HadARCErrors(false) {
if (!outputDir.empty()) {
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
@@ -515,7 +517,7 @@ MigrationProcess::MigrationProcess(const CompilerInvocation &CI,
bool MigrationProcess::applyTransform(TransformFn trans,
RewriteListener *listener) {
std::unique_ptr<CompilerInvocation> 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<ASTUnit> Unit(ASTUnit::LoadFromCompilerInvocationAction(
CInvok.release(), Diags, ASTAction.get()));
CInvok.release(), PCHContainerOps, Diags, ASTAction.get()));
if (!Unit) {
errRec.FinishCapture();
return true;

View File

@@ -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.

View File

@@ -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;

View File

@@ -45,8 +45,10 @@ void ASTMergeAction::ExecuteAction() {
new ForwardingDiagnosticConsumer(
*CI.getDiagnostics().getClient()),
/*ShouldOwnClient=*/true));
std::unique_ptr<ASTUnit> Unit = ASTUnit::LoadFromASTFile(
ASTFiles[I], Diags, CI.getFileSystemOpts(), false);
std::unique_ptr<ASTUnit> Unit =
ASTUnit::LoadFromASTFile(ASTFiles[I], CI.getPCHContainerOperations(),
Diags, CI.getFileSystemOpts(), false);
if (!Unit)
continue;

View File

@@ -648,7 +648,9 @@ void ASTUnit::ConfigureDiags(IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
}
std::unique_ptr<ASTUnit> ASTUnit::LoadFromASTFile(
const std::string &Filename, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
const std::string &Filename,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
const FileSystemOptions &FileSystemOpts, bool OnlyLocalDecls,
ArrayRef<RemappedFile> RemappedFiles, bool CaptureDiagnostics,
bool AllowPCHWithCompilerErrors, bool UserFilesAreVolatile) {
@@ -705,10 +707,10 @@ std::unique_ptr<ASTUnit> 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<ASTInfoCollector>(
*AST->PP, Context, AST->ASTFileLangOpts, AST->TargetOpts, AST->Target,
@@ -916,13 +918,16 @@ class PrecompilePreambleConsumer : public PCHGenerator {
unsigned &Hash;
std::vector<Decl *> 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<PCHBuffer>(),
/*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<char, 0> 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<StoredDiagnostic> &
///
/// \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<llvm::MemoryBuffer> OverrideMainBuffer) {
bool ASTUnit::Parse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
std::unique_ptr<llvm::MemoryBuffer> OverrideMainBuffer) {
SavedMainFileBuffer.reset();
if (!Invocation)
return true;
// Create the compiler instance to use for building the AST.
std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
std::unique_ptr<CompilerInstance> Clang(
new CompilerInstance(PCHContainerOps));
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
@@ -1323,6 +1338,7 @@ makeStandaloneDiagnostic(const LangOptions &LangOpts,
/// Otherwise, returns a NULL pointer.
std::unique_ptr<llvm::MemoryBuffer>
ASTUnit::getMainBufferWithPrecompiledPreamble(
std::shared_ptr<PCHContainerOperations> 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<CompilerInstance> Clang(new CompilerInstance());
std::unique_ptr<CompilerInstance> Clang(
new CompilerInstance(PCHContainerOps));
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
@@ -1702,12 +1719,13 @@ ASTUnit *ASTUnit::create(CompilerInvocation *CI,
}
ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
CompilerInvocation *CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
ASTFrontendAction *Action, ASTUnit *Unit, bool Persistent,
StringRef ResourceFilesPath, bool OnlyLocalDecls, bool CaptureDiagnostics,
bool PrecompilePreamble, bool CacheCodeCompletionResults,
bool IncludeBriefCommentsInCodeCompletion, bool UserFilesAreVolatile,
std::unique_ptr<ASTUnit> *ErrAST) {
CompilerInvocation *CI,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags, ASTFrontendAction *Action,
ASTUnit *Unit, bool Persistent, StringRef ResourceFilesPath,
bool OnlyLocalDecls, bool CaptureDiagnostics, bool PrecompilePreamble,
bool CacheCodeCompletionResults, bool IncludeBriefCommentsInCodeCompletion,
bool UserFilesAreVolatile, std::unique_ptr<ASTUnit> *ErrAST) {
assert(CI && "A CompilerInvocation is required");
std::unique_ptr<ASTUnit> 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<CompilerInstance> Clang(new CompilerInstance());
std::unique_ptr<CompilerInstance> Clang(
new CompilerInstance(PCHContainerOps));
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
@@ -1841,7 +1860,9 @@ ASTUnit *ASTUnit::LoadFromCompilerInvocationAction(
return AST;
}
bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) {
bool ASTUnit::LoadFromCompilerInvocation(
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
bool PrecompilePreamble) {
if (!Invocation)
return true;
@@ -1853,7 +1874,8 @@ bool ASTUnit::LoadFromCompilerInvocation(bool PrecompilePreamble) {
std::unique_ptr<llvm::MemoryBuffer> 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<llvm::MemoryBuffer>
MemBufferCleanup(OverrideMainBuffer.get());
return Parse(std::move(OverrideMainBuffer));
return Parse(PCHContainerOps, std::move(OverrideMainBuffer));
}
std::unique_ptr<ASTUnit> ASTUnit::LoadFromCompilerInvocation(
CompilerInvocation *CI, IntrusiveRefCntPtr<DiagnosticsEngine> Diags,
bool OnlyLocalDecls, bool CaptureDiagnostics, bool PrecompilePreamble,
CompilerInvocation *CI,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
IntrusiveRefCntPtr<DiagnosticsEngine> 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> ASTUnit::LoadFromCompilerInvocation(
llvm::CrashRecoveryContextReleaseRefCleanup<DiagnosticsEngine> >
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<PCHContainerOperations> PCHContainerOps,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags, StringRef ResourceFilesPath,
bool OnlyLocalDecls, bool CaptureDiagnostics,
ArrayRef<RemappedFile> RemappedFiles, bool RemappedFilesKeepOriginalName,
@@ -1975,7 +2000,7 @@ ASTUnit *ASTUnit::LoadFromCommandLine(
llvm::CrashRecoveryContextCleanupRegistrar<ASTUnit>
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<RemappedFile> RemappedFiles) {
bool ASTUnit::Reparse(std::shared_ptr<PCHContainerOperations> PCHContainerOps,
ArrayRef<RemappedFile> RemappedFiles) {
if (!Invocation)
return true;
@@ -2012,8 +2038,9 @@ bool ASTUnit::Reparse(ArrayRef<RemappedFile> RemappedFiles) {
// build a precompiled preamble, do so now.
std::unique_ptr<llvm::MemoryBuffer> 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<RemappedFile> 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<RemappedFile> RemappedFiles,
bool IncludeMacros,
bool IncludeCodePatterns,
bool IncludeBriefComments,
CodeCompleteConsumer &Consumer,
DiagnosticsEngine &Diag, LangOptions &LangOpts,
SourceManager &SourceMgr, FileManager &FileMgr,
SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
SmallVectorImpl<const llvm::MemoryBuffer *> &OwnedBuffers) {
void ASTUnit::CodeComplete(
StringRef File, unsigned Line, unsigned Column,
ArrayRef<RemappedFile> RemappedFiles, bool IncludeMacros,
bool IncludeCodePatterns, bool IncludeBriefComments,
CodeCompleteConsumer &Consumer,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticsEngine &Diag, LangOptions &LangOpts, SourceManager &SourceMgr,
FileManager &FileMgr, SmallVectorImpl<StoredDiagnostic> &StoredDiagnostics,
SmallVectorImpl<const llvm::MemoryBuffer *> &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<CompilerInstance> Clang(new CompilerInstance());
std::unique_ptr<CompilerInstance> Clang(
new CompilerInstance(PCHContainerOps));
// Recover resources if we crash before exiting this method.
llvm::CrashRecoveryContextCleanupRegistrar<CompilerInstance>
@@ -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);
}
}
}

View File

@@ -31,6 +31,7 @@ add_clang_library(clangFrontend
LogDiagnosticPrinter.cpp
ModuleDependencyCollector.cpp
MultiplexConsumer.cpp
PCHContainerOperations.cpp
PrintPreprocessedOutput.cpp
SerializedDiagnosticPrinter.cpp
SerializedDiagnosticReader.cpp

View File

@@ -80,8 +80,9 @@ createASTReader(CompilerInstance &CI, StringRef pchFile,
ASTDeserializationListener *deserialListener = nullptr) {
Preprocessor &PP = CI.getPreprocessor();
std::unique_ptr<ASTReader> 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<ExternalSemaSource> clang::createChainedIncludesSource(
IntrusiveRefCntPtr<DiagnosticsEngine> Diags(
new DiagnosticsEngine(DiagID, &CI.getDiagnosticOpts(), DiagClient));
std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
std::unique_ptr<CompilerInstance> Clang(
new CompilerInstance(CI.getPCHContainerOperations()));
Clang->setInvocation(CInvok.release());
Clang->setDiagnostics(Diags.get());
Clang->setTarget(TargetInfo::CreateTargetInfo(
@@ -157,11 +159,9 @@ IntrusiveRefCntPtr<ExternalSemaSource> clang::createChainedIncludesSource(
&Clang->getPreprocessor());
Clang->createASTContext();
SmallVector<char, 256> serialAST;
llvm::raw_svector_ostream OS(serialAST);
auto consumer =
llvm::make_unique<PCHGenerator>(Clang->getPreprocessor(), "-", nullptr,
/*isysroot=*/"", &OS);
auto Buffer = std::make_shared<PCHBuffer>();
auto consumer = llvm::make_unique<PCHGenerator>(
Clang->getPreprocessor(), "-", nullptr, /*isysroot=*/"", Buffer);
Clang->getASTContext().setASTMutationListener(
consumer->GetASTMutationListener());
Clang->setASTConsumer(std::move(consumer));
@@ -198,7 +198,11 @@ IntrusiveRefCntPtr<ExternalSemaSource> 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());
}

View File

@@ -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<PCHContainerOperations> 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<ASTReader> 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<ASTReader> Reader(
new ASTReader(PP, Context, Sysroot.empty() ? "" : Sysroot.c_str(),
DisablePCHValidation, AllowPCHWithCompilerErrors,
/*AllowConfigurationMismatch*/ false,
HSOpts.ModulesValidateSystemHeaders, UseGlobalModuleIndex));
IntrusiveRefCntPtr<ASTReader> 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();

View File

@@ -191,7 +191,8 @@ bool FrontendAction::BeginSourceFile(CompilerInstance &CI,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags(&CI.getDiagnostics());
std::unique_ptr<ASTUnit> 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;

View File

@@ -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<ASTConsumer>
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<PCHGenerator>(CI.getPreprocessor(), OutputFile,
nullptr, Sysroot, OS);
auto Buffer = std::make_shared<PCHBuffer>();
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
Consumers.push_back(llvm::make_unique<PCHGenerator>(
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<MultiplexConsumer>(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<PCHGenerator>(CI.getPreprocessor(), OutputFile,
Module, Sysroot, OS);
auto Buffer = std::make_shared<PCHBuffer>();
std::vector<std::unique_ptr<ASTConsumer>> Consumers;
Consumers.push_back(llvm::make_unique<PCHGenerator>(
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<MultiplexConsumer>(std::move(Consumers));
}
static SmallVectorImpl<char> &
@@ -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<ASTReader> Reader(
new ASTReader(CI.getPreprocessor(), CI.getASTContext(),
Sysroot.empty() ? "" : Sysroot.c_str(),
/*DisableValidation*/ false,
/*AllowPCHWithCompilerErrors*/ false,
/*AllowConfigurationMismatch*/ true,
/*ValidateSystemInputs*/ true));
std::unique_ptr<ASTReader> 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);
}
//===----------------------------------------------------------------------===//

View File

@@ -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);

View File

@@ -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<PCHBuffer> 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<PCHBuffer> 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<char, 0> Empty;
Buffer->Data = std::move(Empty);
}
};
}
std::unique_ptr<ASTConsumer>
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<PCHBuffer> Buffer) const {
return llvm::make_unique<PCHContainerGenerator>(
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());
}

View File

@@ -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),

View File

@@ -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<PCHBuffer> 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() {

View File

@@ -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<const FileEntry *, ModuleFileInfo> 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;

View File

@@ -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)

View File

@@ -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()),

View File

@@ -25,9 +25,10 @@
namespace clang {
namespace tooling {
RefactoringTool::RefactoringTool(const CompilationDatabase &Compilations,
ArrayRef<std::string> SourcePaths)
: ClangTool(Compilations, SourcePaths) {}
RefactoringTool::RefactoringTool(
const CompilationDatabase &Compilations, ArrayRef<std::string> SourcePaths,
std::shared_ptr<PCHContainerOperations> PCHContainerOps)
: ClangTool(Compilations, SourcePaths, PCHContainerOps) {}
Replacements &RefactoringTool::getReplacements() { return Replace; }

View File

@@ -105,9 +105,10 @@ clang::CompilerInvocation *newInvocation(
}
bool runToolOnCode(clang::FrontendAction *ToolAction, const Twine &Code,
const Twine &FileName) {
return runToolOnCodeWithArgs(
ToolAction, Code, std::vector<std::string>(), FileName);
const Twine &FileName,
std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
return runToolOnCodeWithArgs(ToolAction, Code, std::vector<std::string>(),
FileName, PCHContainerOps);
}
static std::vector<std::string>
@@ -121,17 +122,18 @@ getSyntaxOnlyToolArgs(const std::vector<std::string> &ExtraArgs,
return Args;
}
bool runToolOnCodeWithArgs(clang::FrontendAction *ToolAction, const Twine &Code,
const std::vector<std::string> &Args,
const Twine &FileName,
const FileContentMappings &VirtualMappedFiles) {
bool runToolOnCodeWithArgs(
clang::FrontendAction *ToolAction, const Twine &Code,
const std::vector<std::string> &Args, const Twine &FileName,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
const FileContentMappings &VirtualMappedFiles) {
SmallString<16> FileNameStorage;
StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
llvm::IntrusiveRefCntPtr<FileManager> 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<std::string> CommandLine,
ToolAction *Action, FileManager *Files)
: CommandLine(std::move(CommandLine)),
Action(Action),
OwnsAction(false),
Files(Files),
DiagConsumer(nullptr) {}
ToolInvocation::ToolInvocation(
std::vector<std::string> CommandLine, ToolAction *Action,
FileManager *Files, std::shared_ptr<PCHContainerOperations> PCHContainerOps)
: CommandLine(std::move(CommandLine)), Action(Action), OwnsAction(false),
Files(Files), PCHContainerOps(PCHContainerOps), DiagConsumer(nullptr) {}
ToolInvocation::ToolInvocation(std::vector<std::string> CommandLine,
FrontendAction *FAction, FileManager *Files)
ToolInvocation::ToolInvocation(
std::vector<std::string> CommandLine, FrontendAction *FAction,
FileManager *Files, std::shared_ptr<PCHContainerOperations> 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<PCHContainerOperations> 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<PCHContainerOperations> 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<std::string> SourcePaths)
ArrayRef<std::string> SourcePaths,
std::shared_ptr<PCHContainerOperations> 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<std::unique_ptr<ASTUnit>> &ASTs) : ASTs(ASTs) {}
bool runInvocation(CompilerInvocation *Invocation, FileManager *Files,
std::shared_ptr<PCHContainerOperations> PCHContainerOps,
DiagnosticConsumer *DiagConsumer) override {
// FIXME: This should use the provided FileManager.
std::unique_ptr<ASTUnit> 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<std::unique_ptr<ASTUnit>> &ASTs) {
return run(&Action);
}
std::unique_ptr<ASTUnit> buildASTFromCode(const Twine &Code,
const Twine &FileName) {
return buildASTFromCodeWithArgs(Code, std::vector<std::string>(), FileName);
std::unique_ptr<ASTUnit>
buildASTFromCode(const Twine &Code, const Twine &FileName,
std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
return buildASTFromCodeWithArgs(Code, std::vector<std::string>(), FileName,
PCHContainerOps);
}
std::unique_ptr<ASTUnit>
buildASTFromCodeWithArgs(const Twine &Code,
const std::vector<std::string> &Args,
const Twine &FileName) {
std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
const Twine &Code, const std::vector<std::string> &Args,
const Twine &FileName,
std::shared_ptr<PCHContainerOperations> PCHContainerOps) {
SmallString<16> FileNameStorage;
StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
std::vector<std::unique_ptr<ASTUnit>> ASTs;
ASTBuilderAction Action(ASTs);
ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), &Action,
nullptr);
nullptr, PCHContainerOps);
SmallString<1024> CodeStorage;
Invocation.mapVirtualFile(FileNameRef,

View File

@@ -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<RawPCHContainerOperations>(),
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<RawPCHContainerOperations>(), DiagClient);
std::vector<TransformFn>
transforms = arcmt::getAllTransformations(origCI.getLangOpts()->getGC(),

View File

@@ -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<const char *> Argv, const char *Argv0, void *MainAddr) {
std::unique_ptr<CompilerInstance> Clang(new CompilerInstance());
std::unique_ptr<CompilerInstance> Clang(
new CompilerInstance(std::make_shared<RawPCHContainerOperations>()));
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
// Initialize targets first, so that --version shows registered targets.

View File

@@ -2889,7 +2889,8 @@ enum CXErrorCode clang_createTranslationUnit2(CXIndex CIdx,
IntrusiveRefCntPtr<DiagnosticsEngine> Diags =
CompilerInstance::createDiagnostics(new DiagnosticOptions());
std::unique_ptr<ASTUnit> 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<ASTUnit> ErrUnit;
std::unique_ptr<ASTUnit> 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;

View File

@@ -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());

View File

@@ -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 <vector>
@@ -38,11 +40,14 @@ class CIndexer {
unsigned Options; // CXGlobalOptFlags.
std::string ResourcesPath;
std::shared_ptr<PCHContainerOperations> PCHContainerOps;
public:
CIndexer() : OnlyLocalDecls(false), DisplayDiagnostics(false),
Options(CXGlobalOpt_None) { }
CIndexer(std::shared_ptr<PCHContainerOperations> PCHContainerOps =
std::make_shared<RawPCHContainerOperations>())
: 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<PCHContainerOperations> getPCHContainerOperations() const {
return PCHContainerOps;
}
unsigned getCXGlobalOptFlags() const { return Options; }
void setCXGlobalOptFlags(unsigned options) { Options = options; }

View File

@@ -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);

View File

@@ -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<RawPCHContainerOperations>(),
VirtualMappedFiles)) {
return testing::AssertionFailure() << "Parsing error in \"" << Code << "\"";
}