summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2014-10-17 17:07:59 +0000
committerHans Wennborg <hans@hanshq.net>2014-10-17 17:07:59 +0000
commit6b3f2d24c72610a7143c6069bc260a135cab993d (patch)
tree0dabea599b4a86a93e4037aa646e4e9eb4163e8c /tools
parent365506d4dac5c10be41de9253d3358d5ada62cdb (diff)
Driver: support detecting driver mode when clang has a version suffix without dash (PR21094)
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 a little clearer. Differential Revision: http://reviews.llvm.org/D5833 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@220052 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'tools')
-rw-r--r--tools/driver/driver.cpp157
1 files changed, 81 insertions, 76 deletions
diff --git a/tools/driver/driver.cpp b/tools/driver/driver.cpp
index f411cf9832..5b42783219 100644
--- a/tools/driver/driver.cpp
+++ b/tools/driver/driver.cpp
@@ -198,88 +198,93 @@ extern int cc1_main(ArrayRef<const char *> Argv, const char *Argv0,
extern int cc1as_main(ArrayRef<const char *> Argv, const char *Argv0,
void *MainAddr);
-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++" },
+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++"},
};
- std::string ProgName(llvm::sys::path::stem(ArgVector[0]));
+
+ for (size_t i = 0; i < llvm::array_lengthof(DriverSuffixes); ++i)
+ if (ProgName.endswith(DriverSuffixes[i].Suffix))
+ return &DriverSuffixes[i];
+ return nullptr;
+}
+
+static void ParseProgName(SmallVectorImpl<const char *> &ArgVector,
+ 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;
- }
- StringRef::size_type LastComponent = ProgNameRef.rfind('-');
- if (LastComponent == StringRef::npos)
- break;
- ProgNameRef = ProgNameRef.slice(0, LastComponent);
+ StringRef ProgNameRef = ProgName;
+ const DriverSuffix *DS = FindDriverSuffix(ProgNameRef);
+
+ if (!DS) {
+ // Try again after stripping any trailing version number:
+ // clang++3.5 -> clang++
+ ProgNameRef = ProgNameRef.rtrim("0123456789.");
+ DS = FindDriverSuffix(ProgNameRef);
+ }
+
+ if (!DS) {
+ // Try again after stripping trailing -component.
+ // clang++-tot -> clang++
+ ProgNameRef = ProgNameRef.slice(0, ProgNameRef.rfind('-'));
+ DS = 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 (DS) {
+ if (const char *Flag = DS->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(DS->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, std::begin(arr), std::end(arr));
+ }
}
}
@@ -446,7 +451,7 @@ int main(int argc_, const char **argv_) {
SetInstallDir(argv, TheDriver);
llvm::InitializeAllTargets();
- ParseProgName(argv, SavedStrings, TheDriver);
+ ParseProgName(argv, SavedStrings);
SetBackdoorDriverOutputsFromEnvVars(TheDriver);