]> granicus.if.org Git - clang/commitdiff
Refactor program name logic. Extend it to infer the target triple from
authorJoerg Sonnenberger <joerg@bec.de>
Wed, 16 Mar 2011 20:15:43 +0000 (20:15 +0000)
committerJoerg Sonnenberger <joerg@bec.de>
Wed, 16 Mar 2011 20:15:43 +0000 (20:15 +0000)
the program name, if it includes it as proper prefix. This makes calling
clang with -ccc-host-triple x86_64-linux the same as calling it with the
name x86_64-linux-clang.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127753 91177308-0d34-0410-b5e6-96231b3b80d8

tools/driver/driver.cpp

index 71baf8d78867e740b89dd5321b7356310dee345f..ac529cb528259e8bd148a33ce64deca45d3dbeba 100644 (file)
@@ -35,6 +35,8 @@
 #include "llvm/Support/Program.h"
 #include "llvm/Support/Signals.h"
 #include "llvm/Support/system_error.h"
+#include "llvm/Target/TargetRegistry.h"
+#include "llvm/Target/TargetSelect.h"
 #include <cctype>
 using namespace clang;
 using namespace clang::driver;
@@ -252,6 +254,85 @@ static void ExpandArgv(int argc, const char **argv,
   }
 }
 
+static void ParseProgName(llvm::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 -ccc-host-triple as implicit first argument.
+  static const struct {
+    const char *Suffix;
+    bool IsCXX;
+    bool IsCPP;
+  } suffixes [] = {
+    { "clang", false, false },
+    { "clang++", true, false },
+    { "clang-c++", true, false },
+    { "clang-cc", false, false },
+    { "clang-cpp", false, true },
+    { "clang-g++", true, false },
+    { "clang-gcc", false, false },
+    { "cc", false, false },
+    { "cpp", false, true },
+    { "++", true, false },
+  };
+  std::string ProgName(llvm::sys::path::stem(ArgVector[0]));
+  llvm::StringRef ProgNameRef(ProgName);
+  llvm::StringRef Prefix;
+
+  for (int Components = 2; Components; --Components) {
+    bool FoundMatch = false;
+    size_t i;
+
+    for (i = 0; i < sizeof(suffixes) / sizeof(suffixes[0]); ++i) {
+      if (ProgNameRef.endswith(suffixes[i].Suffix)) {
+        FoundMatch = true;
+        if (suffixes[i].IsCXX)
+          TheDriver.CCCIsCXX = true;
+        if (suffixes[i].IsCPP)
+          TheDriver.CCCIsCPP = true;
+        break;
+      }
+    }
+
+    if (FoundMatch) {
+      llvm::StringRef::size_type LastComponent = ProgNameRef.rfind('-',
+        ProgNameRef.size() - strlen(suffixes[i].Suffix));
+      if (LastComponent != llvm::StringRef::npos)
+        Prefix = ProgNameRef.slice(0, LastComponent);
+      break;
+    }
+
+    llvm::StringRef::size_type LastComponent = ProgNameRef.rfind('-');
+    if (LastComponent == llvm::StringRef::npos)
+      break;
+    ProgNameRef = ProgNameRef.slice(0, LastComponent);
+  }
+
+  if (Prefix.empty())
+    return;
+
+  std::string IgnoredError;
+  if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) {
+    ArgVector.insert(&ArgVector[1],
+      SaveStringInSet(SavedStrings, Prefix));
+    ArgVector.insert(&ArgVector[1],
+      SaveStringInSet(SavedStrings, std::string("-ccc-host-triple")));
+  }
+}
+
 int main(int argc_, const char **argv_) {
   llvm::sys::PrintStackTraceOnErrorSignal();
   llvm::PrettyStackTraceProgram X(argc_, argv_);
@@ -328,24 +409,8 @@ int main(int argc_, const char **argv_) {
       TheDriver.setInstalledDir(InstalledPath);
   }
 
-  // Check for ".*++" or ".*++-[^-]*" to determine if we are a C++
-  // compiler. This matches things like "c++", "clang++", and "clang++-1.1".
-  //
-  // Note that we intentionally want to use argv[0] here, to support "clang++"
-  // being a symlink.
-  //
-  // We use *argv instead of argv[0] to work around a bogus g++ warning.
-  const char *progname = argv_[0];
-  std::string ProgName(llvm::sys::path::stem(progname));
-  if (llvm::StringRef(ProgName).endswith("++") ||
-      llvm::StringRef(ProgName).rsplit('-').first.endswith("++")) {
-    TheDriver.CCCIsCXX = true;
-  }
-
-  if (llvm::StringRef(ProgName).endswith("cpp") ||
-      llvm::StringRef(ProgName).rsplit('-').first.endswith("cpp")) {
-    TheDriver.CCCIsCPP = true;
-  }
+  llvm::InitializeAllTargets();
+  ParseProgName(argv, SavedStrings, TheDriver);
 
   // Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE.
   TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS");