aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorManuel Klimek <klimek@google.com>2012-05-07 09:17:48 +0000
committerManuel Klimek <klimek@google.com>2012-05-07 09:17:48 +0000
commit00f3c4f499cc27c88005176226bb424f6db4a31b (patch)
treef4c0ea23832cd90a58a2897d14e3a1b1eec58e8b
parent0265555a0fec81102bfb3757cfc7f3d90dbbe409 (diff)
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
-rw-r--r--include/clang/Tooling/Tooling.h8
-rw-r--r--lib/Tooling/Tooling.cpp33
-rw-r--r--test/Tooling/clang-check-chdir.cpp18
3 files changed, 40 insertions, 19 deletions
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 <string>
#include <vector>
@@ -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<std::string> > CommandLine;
- std::vector<CommandLine> CommandLines;
+ // We store compile commands as pair (file name, compile command).
+ std::vector< std::pair<std::string, CompileCommand> > CompileCommands;
FileManager Files;
// Contains a list of pairs (<file name>, <file content>).
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<CompileCommand> CompileCommands =
+ std::vector<CompileCommand> 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<std::string> &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<std::string> &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