de1acr0ix created this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

When creating FixedCompilationDatabase from command line, compiler
command is often provided. This commit tries to infer driver mode and
target from that so that clang tools does not need to specify them
explicitly.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D71953

Files:
  clang/lib/Tooling/CompilationDatabase.cpp
  clang/unittests/Tooling/CompilationDatabaseTest.cpp


Index: clang/unittests/Tooling/CompilationDatabaseTest.cpp
===================================================================
--- clang/unittests/Tooling/CompilationDatabaseTest.cpp
+++ clang/unittests/Tooling/CompilationDatabaseTest.cpp
@@ -641,6 +641,43 @@
   EXPECT_EQ(2, Argc);
 }
 
+TEST(ParseFixedCompilationDatabase, InferDriverMode) {
+  const char *Argv[] = {"1", "2", "--", "cl.exe", "-nologo", "somefile.cpp"};
+  int Argc = sizeof(Argv) / sizeof(char *);
+  std::string ErrorMsg;
+  std::unique_ptr<FixedCompilationDatabase> Database =
+      FixedCompilationDatabase::loadFromCommandLine(Argc, Argv, ErrorMsg);
+  ASSERT_TRUE((bool)Database);
+  ASSERT_TRUE(ErrorMsg.empty());
+  std::vector<CompileCommand> Result = Database->getCompileCommands("source");
+  ASSERT_EQ(1ul, Result.size());
+  ASSERT_EQ(".", Result[0].Directory);
+  std::vector<std::string> Expected;
+  ASSERT_THAT(Result[0].CommandLine,
+              ElementsAre(EndsWith("clang-tool"), "--driver-mode=cl", 
"-nologo",
+                          "source"));
+  EXPECT_EQ(2, Argc);
+}
+
+TEST(ParseFixedCompilationDatabase, InferTarget) {
+  const char *Argv[] = {"1", "2", "--", "x86_64-linux-gnu-gcc", 
"somefile.cpp"};
+  int Argc = sizeof(Argv) / sizeof(char *);
+  std::string ErrorMsg;
+  LLVMInitializeX86TargetInfo();
+  std::unique_ptr<FixedCompilationDatabase> Database =
+      FixedCompilationDatabase::loadFromCommandLine(Argc, Argv, ErrorMsg);
+  ASSERT_TRUE((bool)Database);
+  ASSERT_TRUE(ErrorMsg.empty());
+  std::vector<CompileCommand> Result = Database->getCompileCommands("source");
+  ASSERT_EQ(1ul, Result.size());
+  ASSERT_EQ(".", Result[0].Directory);
+  std::vector<std::string> Expected;
+  ASSERT_THAT(Result[0].CommandLine,
+              ElementsAre(EndsWith("clang-tool"), "-target", 
"x86_64-linux-gnu",
+                          "source"));
+  EXPECT_EQ(2, Argc);
+}
+
 struct MemCDB : public CompilationDatabase {
   using EntryMap = llvm::StringMap<SmallVector<CompileCommand, 1>>;
   EntryMap Entries;
Index: clang/lib/Tooling/CompilationDatabase.cpp
===================================================================
--- clang/lib/Tooling/CompilationDatabase.cpp
+++ clang/lib/Tooling/CompilationDatabase.cpp
@@ -275,6 +275,20 @@
       Diagnostics));
   NewDriver->setCheckInputsExist(false);
 
+  // Try to infer driver mode and target from the original argv[0].
+  driver::ParsedClangName NameParts;
+  if (!Args.empty()) {
+    NameParts = driver::ToolChain::getTargetAndModeFromProgramName(Args[0]);
+    if (NameParts.DriverMode) {
+      Args.insert(Args.begin(), NameParts.DriverMode);
+    }
+
+    if (NameParts.TargetIsValid) {
+      const char *arr[] = {"-target", NameParts.TargetPrefix.c_str()};
+      Args.insert(Args.begin(), std::begin(arr), std::end(arr));
+    }
+  }
+
   // This becomes the new argv[0]. The value is used to detect libc++ include
   // dirs on Mac, it isn't used for other platforms.
   std::string Argv0 = GetClangToolCommand();


