[PATCH] D19417: Use gcc's rules for parsing gcc-style response files

Nico Weber via llvm-commits llvm-commits at lists.llvm.org
Fri Apr 22 09:21:25 PDT 2016


thakis created this revision.
thakis added a reviewer: rnk.
thakis added a subscriber: llvm-commits.

In gcc, \ escapes every character. It is true that this makes it harder to mention Windows files in rsp files, but not doing this means clang disagrees with gcc, and also disagrees with the shell (on non-Windows) which rsp file quoting is supposed to match. clang isn't free to choose what to do here.

In general, the idea for response files is to take bits of your command line and write them to a file unchanged, and have things work the same way. Since the command line would've been interpreted by the shell, things in the rsp file need to be subject to the same shell quoting rules.

People who want to put Windows-style paths in their response files either need to escape their backslashes, or use clang-cl which uses cl.exe/cmd.exe quoting rules.

http://reviews.llvm.org/D19417

Files:
  lib/Support/CommandLine.cpp
  unittests/Support/CommandLineTest.cpp

Index: unittests/Support/CommandLineTest.cpp
===================================================================
--- unittests/Support/CommandLineTest.cpp
+++ unittests/Support/CommandLineTest.cpp
@@ -165,11 +165,12 @@
 }
 
 TEST(CommandLineTest, TokenizeGNUCommandLine) {
-  const char *Input = "foo\\ bar \"foo bar\" \'foo bar\' 'foo\\\\bar' "
-                      "foo\"bar\"baz C:\\src\\foo.cpp \"C:\\src\\foo.cpp\"";
-  const char *const Output[] = { "foo bar", "foo bar", "foo bar", "foo\\bar",
-                                 "foobarbaz", "C:\\src\\foo.cpp",
-                                 "C:\\src\\foo.cpp" };
+  const char *Input =
+      "foo\\ bar \"foo bar\" \'foo bar\' 'foo\\\\bar' -DFOO=bar\\(\\) "
+      "foo\"bar\"baz C:\\\\src\\\\foo.cpp \"C:\\\\src\\\\foo.cpp\"";
+  const char *const Output[] = {
+      "foo bar",     "foo bar",   "foo bar",          "foo\\bar",
+      "-DFOO=bar()", "foobarbaz", "C:\\src\\foo.cpp", "C:\\src\\foo.cpp"};
   testCommandLineTokenizer(cl::TokenizeGNUCommandLine, Input, Output,
                            array_lengthof(Output));
 }
Index: lib/Support/CommandLine.cpp
===================================================================
--- lib/Support/CommandLine.cpp
+++ lib/Support/CommandLine.cpp
@@ -515,8 +515,6 @@
 
 static bool isQuote(char C) { return C == '\"' || C == '\''; }
 
-static bool isGNUSpecial(char C) { return strchr("\\\"\' ", C); }
-
 void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver,
                                 SmallVectorImpl<const char *> &NewArgv,
                                 bool MarkEOLs) {
@@ -534,9 +532,8 @@
         break;
     }
 
-    // Backslashes can escape backslashes, spaces, and other quotes.  Otherwise
-    // they are literal.  This makes it much easier to read Windows file paths.
-    if (I + 1 < E && Src[I] == '\\' && isGNUSpecial(Src[I + 1])) {
+    // Backslashe escapes the next character.
+    if (I + 1 < E && Src[I] == '\\') {
       ++I; // Skip the escape.
       Token.push_back(Src[I]);
       continue;
@@ -546,8 +543,8 @@
     if (isQuote(Src[I])) {
       char Quote = Src[I++];
       while (I != E && Src[I] != Quote) {
-        // Backslashes are literal, unless they escape a special character.
-        if (Src[I] == '\\' && I + 1 != E && isGNUSpecial(Src[I + 1]))
+        // Backslashes escape the next character.
+        if (Src[I] == '\\' && I + 1 != E)
           ++I;
         Token.push_back(Src[I]);
         ++I;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D19417.54668.patch
Type: text/x-patch
Size: 2481 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20160422/2f07ebc7/attachment.bin>


More information about the llvm-commits mailing list