summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp115
1 files changed, 88 insertions, 27 deletions
diff --git a/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp b/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp
index f9cb7c6..fd5596e 100644
--- a/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp
+++ b/contrib/llvm/tools/clang/lib/Tooling/Tooling.cpp
@@ -17,6 +17,7 @@
#include "clang/Driver/Compilation.h"
#include "clang/Driver/Driver.h"
#include "clang/Driver/Tool.h"
+#include "clang/Driver/ToolChain.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
@@ -31,13 +32,6 @@
#include "llvm/Support/Host.h"
#include "llvm/Support/raw_ostream.h"
-// For chdir, see the comment in ClangTool::run for more information.
-#ifdef LLVM_ON_WIN32
-# include <direct.h>
-#else
-# include <unistd.h>
-#endif
-
#define DEBUG_TYPE "clang-tooling"
namespace clang {
@@ -52,10 +46,11 @@ FrontendActionFactory::~FrontendActionFactory() {}
// it to be based on the same framework.
/// \brief Builds a clang driver initialized for running clang tools.
-static clang::driver::Driver *newDriver(clang::DiagnosticsEngine *Diagnostics,
- const char *BinaryName) {
+static clang::driver::Driver *newDriver(
+ clang::DiagnosticsEngine *Diagnostics, const char *BinaryName,
+ IntrusiveRefCntPtr<vfs::FileSystem> VFS) {
clang::driver::Driver *CompilerDriver = new clang::driver::Driver(
- BinaryName, llvm::sys::getDefaultTargetTriple(), *Diagnostics);
+ BinaryName, llvm::sys::getDefaultTargetTriple(), *Diagnostics, VFS);
CompilerDriver->setTitle("clang_based_tool");
return CompilerDriver;
}
@@ -130,18 +125,25 @@ bool runToolOnCodeWithArgs(
SmallString<16> FileNameStorage;
StringRef FileNameRef = FileName.toNullTerminatedStringRef(FileNameStorage);
+ llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
+ new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+ OverlayFileSystem->pushOverlay(InMemoryFileSystem);
llvm::IntrusiveRefCntPtr<FileManager> Files(
- new FileManager(FileSystemOptions()));
+ new FileManager(FileSystemOptions(), OverlayFileSystem));
ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef),
ToolAction, Files.get(), PCHContainerOps);
SmallString<1024> CodeStorage;
- Invocation.mapVirtualFile(FileNameRef,
- Code.toNullTerminatedStringRef(CodeStorage));
+ InMemoryFileSystem->addFile(FileNameRef, 0,
+ llvm::MemoryBuffer::getMemBuffer(
+ Code.toNullTerminatedStringRef(CodeStorage)));
for (auto &FilenameWithContent : VirtualMappedFiles) {
- Invocation.mapVirtualFile(FilenameWithContent.first,
- FilenameWithContent.second);
+ InMemoryFileSystem->addFile(
+ FilenameWithContent.first, 0,
+ llvm::MemoryBuffer::getMemBuffer(FilenameWithContent.second));
}
return Invocation.run();
@@ -162,6 +164,31 @@ std::string getAbsolutePath(StringRef File) {
return AbsolutePath.str();
}
+void addTargetAndModeForProgramName(std::vector<std::string> &CommandLine,
+ StringRef InvokedAs) {
+ if (!CommandLine.empty() && !InvokedAs.empty()) {
+ bool AlreadyHasTarget = false;
+ bool AlreadyHasMode = false;
+ // Skip CommandLine[0].
+ for (auto Token = ++CommandLine.begin(); Token != CommandLine.end();
+ ++Token) {
+ StringRef TokenRef(*Token);
+ AlreadyHasTarget |=
+ (TokenRef == "-target" || TokenRef.startswith("-target="));
+ AlreadyHasMode |= (TokenRef == "--driver-mode" ||
+ TokenRef.startswith("--driver-mode="));
+ }
+ auto TargetMode =
+ clang::driver::ToolChain::getTargetAndModeFromProgramName(InvokedAs);
+ if (!AlreadyHasMode && !TargetMode.second.empty()) {
+ CommandLine.insert(++CommandLine.begin(), TargetMode.second);
+ }
+ if (!AlreadyHasTarget && !TargetMode.first.empty()) {
+ CommandLine.insert(++CommandLine.begin(), {"-target", TargetMode.first});
+ }
+ }
+}
+
namespace {
class SingleFrontendActionFactory : public FrontendActionFactory {
@@ -212,7 +239,7 @@ bool ToolInvocation::run() {
DiagConsumer ? DiagConsumer : &DiagnosticPrinter, false);
const std::unique_ptr<clang::driver::Driver> Driver(
- newDriver(&Diagnostics, BinaryName));
+ newDriver(&Diagnostics, BinaryName, Files->getVirtualFileSystem()));
// Since the input might only be virtual, don't check whether it exists.
Driver->setCheckInputsExist(false);
const std::unique_ptr<clang::driver::Compilation> Compilation(
@@ -224,6 +251,7 @@ bool ToolInvocation::run() {
}
std::unique_ptr<clang::CompilerInvocation> Invocation(
newInvocation(&Diagnostics, *CC1Args));
+ // FIXME: remove this when all users have migrated!
for (const auto &It : MappedFileContents) {
// Inject the code as the given file name into the preprocessor options.
std::unique_ptr<llvm::MemoryBuffer> Input =
@@ -282,7 +310,11 @@ ClangTool::ClangTool(const CompilationDatabase &Compilations,
std::shared_ptr<PCHContainerOperations> PCHContainerOps)
: Compilations(Compilations), SourcePaths(SourcePaths),
PCHContainerOps(PCHContainerOps),
- Files(new FileManager(FileSystemOptions())), DiagConsumer(nullptr) {
+ OverlayFileSystem(new vfs::OverlayFileSystem(vfs::getRealFileSystem())),
+ InMemoryFileSystem(new vfs::InMemoryFileSystem),
+ Files(new FileManager(FileSystemOptions(), OverlayFileSystem)),
+ DiagConsumer(nullptr) {
+ OverlayFileSystem->pushOverlay(InMemoryFileSystem);
appendArgumentsAdjuster(getClangStripOutputAdjuster());
appendArgumentsAdjuster(getClangSyntaxOnlyAdjuster());
}
@@ -320,6 +352,16 @@ int ClangTool::run(ToolAction *Action) {
if (std::error_code EC = llvm::sys::fs::current_path(InitialDirectory))
llvm::report_fatal_error("Cannot detect current path: " +
Twine(EC.message()));
+
+ // First insert all absolute paths into the in-memory VFS. These are global
+ // for all compile commands.
+ if (SeenWorkingDirectories.insert("/").second)
+ for (const auto &MappedFile : MappedFileContents)
+ if (llvm::sys::path::is_absolute(MappedFile.first))
+ InMemoryFileSystem->addFile(
+ MappedFile.first, 0,
+ llvm::MemoryBuffer::getMemBuffer(MappedFile.second));
+
bool ProcessingFailed = false;
for (const auto &SourcePath : SourcePaths) {
std::string File(getAbsolutePath(SourcePath));
@@ -350,12 +392,24 @@ int ClangTool::run(ToolAction *Action) {
// difference for example on network filesystems, where symlinks might be
// switched during runtime of the tool. Fixing this depends on having a
// file system abstraction that allows openat() style interactions.
- if (chdir(CompileCommand.Directory.c_str()))
+ if (OverlayFileSystem->setCurrentWorkingDirectory(
+ CompileCommand.Directory))
llvm::report_fatal_error("Cannot chdir into \"" +
Twine(CompileCommand.Directory) + "\n!");
+
+ // Now fill the in-memory VFS with the relative file mappings so it will
+ // have the correct relative paths. We never remove mappings but that
+ // should be fine.
+ if (SeenWorkingDirectories.insert(CompileCommand.Directory).second)
+ for (const auto &MappedFile : MappedFileContents)
+ if (!llvm::sys::path::is_absolute(MappedFile.first))
+ InMemoryFileSystem->addFile(
+ MappedFile.first, 0,
+ llvm::MemoryBuffer::getMemBuffer(MappedFile.second));
+
std::vector<std::string> CommandLine = CompileCommand.CommandLine;
if (ArgsAdjuster)
- CommandLine = ArgsAdjuster(CommandLine);
+ CommandLine = ArgsAdjuster(CommandLine, CompileCommand.Filename);
assert(!CommandLine.empty());
CommandLine[0] = MainExecutable;
// FIXME: We need a callback mechanism for the tool writer to output a
@@ -364,8 +418,7 @@ int ClangTool::run(ToolAction *Action) {
ToolInvocation Invocation(std::move(CommandLine), Action, Files.get(),
PCHContainerOps);
Invocation.setDiagnosticConsumer(DiagConsumer);
- for (const auto &MappedFile : MappedFileContents)
- Invocation.mapVirtualFile(MappedFile.first, MappedFile.second);
+
if (!Invocation.run()) {
// FIXME: Diagnostics should be used instead.
llvm::errs() << "Error while processing " << File << ".\n";
@@ -373,7 +426,7 @@ int ClangTool::run(ToolAction *Action) {
}
// Return to the initial directory to correctly resolve next file by
// relative path.
- if (chdir(InitialDirectory.c_str()))
+ if (OverlayFileSystem->setCurrentWorkingDirectory(InitialDirectory.c_str()))
llvm::report_fatal_error("Cannot chdir into \"" +
Twine(InitialDirectory) + "\n!");
}
@@ -392,12 +445,12 @@ public:
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, PCHContainerOps,
CompilerInstance::createDiagnostics(&Invocation->getDiagnosticOpts(),
DiagConsumer,
- /*ShouldOwnClient=*/false));
+ /*ShouldOwnClient=*/false),
+ Files);
if (!AST)
return false;
@@ -429,12 +482,20 @@ std::unique_ptr<ASTUnit> buildASTFromCodeWithArgs(
std::vector<std::unique_ptr<ASTUnit>> ASTs;
ASTBuilderAction Action(ASTs);
+ llvm::IntrusiveRefCntPtr<vfs::OverlayFileSystem> OverlayFileSystem(
+ new vfs::OverlayFileSystem(vfs::getRealFileSystem()));
+ llvm::IntrusiveRefCntPtr<vfs::InMemoryFileSystem> InMemoryFileSystem(
+ new vfs::InMemoryFileSystem);
+ OverlayFileSystem->pushOverlay(InMemoryFileSystem);
+ llvm::IntrusiveRefCntPtr<FileManager> Files(
+ new FileManager(FileSystemOptions(), OverlayFileSystem));
ToolInvocation Invocation(getSyntaxOnlyToolArgs(Args, FileNameRef), &Action,
- nullptr, PCHContainerOps);
+ Files.get(), PCHContainerOps);
SmallString<1024> CodeStorage;
- Invocation.mapVirtualFile(FileNameRef,
- Code.toNullTerminatedStringRef(CodeStorage));
+ InMemoryFileSystem->addFile(FileNameRef, 0,
+ llvm::MemoryBuffer::getMemBuffer(
+ Code.toNullTerminatedStringRef(CodeStorage)));
if (!Invocation.run())
return nullptr;
OpenPOWER on IntegriCloud