aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/Support/CommandLineTest.cpp
diff options
context:
space:
mode:
authorSimon Tatham <simon.tatham@arm.com>2022-05-03 10:33:11 +0100
committerSimon Tatham <simon.tatham@arm.com>2022-05-03 11:57:50 +0100
commit32814df442690d4673759296d850804773a7ea5b (patch)
tree9eda48776326782c9bd2daf68faac03289704213 /llvm/unittests/Support/CommandLineTest.cpp
parent1be024ee450f2d3cb07086f6141d50f291c1910b (diff)
downloadllvm-32814df442690d4673759296d850804773a7ea5b.zip
llvm-32814df442690d4673759296d850804773a7ea5b.tar.gz
llvm-32814df442690d4673759296d850804773a7ea5b.tar.bz2
[Windows] Fix handling of \" in program name on cmd line.
Bugzilla #47579: if you invoke clang on Windows via a pathname in which a quoted section closes just after a backslash, e.g. "C:\Program Files\Whatever\"clang.exe then cmd.exe and CreateProcess will correctly find the binary, because when they parse the program name at the start of the command line, they don't regard the \ before the " as having any kind of escaping effect. This is different from the behaviour of the Windows standard C library when it parses the rest of the command line, which would consider that \" not to close the quoted string. But this confuses windows::GetCommandLineArguments, because the Windows API function GetCommandLineW() will return a command line containing that \" sequence, and cl::TokenizeWindowsCommandLine will tokenize the whole string according to the C library's rules. So it will misidentify where the program name stops and the arguments start. To fix this, I've introduced a new variant function cl::TokenizeWindowsCommandLineFull(), intended to be applied to the string returned from GetCommandLineW(). It parses the first word of the command line according to CreateProcess's rules, considering \ to never be an escaping character; thereafter, it switches over to the C library rules for the rest of the command line. Reviewed By: hans Differential Revision: https://reviews.llvm.org/D122914
Diffstat (limited to 'llvm/unittests/Support/CommandLineTest.cpp')
-rw-r--r--llvm/unittests/Support/CommandLineTest.cpp18
1 files changed, 18 insertions, 0 deletions
diff --git a/llvm/unittests/Support/CommandLineTest.cpp b/llvm/unittests/Support/CommandLineTest.cpp
index 7f751e5..ec9901a 100644
--- a/llvm/unittests/Support/CommandLineTest.cpp
+++ b/llvm/unittests/Support/CommandLineTest.cpp
@@ -257,6 +257,24 @@ TEST(CommandLineTest, TokenizeWindowsCommandLineQuotedLastArgument) {
testCommandLineTokenizer(cl::TokenizeWindowsCommandLine, Input3, Output3);
}
+TEST(CommandLineTest, TokenizeWindowsCommandLineExeName) {
+ const char Input1[] =
+ R"("C:\Program Files\Whatever\"clang.exe z.c -DY=\"x\")";
+ const char *const Output1[] = {"C:\\Program Files\\Whatever\\clang.exe",
+ "z.c", "-DY=\"x\""};
+ testCommandLineTokenizer(cl::TokenizeWindowsCommandLineFull, Input1, Output1);
+
+ const char Input2[] = "\"a\\\"b c\\\"d\n\"e\\\"f g\\\"h\n";
+ const char *const Output2[] = {"a\\b", "c\"d", nullptr,
+ "e\\f", "g\"h", nullptr};
+ testCommandLineTokenizer(cl::TokenizeWindowsCommandLineFull, Input2, Output2,
+ /*MarkEOLs=*/true);
+
+ const char Input3[] = R"(\\server\share\subdir\clang.exe)";
+ const char *const Output3[] = {"\\\\server\\share\\subdir\\clang.exe"};
+ testCommandLineTokenizer(cl::TokenizeWindowsCommandLineFull, Input3, Output3);
+}
+
TEST(CommandLineTest, TokenizeAndMarkEOLs) {
// Clang uses EOL marking in response files to support options that consume
// the rest of the arguments on the current line, but do not consume arguments