summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/lib/Driver/Driver.cpp7
-rw-r--r--clang/test/Driver/Inputs/cc1-response.txt4
-rw-r--r--clang/test/Driver/cc1-response-files.c2
-rw-r--r--clang/test/Driver/cl-link-at-file.c22
-rw-r--r--clang/tools/driver/driver.cpp29
5 files changed, 60 insertions, 4 deletions
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index f6a39a9ab7c..482f9cf1730 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -83,6 +83,9 @@ void Driver::ParseDriverMode(ArrayRef<const char *> Args) {
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 @@ void Driver::ParseDriverMode(ArrayRef<const char *> Args) {
}
}
-InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) {
+InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings) {
llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
unsigned IncludedFlagsBitmask;
@@ -111,7 +114,7 @@ InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) {
getIncludeExcludeOptionFlagMasks();
unsigned MissingArgIndex, MissingArgCount;
- InputArgList *Args = getOpts().ParseArgs(ArgList.begin(), ArgList.end(),
+ InputArgList *Args = getOpts().ParseArgs(ArgStrings.begin(), ArgStrings.end(),
MissingArgIndex, MissingArgCount,
IncludedFlagsBitmask,
ExcludedFlagsBitmask);
diff --git a/clang/test/Driver/Inputs/cc1-response.txt b/clang/test/Driver/Inputs/cc1-response.txt
new file mode 100644
index 00000000000..0236fdc6aa3
--- /dev/null
+++ b/clang/test/Driver/Inputs/cc1-response.txt
@@ -0,0 +1,4 @@
+
+
+-cc1
+-triple i686-pc-windows-msvc
diff --git a/clang/test/Driver/cc1-response-files.c b/clang/test/Driver/cc1-response-files.c
new file mode 100644
index 00000000000..f47e6448a6c
--- /dev/null
+++ b/clang/test/Driver/cc1-response-files.c
@@ -0,0 +1,2 @@
+// RUN: %clang @%S/Inputs/cc1-response.txt -fsyntax-only -disable-llvm-optzns
+int main() {}
diff --git a/clang/test/Driver/cl-link-at-file.c b/clang/test/Driver/cl-link-at-file.c
new file mode 100644
index 00000000000..f817ce523ad
--- /dev/null
+++ b/clang/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
diff --git a/clang/tools/driver/driver.cpp b/clang/tools/driver/driver.cpp
index 2533401082a..524ead29a7f 100644
--- a/clang/tools/driver/driver.cpp
+++ b/clang/tools/driver/driver.cpp
@@ -116,6 +116,9 @@ static void ApplyOneQAOverride(raw_ostream &OS,
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 @@ static void ApplyOneQAOverride(raw_ostream &OS,
} 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,33 @@ int main(int argc_, const char **argv_) {
std::set<std::string> 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, even if -cc1 was expanded from a response
+ // file.
+ auto FirstArg = std::find_if(argv.begin() + 1, argv.end(),
+ [](const char *A) { return A != nullptr; });
+ if (FirstArg != argv.end() && StringRef(*FirstArg).startswith("-cc1")) {
+ // If -cc1 came from a response file, remove the EOL sentinels.
+ 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;
OpenPOWER on IntegriCloud