This is the clang side of my updated patch in D4899. I updated the Driver to 
cope with the new LLVM API proposed in that patch: 

- Call ExpandResponseFiles with MarkEOLs set to true to allow correct expansion 
of the /LINK argument, fixing PR17239. Only do this for the clang driver, not 
for clang -cc1 tools.
- Ignore nullptrs in the argv vector because they are now used to indicate end 
of lines.

I also updated the Driver::ParseArgStrings parameter name that had a confusing 
argument name that was the same of a known class used in the same scope (NFC).

http://reviews.llvm.org/D4900

Files:
  lib/Driver/Driver.cpp
  test/Driver/cl-link-at-file.c
  tools/driver/driver.cpp
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,16 +105,16 @@
   }
 }
 
-InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) {
+InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgStrings) {
   llvm::PrettyStackTraceString CrashInfo("Command line argument parsing");
 
   unsigned IncludedFlagsBitmask;
   unsigned ExcludedFlagsBitmask;
   std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
     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<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.
+  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
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to