diff options
Diffstat (limited to 'tools/driver/driver.cpp')
-rw-r--r-- | tools/driver/driver.cpp | 105 |
1 files changed, 90 insertions, 15 deletions
diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp index 0b5d2c9..db72da4 100644 --- a/tools/driver/driver.cpp +++ b/tools/driver/driver.cpp @@ -18,6 +18,7 @@ #include "clang/Frontend/DiagnosticOptions.h" #include "clang/Frontend/TextDiagnosticPrinter.h" +#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/OwningPtr.h" @@ -35,6 +36,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 +255,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,19 +410,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; - } + llvm::InitializeAllTargets(); + ParseProgName(argv, SavedStrings, TheDriver); // Handle CC_PRINT_OPTIONS and CC_PRINT_OPTIONS_FILE. TheDriver.CCPrintOptions = !!::getenv("CC_PRINT_OPTIONS"); @@ -352,6 +423,11 @@ int main(int argc_, const char **argv_) { if (TheDriver.CCPrintHeaders) TheDriver.CCPrintHeadersFilename = ::getenv("CC_PRINT_HEADERS_FILE"); + // Handle CC_LOG_DIAGNOSTICS and CC_LOG_DIAGNOSTICS_FILE. + TheDriver.CCLogDiagnostics = !!::getenv("CC_LOG_DIAGNOSTICS"); + if (TheDriver.CCLogDiagnostics) + TheDriver.CCLogDiagnosticsFilename = ::getenv("CC_LOG_DIAGNOSTICS_FILE"); + // Handle QA_OVERRIDE_GCC3_OPTIONS and CCC_ADD_ARGS, used for editing a // command line behind the scenes. if (const char *OverrideStr = ::getenv("QA_OVERRIDE_GCC3_OPTIONS")) { @@ -378,8 +454,7 @@ int main(int argc_, const char **argv_) { argv.insert(&argv[1], ExtraArgs.begin(), ExtraArgs.end()); } - llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(argv.size(), - &argv[0])); + llvm::OwningPtr<Compilation> C(TheDriver.BuildCompilation(argv)); int Res = 0; if (C.get()) Res = TheDriver.ExecuteCompilation(*C); |