Hi dblaikie, majnemer,

Clang would previously not get into C++ mode when invoked as 'clang++3.6' 
(though clang++-3.6 would work).

I found the previous loop logic in this function confusing; hopefully this 
makes it clearer.

http://reviews.llvm.org/D5833

Files:
  test/Driver/parse-progname.c
  tools/driver/driver.cpp
Index: test/Driver/parse-progname.c
===================================================================
--- /dev/null
+++ test/Driver/parse-progname.c
@@ -0,0 +1,56 @@
+// REQUIRES: shell, arm-registered-target
+
+
+
+// RUN: ln -fs %clang %T/clang++
+// RUN: ln -fs %clang %T/clang++3.5
+// RUN: ln -fs %clang %T/clang++-3.5
+// RUN: ln -fs %clang %T/clang++-tot
+// RUN: ln -fs %clang %T/clang-c++
+// RUN: ln -fs %clang %T/clang-g++
+// RUN: ln -fs %clang %T/c++
+// RUN: ln -fs %clang %T/foo-clang++
+// RUN: ln -fs %clang %T/foo-clang++-3.5
+// RUN: ln -fs %clang %T/foo-clang++3.5
+// RUN: %T/clang++          -### %s 2>&1 | FileCheck -check-prefix=CXXMODE %s
+// RUN: %T/clang++3.5       -### %s 2>&1 | FileCheck -check-prefix=CXXMODE %s
+// RUN: %T/clang++-3.5      -### %s 2>&1 | FileCheck -check-prefix=CXXMODE %s
+// RUN: %T/clang++-tot      -### %s 2>&1 | FileCheck -check-prefix=CXXMODE %s
+// RUN: %T/clang-c++        -### %s 2>&1 | FileCheck -check-prefix=CXXMODE %s
+// RUN: %T/clang-g++        -### %s 2>&1 | FileCheck -check-prefix=CXXMODE %s
+// RUN: %T/c++              -### %s 2>&1 | FileCheck -check-prefix=CXXMODE %s
+// RUN: %T/foo-clang++      -### %s 2>&1 | FileCheck -check-prefix=CXXMODE %s
+// RUN: %T/foo-clang++-3.5  -### %s 2>&1 | FileCheck -check-prefix=CXXMODE %s
+// RUN: %T/foo-clang++3.5   -### %s 2>&1 | FileCheck -check-prefix=CXXMODE %s
+// CXXMODE: "-x" "c++"
+
+
+// RUN: ln -fs %clang %T/clang-cl
+// RUN: ln -fs %clang %T/cl
+// RUN: ln -fs %clang %T/cl.exe
+// RUN: ln -fs %clang %T/clang-cl3.5
+// RUN: ln -fs %clang %T/clang-cl-3.5
+// RUN: %T/clang-cl         -### %s 2>&1 | FileCheck -check-prefix=CLMODE %s
+// RUN: %T/cl               -### %s 2>&1 | FileCheck -check-prefix=CLMODE %s
+// RUN: %T/cl.exe           -### %s 2>&1 | FileCheck -check-prefix=CLMODE %s
+// RUN: %T/clang-cl3.5      -### %s 2>&1 | FileCheck -check-prefix=CLMODE %s
+// RUN: %T/clang-cl-3.5     -### %s 2>&1 | FileCheck -check-prefix=CLMODE %s
+// CLMODE: "-fdiagnostics-format" "msvc"
+
+
+// RUN: ln -fs %clang %T/clang-cpp
+// RUN: ln -fs %clang %T/cpp
+// RUN: %T/clang-cpp        -### %s 2>&1 | FileCheck -check-prefix=CPPMODE %s
+// RUN: %T/cpp              -### %s 2>&1 | FileCheck -check-prefix=CPPMODE %s
+// CPPMODE: "-E"
+
+
+// RUN: ln -fs %clang %T/cl-clang
+// RUN: %T/cl-clang        -### %s 2>&1 | FileCheck -check-prefix=CMODE %s
+// CMODE: "-x" "c"
+// CMODE-NOT: "-fdiagnostics-format" "msvc"
+
+
+// RUN: ln -fs %clang %T/arm-linux-gnueabi-clang
+// RUN: %T/arm-linux-gnueabi-clang -### %s 2>&1 | FileCheck -check-prefix=TARGET %s
+// TARGET: Target: arm--linux-gnueabi
Index: tools/driver/driver.cpp
===================================================================
--- tools/driver/driver.cpp
+++ tools/driver/driver.cpp
@@ -198,88 +198,91 @@
 extern int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0,
                       void *MainAddr);
 
