expected = [
{ 'wd': '/home/john.doe/MyProject',
'file': '/home/john.doe/MyProject/project.cpp',
- 'line': ['clang++', '-o', 'project.o', '-c',
+ 'line': ['clang++', '--driver-mode=g++', '-o', 'project.o', '-c',
'/home/john.doe/MyProject/project.cpp']},
{ 'wd': '/home/john.doe/MyProjectA',
'file': '/home/john.doe/MyProject/project2.cpp',
- 'line': ['clang++', '-o', 'project2.o', '-c',
+ 'line': ['clang++', '--driver-mode=g++', '-o', 'project2.o', '-c',
'/home/john.doe/MyProject/project2.cpp']},
{ 'wd': '/home/john.doe/MyProjectB',
'file': '/home/john.doe/MyProject/project2.cpp',
- 'line': ['clang++', '-DFEATURE=1', '-o', 'project2-feature.o', '-c',
+ 'line': ['clang++', '--driver-mode=g++', '-DFEATURE=1', '-o',
+ 'project2-feature.o', '-c',
'/home/john.doe/MyProject/project2.cpp']},
]
self.assertEqual(len(cmds), 1)
self.assertEqual(cmds[0].directory, os.path.dirname(file))
self.assertEqual(cmds[0].filename, file)
- expected = [ 'clang++', '-o', 'project.o', '-c',
+ expected = [ 'clang++', '--driver-mode=g++', '-o', 'project.o', '-c',
'/home/john.doe/MyProject/project.cpp']
for arg, exp in zip(cmds[0].arguments, expected):
self.assertEqual(arg, exp)
self.assertEqual(len(cmds), 2)
expected = [
{ 'wd': '/home/john.doe/MyProjectA',
- 'line': ['clang++', '-o', 'project2.o', '-c',
+ 'line': ['clang++', '--driver-mode=g++', '-o', 'project2.o', '-c',
'/home/john.doe/MyProject/project2.cpp']},
{ 'wd': '/home/john.doe/MyProjectB',
- 'line': ['clang++', '-DFEATURE=1', '-o', 'project2-feature.o', '-c',
+ 'line': ['clang++', '--driver-mode=g++', '-DFEATURE=1', '-o',
+ 'project2-feature.o', '-c',
'/home/john.doe/MyProject/project2.cpp']}
]
for i in range(len(cmds)):
std::unique_ptr<CompilationDatabase>
inferMissingCompileCommands(std::unique_ptr<CompilationDatabase>);
+/// Returns a wrapped CompilationDatabase that will add -target and -mode flags
+/// to commandline when they can be deduced from argv[0] of commandline returned
+/// by underlying database.
+std::unique_ptr<CompilationDatabase>
+inferTargetAndDriverMode(std::unique_ptr<CompilationDatabase> Base);
+
} // namespace tooling
} // namespace clang
Execution.cpp
FileMatchTrie.cpp
FixIt.cpp
+ GuessTargetAndModeCompilationDatabase.cpp
InterpolatingCompilationDatabase.cpp
JSONCompilationDatabase.cpp
Refactoring.cpp
--- /dev/null
+//===- GuessTargetAndModeCompilationDatabase.cpp --------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Tooling/CompilationDatabase.h"
+#include "clang/Tooling/Tooling.h"
+#include <memory>
+
+namespace clang {
+namespace tooling {
+
+namespace {
+class TargetAndModeAdderDatabase : public CompilationDatabase {
+public:
+ TargetAndModeAdderDatabase(std::unique_ptr<CompilationDatabase> Base)
+ : Base(std::move(Base)) {
+ assert(this->Base != nullptr);
+ }
+
+ std::vector<std::string> getAllFiles() const override {
+ return Base->getAllFiles();
+ }
+
+ std::vector<CompileCommand> getAllCompileCommands() const override {
+ return addTargetAndMode(Base->getAllCompileCommands());
+ }
+
+ std::vector<CompileCommand>
+ getCompileCommands(StringRef FilePath) const override {
+ return addTargetAndMode(Base->getCompileCommands(FilePath));
+ }
+
+private:
+ std::vector<CompileCommand>
+ addTargetAndMode(std::vector<CompileCommand> Cmds) const {
+ for (auto &Cmd : Cmds) {
+ if (Cmd.CommandLine.empty())
+ continue;
+ addTargetAndModeForProgramName(Cmd.CommandLine, Cmd.CommandLine.front());
+ }
+ return Cmds;
+ }
+ std::unique_ptr<CompilationDatabase> Base;
+};
+} // namespace
+
+std::unique_ptr<CompilationDatabase>
+inferTargetAndDriverMode(std::unique_ptr<CompilationDatabase> Base) {
+ return llvm::make_unique<TargetAndModeAdderDatabase>(std::move(Base));
+}
+
+} // namespace tooling
+} // namespace clang
#include "clang/Basic/LLVM.h"
#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/CompilationDatabasePluginRegistry.h"
+#include "clang/Tooling/Tooling.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
llvm::sys::path::append(JSONDatabasePath, "compile_commands.json");
auto Base = JSONCompilationDatabase::loadFromFile(
JSONDatabasePath, ErrorMessage, JSONCommandLineSyntax::AutoDetect);
- return Base ? inferMissingCompileCommands(std::move(Base)) : nullptr;
+ return Base ? inferTargetAndDriverMode(
+ inferMissingCompileCommands(std::move(Base)))
+ : nullptr;
}
};
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclGroup.h"
#include "clang/Frontend/FrontendAction.h"
+#include "clang/Tooling/CompilationDatabase.h"
#include "clang/Tooling/FileMatchTrie.h"
#include "clang/Tooling/JSONCompilationDatabase.h"
#include "clang/Tooling/Tooling.h"
#include "llvm/Support/Path.h"
+#include "llvm/Support/TargetSelect.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
}
};
-class InterpolateTest : public ::testing::Test {
+class MemDBTest : public ::testing::Test {
protected:
// Adds an entry to the underlying compilation database.
// A flag is injected: -D <File>, so the command used can be identified.
return Result.str();
}
+ MemCDB::EntryMap Entries;
+};
+
+class InterpolateTest : public MemDBTest {
+protected:
// Look up the command from a relative path, and return it in string form.
// The input file is not included in the returned command.
std::string getCommand(llvm::StringRef F) {
llvm::sys::path::native(Result, llvm::sys::path::Style::posix);
return Result.str();
}
-
- MemCDB::EntryMap Entries;
};
TEST_F(InterpolateTest, Nearby) {
EXPECT_TRUE(CCRef != CCTest);
}
+class TargetAndModeTest : public MemDBTest {
+public:
+ TargetAndModeTest() { llvm::InitializeAllTargetInfos(); }
+
+protected:
+ // Look up the command from a relative path, and return it in string form.
+ std::string getCommand(llvm::StringRef F) {
+ auto Results = inferTargetAndDriverMode(llvm::make_unique<MemCDB>(Entries))
+ ->getCompileCommands(path(F));
+ if (Results.empty())
+ return "none";
+ return llvm::join(Results[0].CommandLine, " ");
+ }
+};
+
+TEST_F(TargetAndModeTest, TargetAndMode) {
+ add("foo.cpp", "clang-cl", "");
+ add("bar.cpp", "x86_64-linux-clang", "");
+
+ EXPECT_EQ(getCommand("foo.cpp"),
+ "clang-cl --driver-mode=cl foo.cpp -D foo.cpp");
+ EXPECT_EQ(getCommand("bar.cpp"),
+ "x86_64-linux-clang -target x86_64-linux bar.cpp -D bar.cpp");
+}
+
} // end namespace tooling
} // end namespace clang