de1acr0ix updated this revision to Diff 235496.
de1acr0ix added a comment.

Check if argv[0] is an option before inferring - anything starting with dash or 
slash (but without a second slash) will be treated as compiler option.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D71953/new/

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
@@ -605,6 +605,25 @@
   EXPECT_EQ(2, Argc);
 }
 
+TEST(ParseFixedCompilationDatabase, HandlesPositionalArgsSlash) {
+  // Arguments starting with slash will be stripped without explicitly setting
+  // driver mode to CL.
+  const char *Argv[] = {"1", "2", "--", "/O2", "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"), "source"));
+  EXPECT_EQ(2, Argc);
+}
+
 TEST(ParseFixedCompilationDatabase, HandlesPositionalArgsSyntaxOnly) {
   // Adjust the given command line arguments to ensure that any positional
   // arguments in them are stripped.
@@ -641,6 +660,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,24 @@
       Diagnostics));
   NewDriver->setCheckInputsExist(false);
 
+  // Try to infer driver mode and target from the original argv[0].
+  driver::ParsedClangName NameParts;
+  if (!Args.empty()) {
+    StringRef Argv0 = Args[0];
+    if (!Argv0.startswith("-") &&
+        (!Argv0.startswith("/") || Argv0.count("/") > 1)) {
+      NameParts = driver::ToolChain::getTargetAndModeFromProgramName(Argv0);
+      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