+/// \brief A list of known driver suffixes. Suffixes are compared against the
+/// program name in order. If there is a match, the frontend type if updated as
+/// necessary by applying the ModeFlag.
+static const struct {
+  const char *Suffix;
+  const char *ModeFlag;
+} DriverSuffixes[] = {
+      {"clang",       nullptr},
+      {"clang++",     "--driver-mode=g++"},
+      {"clang-c++",   "--driver-mode=g++"},
+      {"clang-cc",    nullptr},
+      {"clang-cpp",   "--driver-mode=cpp"},
+      {"clang-g++",   "--driver-mode=g++"},
+      {"clang-gcc",   nullptr},
+      {"clang-cl",    "--driver-mode=cl"},
+      {"cc",          nullptr},
+      {"cpp",         "--driver-mode=cpp"},
+      {"cl",          "--driver-mode=cl"},
+      {"++",          "--driver-mode=g++"},
+};
+
+static int FindDriverSuffix(StringRef ProgName) {
+  for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i)
+    if (ProgName.endswith(DriverSuffixes[i].Suffix))
+      return i;
+  return -1;
+}
+
 static void ParseProgName(SmallVectorImpl<const char *> &ArgVector,
-                          std::set<std::string> &SavedStrings,
-                          Driver &TheDriver)
-{
-  // Try to infer frontend type and default target from the program name.
-
-  // suffixes[] contains the list of known driver suffixes.
-  // Suffixes are compared against the program name in order.
-  // If there is a match, the frontend type is updated as necessary (CPP/C++).
-  // If there is no match, a second round is done after stripping the last
-  // hyphen and everything following it. This allows using something like
-  // "clang++-2.9".
-
-  // If there is a match in either the first or second round,
-  // the function tries to identify a target as prefix. E.g.
-  // "x86_64-linux-clang" as interpreted as suffix "clang" with
-  // target prefix "x86_64-linux". If such a target prefix is found,
-  // is gets added via -target as implicit first argument.
-  static const struct {
-    const char *Suffix;
-    const char *ModeFlag;
-  } suffixes [] = {
-    { "clang",     nullptr },
-    { "clang++",   "--driver-mode=g++" },
-    { "clang-c++", "--driver-mode=g++" },
-    { "clang-cc",  nullptr },
-    { "clang-cpp", "--driver-mode=cpp" },
-    { "clang-g++", "--driver-mode=g++" },
-    { "clang-gcc", nullptr },
-    { "clang-cl",  "--driver-mode=cl"  },
-    { "cc",        nullptr },
-    { "cpp",       "--driver-mode=cpp" },
-    { "cl" ,       "--driver-mode=cl"  },
-    { "++",        "--driver-mode=g++" },
-  };
+                          std::set<std::string> &SavedStrings) {
+  // Try to infer frontend type and default target from the program name by
+  // comparing it against DriverSuffixes in order.
+
+  // If there is a match, the function tries to identify a target as prefix.
+  // E.g. "x86_64-linux-clang" as interpreted as suffix "clang" with target
+  // prefix "x86_64-linux". If such a target prefix is found, is gets added via
+  // -target as implicit first argument.
+
   std::string ProgName(llvm::sys::path::stem(ArgVector[0]));
 #ifdef LLVM_ON_WIN32
   // Transform to lowercase for case insensitive file systems.
-  std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(),
-                 toLowercase);
+  ProgName = StringRef(ProgName).lower();
 #endif