Index: clang/unittests/Tooling/CompilationDatabaseTest.cpp
===================================================================
--- clang/unittests/Tooling/CompilationDatabaseTest.cpp
+++ clang/unittests/Tooling/CompilationDatabaseTest.cpp
@@ -641,6 +641,43 @@
   EXPECT_EQ(2, Argc);
 }
 
+TEST(ParseFixedCompilationDatabase, InferDriverMode) {
+  const char *Argv[] = {"1", "2", "--", "cl.exe", "-nologo", "somefile.cpp"};
+  int Argc = sizeof(Argv) / sizeof(char *);
+  std::string ErrorMsg;
+  std::unique_ptr<FixedCompilationDatabase> Database =
+      FixedCompilationDatabase::loadFromCommandLine(Argc, Argv, ErrorMsg);
+  ASSERT_TRUE((bool)Database);
+  ASSERT_TRUE(ErrorMsg.empty());
+  std::vector<CompileCommand> Result = Database->getCompileCommands("source");
+  ASSERT_EQ(1ul, Result.size());
+  ASSERT_EQ(".", Result[0].Directory);
+  std::vector<std::string> Expected;
+  ASSERT_THAT(Result[0].CommandLine,
+              ElementsAre(EndsWith("clang-tool"), "--driver-mode=cl", "-nologo",
+                          "source"));
+  EXPECT_EQ(2, Argc);
+}
+
+TEST(ParseFixedCompilationDatabase, InferTarget) {
+  const char *Argv[] = {"1", "2", "--", "x86_64-linux-gnu-gcc", "somefile.cpp"};
+  int Argc = sizeof(Argv) / sizeof(char *);
+  std::string ErrorMsg;
+  LLVMInitializeX86TargetInfo();
+  std::unique_ptr<FixedCompilationDatabase> Database =
+      FixedCompilationDatabase::loadFromCommandLine(Argc, Argv, ErrorMsg);
+  ASSERT_TRUE((bool)Database);
+  ASSERT_TRUE(ErrorMsg.empty());
+  std::vector<CompileCommand> Result = Database->getCompileCommands("source");
+  ASSERT_EQ(1ul, Result.size());
+  ASSERT_EQ(".", Result[0].Directory);
+  std::vector<std::string> Expected;
+  ASSERT_THAT(Result[0].CommandLine,
+              ElementsAre(EndsWith("clang-tool"), "-target", "x86_64-linux-gnu",
+                          "source"));
+  EXPECT_EQ(2, Argc);
+}
+
 struct MemCDB : public CompilationDatabase {
   using EntryMap = llvm::StringMap<SmallVector<CompileCommand, 1>>;
   EntryMap Entries;
Index: clang/lib/Tooling/CompilationDatabase.cpp
===================================================================
--- clang/lib/Tooling/CompilationDatabase.cpp
+++ clang/lib/Tooling/CompilationDatabase.cpp
@@ -275,6 +275,20 @@
       Diagnostics));
   NewDriver->setCheckInputsExist(false);
 
+  // Try to infer driver mode and target from the original argv[0].
+  driver::ParsedClangName NameParts;
+  if (!Args.empty()) {
+    NameParts = driver::ToolChain::getTargetAndModeFromProgramName(Args[0]);
+    if (NameParts.DriverMode) {
+      Args.insert(Args.begin(), NameParts.DriverMode);
+    }
+
+    if (NameParts.TargetIsValid) {
+      const char *arr[] = {"-target", NameParts.TargetPrefix.c_str()};
+      Args.insert(Args.begin(), std::begin(arr), std::end(arr));
+    }
+  }
+
   // This becomes the new argv[0]. The value is used to detect libc++ include
   // dirs on Mac, it isn't used for other platforms.
   std::string Argv0 = GetClangToolCommand();
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to