Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp +++ lib/Driver/Driver.cpp @@ -83,6 +83,9 @@ getOpts().getOption(options::OPT_driver_mode).getPrefixedName(); for (size_t I = 0, E = Args.size(); I != E; ++I) { + // Ingore nullptrs, they are response file's EOL markers + if (Args[I] == nullptr) + continue; const StringRef Arg = Args[I]; if (!Arg.startswith(OptName)) continue; @@ -102,7 +105,7 @@ } } -InputArgList *Driver::ParseArgStrings(ArrayRef ArgList) { +InputArgList *Driver::ParseArgStrings(ArrayRef ArgStrings) { llvm::PrettyStackTraceString CrashInfo("Command line argument parsing"); unsigned IncludedFlagsBitmask; @@ -111,7 +114,7 @@ getIncludeExcludeOptionFlagMasks(); unsigned MissingArgIndex, MissingArgCount; - InputArgList *Args = getOpts().ParseArgs(ArgList.begin(), ArgList.end(), + InputArgList *Args = getOpts().ParseArgs(ArgStrings.begin(), ArgStrings.end(), MissingArgIndex, MissingArgCount, IncludedFlagsBitmask, ExcludedFlagsBitmask); Index: test/Driver/cl-link-at-file.c =================================================================== --- /dev/null +++ test/Driver/cl-link-at-file.c @@ -0,0 +1,22 @@ +// PR17239 - The /link option, when inside a response file, should only extend +// until the end of the response file (and not the entire command line) + +// Don't attempt slash switches on msys bash. +// REQUIRES: shell-preserves-root + +// Note: %s must be preceded by -- or bound to another option, otherwise it may +// be interpreted as a command-line option, e.g. on Mac where %s is commonly +// under /Users. + +// RUN: echo /link bar.lib baz.lib > %t.args +// RUN: touch %t.obj +// RUN: %clang_cl -### @%t.args -- %t.obj 2>&1 | FileCheck %s -check-prefix=ARGS +// If the "/link" option captures all remaining args beyond its response file, +// it will also capture "--" and our input argument. In this case, Clang will +// be clueless and will emit "argument unused" warnings. If PR17239 is properly +// fixed, this should not happen because the "/link" option is restricted to +// consume only remaining args in its response file. +// ARGS-NOT: warning +// ARGS-NOT: argument unused during compilation +// Identify the linker command +// ARGS: link.exe Index: tools/driver/driver.cpp =================================================================== --- tools/driver/driver.cpp +++ tools/driver/driver.cpp @@ -116,6 +116,9 @@ ReplPattern = ReplPattern.slice(0, ReplPattern.size()-1); for (unsigned i = 1, e = Args.size(); i != e; ++i) { + // Ignore end-of-line response file markers + if (Args[i] == nullptr) + continue; std::string Repl = llvm::Regex(MatchPattern).sub(ReplPattern, Args[i]); if (Repl != Args[i]) { @@ -142,6 +145,9 @@ } else if (Edit[0] == 'O') { for (unsigned i = 1; i < Args.size();) { const char *A = Args[i]; + // Ignore end-of-line response file markers + if (A == nullptr) + continue; if (A[0] == '-' && A[1] == 'O' && (A[2] == '\0' || (A[3] == '\0' && (A[2] == 's' || A[2] == 'z' || @@ -384,14 +390,31 @@ std::set SavedStrings; StringSetSaver Saver(SavedStrings); - llvm::cl::ExpandResponseFiles(Saver, llvm::cl::TokenizeGNUCommandLine, argv); - // Handle -cc1 integrated tools. + // 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); + + // Handle -cc1 integrated tools. + if (argv.size() > 1 && argv[1] != nullptr && + StringRef(argv[1]).startswith("-cc1")) { + // Remove markers, if we added them + if (MarkEOLs) { + auto newEnd = std::remove(argv.begin(), argv.end(), nullptr); + argv.resize(newEnd - argv.begin()); + } return ExecuteCC1Tool(argv, argv[1] + 4); + } bool CanonicalPrefixes = true; for (int i = 1, size = argv.size(); i < size; ++i) { + // Skip end-of-line response file markers + if (argv[i] == nullptr) + continue; if (StringRef(argv[i]) == "-no-canonical-prefixes") { CanonicalPrefixes = false; break; @@ -463,7 +486,7 @@ // If any timers were active but haven't been destroyed yet, print their // results now. This happens in -disable-free mode. llvm::TimerGroup::printAll(llvm::errs()); - + llvm::llvm_shutdown(); #ifdef LLVM_ON_WIN32