From: Manuel Klimek Date: Mon, 7 May 2012 09:17:48 +0000 (+0000) Subject: Fixes resolution of relative paths when running clang tools. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=00f3c4f499cc27c88005176226bb424f6db4a31b;p=clang Fixes resolution of relative paths when running clang tools. The chdir is not the perfect fix, as it is thread hostile. The real fix will be to make -working-dir work correctly, which will take time to implement. Before that, the tooling library cannot be used concurrently. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@156299 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h index 25ed36b726..ff66616dfc 100644 --- a/include/clang/Tooling/Tooling.h +++ b/include/clang/Tooling/Tooling.h @@ -35,6 +35,7 @@ #include "clang/Basic/FileManager.h" #include "clang/Basic/LLVM.h" #include "clang/Driver/Util.h" +#include "clang/Tooling/CompilationDatabase.h" #include #include @@ -50,8 +51,6 @@ class FrontendAction; namespace tooling { -class CompilationDatabase; - /// \brief Interface to generate clang::FrontendActions. class FrontendActionFactory { public: @@ -169,9 +168,8 @@ class ClangTool { FileManager &getFiles() { return Files; } private: - // We store command lines as pair (file name, command line). - typedef std::pair< std::string, std::vector > CommandLine; - std::vector CommandLines; + // We store compile commands as pair (file name, compile command). + std::vector< std::pair > CompileCommands; FileManager Files; // Contains a list of pairs (, ). diff --git a/lib/Tooling/Tooling.cpp b/lib/Tooling/Tooling.cpp index 646a22af87..6ab71e2043 100644 --- a/lib/Tooling/Tooling.cpp +++ b/lib/Tooling/Tooling.cpp @@ -256,18 +256,12 @@ ClangTool::ClangTool(const CompilationDatabase &Compilations, llvm::SmallString<1024> File(getAbsolutePath( SourcePaths[I], BaseDirectory)); - std::vector CompileCommands = + std::vector CompileCommandsForFile = Compilations.getCompileCommands(File.str()); - if (!CompileCommands.empty()) { - for (int I = 0, E = CompileCommands.size(); I != E; ++I) { - CompileCommand &Command = CompileCommands[I]; - if (!Command.Directory.empty()) { - // FIXME: What should happen if CommandLine includes -working-directory - // as well? - Command.CommandLine.push_back( - "-working-directory=" + Command.Directory); - } - CommandLines.push_back(std::make_pair(File.str(), Command.CommandLine)); + if (!CompileCommandsForFile.empty()) { + for (int I = 0, E = CompileCommandsForFile.size(); I != E; ++I) { + CompileCommands.push_back(std::make_pair(File.str(), + CompileCommandsForFile[I])); } } else { // FIXME: There are two use cases here: doing a fuzzy @@ -286,9 +280,20 @@ void ClangTool::mapVirtualFile(StringRef FilePath, StringRef Content) { int ClangTool::run(FrontendActionFactory *ActionFactory) { bool ProcessingFailed = false; - for (unsigned I = 0; I < CommandLines.size(); ++I) { - std::string File = CommandLines[I].first; - std::vector &CommandLine = CommandLines[I].second; + for (unsigned I = 0; I < CompileCommands.size(); ++I) { + std::string File = CompileCommands[I].first; + // FIXME: chdir is thread hostile; on the other hand, creating the same + // behavior as chdir is complex: chdir resolves the path once, thus + // guaranteeing that all subsequent relative path operations work + // on the same path the original chdir resulted in. This makes a 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(CompileCommands[I].second.Directory.c_str())) + llvm::report_fatal_error("Cannot chdir into \"" + + CompileCommands[I].second.Directory + "\n!"); + std::vector &CommandLine = + CompileCommands[I].second.CommandLine; llvm::outs() << "Processing: " << File << ".\n"; ToolInvocation Invocation(CommandLine, ActionFactory->create(), &Files); for (int I = 0, E = MappedFileContents.size(); I != E; ++I) { diff --git a/test/Tooling/clang-check-chdir.cpp b/test/Tooling/clang-check-chdir.cpp new file mode 100644 index 0000000000..fbcd7ae3e8 --- /dev/null +++ b/test/Tooling/clang-check-chdir.cpp @@ -0,0 +1,18 @@ +// Verifies that paths are resolved relatively to the directory specified in the +// compilation database. +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: echo "[{\"directory\":\"%t\",\"command\":\"clang -c test.cpp -I.\",\"file\":\"%t/test.cpp\"}]" > %t/compile_commands.json +// RUN: cp "%s" "%t/test.cpp" +// RUN: touch "%t/clang-check-test.h" +// RUN: clang-check "%t" "%t/test.cpp" 2>&1|FileCheck %s +// FIXME: Make the above easier. + +#include "clang-check-test.h" + +// CHECK: C++ requires +invalid; + +// FIXME: JSON doesn't like path separator '\', on Win32 hosts. +// FIXME: clang-check doesn't like gcc driver on cygming. +// XFAIL: cygwin,mingw32,win32