diff options
author | Reid Kleckner <reid@kleckner.net> | 2015-07-15 22:42:37 +0000 |
---|---|---|
committer | Reid Kleckner <reid@kleckner.net> | 2015-07-15 22:42:37 +0000 |
commit | e2d03448ba7944e8f983ddd95d50a20e9433777c (patch) | |
tree | 774ed171d9932452f86644e5eca0d468a4d01bd7 /clang/tools/driver/driver.cpp | |
parent | 3f5ed1566e34e7d2a83fb98bead1079e37b52579 (diff) | |
download | bcm5719-llvm-e2d03448ba7944e8f983ddd95d50a20e9433777c.tar.gz bcm5719-llvm-e2d03448ba7944e8f983ddd95d50a20e9433777c.zip |
[clang-cl] Use the Windows response file tokenizer
We were still using the Unix response file tokenizer for all driver
modes. This was difficult to get right in the beginning because there is
a circular dependency. The Driver class also can't officially determine
its mode until it can see all possible --driver-mode= flags, and those
flags could come from the response file.
Now we use the Windows parsing algorithm if the program name looks like
clang-cl, or if the --driver-mode=cl flag is present on the main command
line.
Fixes PR23709.
Reviewers: hans
Differential Revision: http://reviews.llvm.org/D11229
llvm-svn: 242346
Diffstat (limited to 'clang/tools/driver/driver.cpp')
-rw-r--r-- | clang/tools/driver/driver.cpp | 108 |
1 files changed, 67 insertions, 41 deletions
diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp index 5925447841f..d6817a861a0 100644 --- a/clang/tools/driver/driver.cpp +++ b/clang/tools/driver/driver.cpp @@ -231,8 +231,18 @@ static const DriverSuffix *FindDriverSuffix(StringRef ProgName) { return nullptr; } -static void ParseProgName(SmallVectorImpl<const char *> &ArgVector, - std::set<std::string> &SavedStrings) { +/// 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. @@ -240,54 +250,53 @@ static void ParseProgName(SmallVectorImpl<const char *> &ArgVector, // 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. - ProgName = StringRef(ProgName).lower(); -#endif - - StringRef ProgNameRef = ProgName; - const DriverSuffix *DS = FindDriverSuffix(ProgNameRef); + const DriverSuffix *DS = FindDriverSuffix(ProgName); if (!DS) { // Try again after stripping any trailing version number: // clang++3.5 -> clang++ - ProgNameRef = ProgNameRef.rtrim("0123456789."); - DS = FindDriverSuffix(ProgNameRef); + ProgName = ProgName.rtrim("0123456789."); + DS = FindDriverSuffix(ProgName); } if (!DS) { // Try again after stripping trailing -component. // clang++-tot -> clang++ - ProgNameRef = ProgNameRef.slice(0, ProgNameRef.rfind('-')); - DS = FindDriverSuffix(ProgNameRef); + ProgName = ProgName.slice(0, ProgName.rfind('-')); + DS = FindDriverSuffix(ProgName); } + return DS; +} - 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); - } +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. + 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)); - } + 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)) { + 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)); } } @@ -380,16 +389,33 @@ int main(int argc_, const char **argv_) { return 1; } + std::string ProgName = normalizeProgramName(argv[0]); + const DriverSuffix *DS = parseDriverSuffix(ProgName); + llvm::BumpPtrAllocator A; llvm::BumpPtrStringSaver Saver(A); + // Parse response files using the GNU syntax, unless we're in CL mode. There + // are two ways to put clang in CL compatibility mode: argv[0] is either + // clang-cl or cl, or --driver-mode=cl is on the command line. The normal + // command line parsing can't happen until after response file parsing, so we + // have to manually search for a --driver-mode=cl argument the hard way. + // 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) || + std::find_if(argv.begin(), argv.end(), [](const char *F) { + return F && strcmp(F, "--driver-mode=cl") == 0; + }) != argv.end()) { + Tokenizer = &llvm::cl::TokenizeWindowsCommandLine; + } + // Determines whether we want nullptr markers in argv to indicate response // files end-of-lines. We only use this for the /LINK driver argument. bool MarkEOLs = true; if (argv.size() > 1 && StringRef(argv[1]).startswith("-cc1")) MarkEOLs = false; - llvm::cl::ExpandResponseFiles(Saver, llvm::cl::TokenizeGNUCommandLine, argv, - MarkEOLs); + llvm::cl::ExpandResponseFiles(Saver, Tokenizer, argv, MarkEOLs); // Handle -cc1 integrated tools, even if -cc1 was expanded from a response // file. @@ -450,7 +476,7 @@ int main(int argc_, const char **argv_) { SetInstallDir(argv, TheDriver); llvm::InitializeAllTargets(); - ParseProgName(argv, SavedStrings); + insertArgsFromProgramName(ProgName, DS, argv, SavedStrings); SetBackdoorDriverOutputsFromEnvVars(TheDriver); |