#include "llvm/Option/Option.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace clang::driver;
using namespace clang;
using namespace llvm::opt;
return *SanitizerArguments.get();
}
+namespace {
+struct DriverSuffix {
+ const char *Suffix;
+ const char *ModeFlag;
+};
+
+const DriverSuffix *FindDriverSuffix(StringRef ProgName) {
+ // A 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 by applying the ModeFlag.
+ static const DriverSuffix 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++"},
+ };
+
+ for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i)
+ if (ProgName.endswith(DriverSuffixes[i].Suffix))
+ return &DriverSuffixes[i];
+ return nullptr;
+}
+
+/// Normalize the program name from argv[0] by stripping the file extension if
+/// present and lower-casing the string on Windows.
+std::string normalizeProgramName(llvm::StringRef Argv0) {
+ std::string ProgName = llvm::sys::path::stem(Argv0);
+#ifdef LLVM_ON_WIN32
+ // Transform to lowercase for case insensitive file systems.
+ std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(), ::tolower);
+#endif
+ return ProgName;
+}
+
+const DriverSuffix *parseDriverSuffix(StringRef ProgName) {
+ // 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, it may be
+ // added via -target as implicit first argument.
+ const DriverSuffix *DS = FindDriverSuffix(ProgName);
+
+ if (!DS) {
+ // Try again after stripping any trailing version number:
+ // clang++3.5 -> clang++
+ ProgName = ProgName.rtrim("0123456789.");
+ DS = FindDriverSuffix(ProgName);
+ }
+
+ if (!DS) {
+ // Try again after stripping trailing -component.
+ // clang++-tot -> clang++
+ ProgName = ProgName.slice(0, ProgName.rfind('-'));
+ DS = FindDriverSuffix(ProgName);
+ }
+ return DS;
+}
+} // anonymous namespace
+
+std::pair<std::string, std::string>
+ToolChain::getTargetAndModeFromProgramName(StringRef PN) {
+ std::string ProgName = normalizeProgramName(PN);
+ const DriverSuffix *DS = parseDriverSuffix(ProgName);
+ if (!DS)
+ return std::make_pair("", "");
+ std::string ModeFlag = DS->ModeFlag == nullptr ? "" : DS->ModeFlag;
+
+ std::string::size_type LastComponent =
+ ProgName.rfind('-', ProgName.size() - strlen(DS->Suffix));
+ if (LastComponent == std::string::npos)
+ return std::make_pair("", ModeFlag);
+
+ // Infer target from the prefix.
+ StringRef Prefix(ProgName);
+ Prefix = Prefix.slice(0, LastComponent);
+ std::string IgnoredError;
+ std::string Target;
+ if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) {
+ Target = Prefix;
+ }
+ return std::make_pair(Target, ModeFlag);
+}
+
StringRef ToolChain::getDefaultUniversalArchName() const {
// In universal driver terms, the arch name accepted by -arch isn't exactly
// the same as the ones that appear in the triple. Roughly speaking, this is
#include "clang/Driver/Driver.h"
#include "clang/Driver/DriverDiagnostic.h"
#include "clang/Driver/Options.h"
+#include "clang/Driver/ToolChain.h"
#include "clang/Frontend/ChainedDiagnosticConsumer.h"
#include "clang/Frontend/CompilerInvocation.h"
#include "clang/Frontend/SerializedDiagnosticPrinter.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/Signals.h"
#include "llvm/Support/StringSaver.h"
-#include "llvm/Support/TargetRegistry.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/Timer.h"
#include "llvm/Support/raw_ostream.h"
extern int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0,
void *MainAddr);
-struct DriverSuffix {
- const char *Suffix;
- const char *ModeFlag;
-};
-
-static const DriverSuffix *FindDriverSuffix(StringRef ProgName) {
- // 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 DriverSuffix 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++"},
- };
-
- for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i)
- if (ProgName.endswith(DriverSuffixes[i].Suffix))
- return &DriverSuffixes[i];
- return nullptr;
-}
-
-/// Normalize the program name from argv[0] by stripping the file extension if
-/// present and lower-casing the string on Windows.
-static std::string normalizeProgramName(const char *Argv0) {
- std::string ProgName = llvm::sys::path::stem(Argv0);
-#ifdef LLVM_ON_WIN32
- // Transform to lowercase for case insensitive file systems.
- std::transform(ProgName.begin(), ProgName.end(), ProgName.begin(), ::tolower);
-#endif
- return ProgName;
-}
-
-static const DriverSuffix *parseDriverSuffix(StringRef ProgName) {
- // 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.
- const DriverSuffix *DS = FindDriverSuffix(ProgName);
-
- if (!DS) {
- // Try again after stripping any trailing version number:
- // clang++3.5 -> clang++
- ProgName = ProgName.rtrim("0123456789.");
- DS = FindDriverSuffix(ProgName);
- }
-
- if (!DS) {
- // Try again after stripping trailing -component.
- // clang++-tot -> clang++
- ProgName = ProgName.slice(0, ProgName.rfind('-'));
- DS = FindDriverSuffix(ProgName);
- }
- return DS;
-}
-
-static void insertArgsFromProgramName(StringRef ProgName,
- const DriverSuffix *DS,
- SmallVectorImpl<const char *> &ArgVector,
- std::set<std::string> &SavedStrings) {
- if (!DS)
- return;
-
- if (const char *Flag = DS->ModeFlag) {
- // Add Flag to the arguments.
+static void insertTargetAndModeArgs(StringRef Target, StringRef Mode,
+ SmallVectorImpl<const char *> &ArgVector,
+ std::set<std::string> &SavedStrings) {
+ if (!Mode.empty()) {
+ // Add the mode flag to the arguments.
auto it = ArgVector.begin();
if (it != ArgVector.end())
++it;
- ArgVector.insert(it, Flag);
+ ArgVector.insert(it, GetStableCStr(SavedStrings, Mode));
}
- StringRef::size_type LastComponent = ProgName.rfind(
- '-', ProgName.size() - strlen(DS->Suffix));
- if (LastComponent == StringRef::npos)
- return;
-
- // Infer target from the prefix.
- StringRef Prefix = ProgName.slice(0, LastComponent);
- std::string IgnoredError;
- if (llvm::TargetRegistry::lookupTarget(Prefix, IgnoredError)) {
+ if (!Target.empty()) {
auto it = ArgVector.begin();
if (it != ArgVector.end())
++it;
- const char *arr[] = { "-target", GetStableCStr(SavedStrings, Prefix) };
+ const char *arr[] = {"-target", GetStableCStr(SavedStrings, Target)};
ArgVector.insert(it, std::begin(arr), std::end(arr));
}
}
return 1;
}
- std::string ProgName = normalizeProgramName(argv[0]);
- const DriverSuffix *DS = parseDriverSuffix(ProgName);
+ llvm::InitializeAllTargets();
+ std::string ProgName = argv[0];
+ std::pair<std::string, std::string> TargetAndMode =
+ ToolChain::getTargetAndModeFromProgramName(ProgName);
llvm::BumpPtrAllocator A;
llvm::StringSaver Saver(A);
// Finally, our -cc1 tools don't care which tokenization mode we use because
// response files written by clang will tokenize the same way in either mode.
llvm::cl::TokenizerCallback Tokenizer = &llvm::cl::TokenizeGNUCommandLine;
- if ((DS && DS->ModeFlag && strcmp(DS->ModeFlag, "--driver-mode=cl") == 0) ||
+ if (TargetAndMode.second == "--driver-mode=cl" ||
std::find_if(argv.begin(), argv.end(), [](const char *F) {
return F && strcmp(F, "--driver-mode=cl") == 0;
}) != argv.end()) {
Driver TheDriver(Path, llvm::sys::getDefaultTargetTriple(), Diags);
SetInstallDir(argv, TheDriver, CanonicalPrefixes);
- llvm::InitializeAllTargets();
- insertArgsFromProgramName(ProgName, DS, argv, SavedStrings);
+ insertTargetAndModeArgs(TargetAndMode.first, TargetAndMode.second, argv,
+ SavedStrings);
SetBackdoorDriverOutputsFromEnvVars(TheDriver);