+
   StringRef ProgNameRef(ProgName);
-  StringRef Prefix;
-
-  for (int Components = 2; Components; --Components) {
-    auto I = std::find_if(std::begin(suffixes), std::end(suffixes),
-                          [&](decltype(suffixes[0]) &suffix) {
-      return ProgNameRef.endswith(suffix.Suffix);
-    });
-
-    if (I != std::end(suffixes)) {
-      if (I->ModeFlag) {
-        auto it = ArgVector.begin();
-        if (it != ArgVector.end())
-          ++it;
-        ArgVector.insert(it, I->ModeFlag);
-      }
-      StringRef::size_type LastComponent = ProgNameRef.rfind('-',
-        ProgNameRef.size() - strlen(I->Suffix));
-      if (LastComponent != StringRef::npos)
-        Prefix = ProgNameRef.slice(0, LastComponent);
-      break;
-    }
+  int SuffixIndex = FindDriverSuffix(ProgNameRef);
 
-    StringRef::size_type LastComponent = ProgNameRef.rfind('-');
-    if (LastComponent == StringRef::npos)
-      break;
-    ProgNameRef = ProgNameRef.slice(0, LastComponent);
+  if (SuffixIndex == -1) {
+    // Try again after stripping any trailing version number.
+    while (!ProgNameRef.empty() &&
+           (isDigit(ProgNameRef.back()) || ProgNameRef.back() == '.'))
+      ProgNameRef = ProgNameRef.drop_back(1);
+  }
+  SuffixIndex = FindDriverSuffix(ProgNameRef);
+
+  if (SuffixIndex == -1) {
+    // Try again after stripping trailing -component.
+    ProgNameRef = ProgNameRef.slice(0, ProgNameRef.rfind('-'));
+    SuffixIndex = FindDriverSuffix(ProgNameRef);
   }
 
-  if (Prefix.empty())
-    return;
-
-  std::string IgnoredError;
-  if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) {
-    auto it = ArgVector.begin();
-    if (it != ArgVector.end())
-      ++it;
-    const char* Strings[] =
-      { GetStableCStr(SavedStrings, std::string("-target")),
-        GetStableCStr(SavedStrings, Prefix) };
-    ArgVector.insert(it, std::begin(Strings), std::end(Strings));
+  if (SuffixIndex != -1) {
+    if (const char *Flag = DriverSuffixes[SuffixIndex].ModeFlag) {
+      // Add Flag to the arguments.
+      auto it = ArgVector.begin();
+      if (it != ArgVector.end())
+        ++it;
+      ArgVector.insert(it, Flag);
+    }
+
+    StringRef::size_type LastComponent = ProgNameRef.rfind(
+        '-', ProgNameRef.size() - strlen(DriverSuffixes[SuffixIndex].Suffix));
+    if (LastComponent == StringRef::npos)
+      return;
+
+    // Infer target from the prefix.
+    StringRef Prefix = ProgNameRef.slice(0, LastComponent);
+    std::string IgnoredError;
+    if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) {
+      auto it = ArgVector.begin();
+      if (it != ArgVector.end())
+        ++it;
+      const char *arr[] = { "-target", GetStableCStr(SavedStrings, Prefix) };
+      ArgVector.insert(it, arr, arr + 2);
+    }
   }
 }
 
@@ -446,7 +449,7 @@
   SetInstallDir(argv, TheDriver);
 
   llvm::InitializeAllTargets();
-  ParseProgName(argv, SavedStrings, TheDriver);
+  ParseProgName(argv, SavedStrings);
 
   SetBackdoorDriverOutputsFromEnvVars(TheDriver);
 
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to