Index: cfe/trunk/bindings/python/tests/cindex/test_cdb.py =================================================================== --- cfe/trunk/bindings/python/tests/cindex/test_cdb.py +++ cfe/trunk/bindings/python/tests/cindex/test_cdb.py @@ -63,15 +63,16 @@ 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']}, ] @@ -89,7 +90,7 @@ 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) @@ -101,10 +102,11 @@ 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)): Index: cfe/trunk/include/clang/Tooling/CompilationDatabase.h =================================================================== --- cfe/trunk/include/clang/Tooling/CompilationDatabase.h +++ cfe/trunk/include/clang/Tooling/CompilationDatabase.h @@ -213,6 +213,12 @@ std::unique_ptr inferMissingCompileCommands(std::unique_ptr); +/// 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 +inferTargetAndDriverMode(std::unique_ptr Base); + } // namespace tooling } // namespace clang Index: cfe/trunk/lib/Tooling/CMakeLists.txt =================================================================== --- cfe/trunk/lib/Tooling/CMakeLists.txt +++ cfe/trunk/lib/Tooling/CMakeLists.txt @@ -17,6 +17,7 @@ Execution.cpp FileMatchTrie.cpp FixIt.cpp + GuessTargetAndModeCompilationDatabase.cpp InterpolatingCompilationDatabase.cpp JSONCompilationDatabase.cpp Refactoring.cpp Index: cfe/trunk/lib/Tooling/GuessTargetAndModeCompilationDatabase.cpp =================================================================== --- cfe/trunk/lib/Tooling/GuessTargetAndModeCompilationDatabase.cpp +++ cfe/trunk/lib/Tooling/GuessTargetAndModeCompilationDatabase.cpp @@ -0,0 +1,57 @@ +//===- 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 + +namespace clang { +namespace tooling { + +namespace { +class TargetAndModeAdderDatabase : public CompilationDatabase { +public: + TargetAndModeAdderDatabase(std::unique_ptr Base) + : Base(std::move(Base)) { + assert(this->Base != nullptr); + } + + std::vector getAllFiles() const override { + return Base->getAllFiles(); + } + + std::vector getAllCompileCommands() const override { + return addTargetAndMode(Base->getAllCompileCommands()); + } + + std::vector + getCompileCommands(StringRef FilePath) const override { + return addTargetAndMode(Base->getCompileCommands(FilePath)); + } + +private: + std::vector + addTargetAndMode(std::vector Cmds) const { + for (auto &Cmd : Cmds) { + if (Cmd.CommandLine.empty()) + continue; + addTargetAndModeForProgramName(Cmd.CommandLine, Cmd.CommandLine.front()); + } + return Cmds; + } + std::unique_ptr Base; +}; +} // namespace + +std::unique_ptr +inferTargetAndDriverMode(std::unique_ptr Base) { + return llvm::make_unique(std::move(Base)); +} + +} // namespace tooling +} // namespace clang Index: cfe/trunk/lib/Tooling/JSONCompilationDatabase.cpp =================================================================== --- cfe/trunk/lib/Tooling/JSONCompilationDatabase.cpp +++ cfe/trunk/lib/Tooling/JSONCompilationDatabase.cpp @@ -14,7 +14,9 @@ #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" @@ -165,7 +167,9 @@ 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; } }; Index: cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp =================================================================== --- cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp +++ cfe/trunk/unittests/Tooling/CompilationDatabaseTest.cpp @@ -9,10 +9,12 @@ #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" @@ -632,7 +634,7 @@ } }; -class InterpolateTest : public ::testing::Test { +class MemDBTest : public ::testing::Test { protected: // Adds an entry to the underlying compilation database. // A flag is injected: -D , so the command used can be identified. @@ -658,6 +660,11 @@ 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) { @@ -693,8 +700,6 @@ llvm::sys::path::native(Result, llvm::sys::path::Style::posix); return Result.str(); } - - MemCDB::EntryMap Entries; }; TEST_F(InterpolateTest, Nearby) { @@ -804,5 +809,30 @@ 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(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