From 0ce89c6b36004b2def9e7606c7d4678885314d5f Mon Sep 17 00:00:00 2001 From: Joerg Sonnenberger Date: Wed, 16 Mar 2011 20:15:43 +0000 Subject: [PATCH] Refactor program name logic. Extend it to infer the target triple from 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 | 101 +++++++++++++++++++++++++++++++++------- 1 file changed, 83 insertions(+), 18 deletions(-) diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp index 71baf8d788..ac529cb528 100644 --- a/tools/driver/driver.cpp +++ b/tools/driver/driver.cpp @@ -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 using namespace clang; using namespace clang::driver; @@ -252,6 +254,85 @@ static void ExpandArgv(int argc, const char **argv, } } +static void ParseProgName(llvm::SmallVectorImpl &ArgVector, + std::set &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"); -- 2.40.0