xref: /llvm-project/llvm/unittests/Support/CommandLineTest.cpp (revision 9d66d263ad4371160320f4f91720a345eb241471)
1 //===- llvm/unittest/Support/CommandLineTest.cpp - CommandLine tests ------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/Support/CommandLine.h"
10 #include "llvm/ADT/STLExtras.h"
11 #include "llvm/ADT/SmallString.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/Config/config.h"
14 #include "llvm/Support/Allocator.h"
15 #include "llvm/Support/FileSystem.h"
16 #include "llvm/Support/InitLLVM.h"
17 #include "llvm/Support/MemoryBuffer.h"
18 #include "llvm/Support/Path.h"
19 #include "llvm/Support/Program.h"
20 #include "llvm/Support/StringSaver.h"
21 #include "llvm/Support/VirtualFileSystem.h"
22 #include "llvm/Support/raw_ostream.h"
23 #include "llvm/TargetParser/Host.h"
24 #include "llvm/TargetParser/Triple.h"
25 #include "llvm/Testing/Support/SupportHelpers.h"
26 #include "gmock/gmock.h"
27 #include "gtest/gtest.h"
28 #include <fstream>
29 #include <stdlib.h>
30 #include <string>
31 #include <tuple>
32 
33 using namespace llvm;
34 using llvm::unittest::TempDir;
35 using llvm::unittest::TempFile;
36 
37 namespace {
38 
39 MATCHER(StringEquality, "Checks if two char* are equal as strings") {
40   return std::string(std::get<0>(arg)) == std::string(std::get<1>(arg));
41 }
42 
43 class TempEnvVar {
44  public:
45   TempEnvVar(const char *name, const char *value)
46       : name(name) {
47     const char *old_value = getenv(name);
48     EXPECT_EQ(nullptr, old_value) << old_value;
49 #if HAVE_SETENV
50     setenv(name, value, true);
51 #endif
52   }
53 
54   ~TempEnvVar() {
55 #if HAVE_SETENV
56     // Assume setenv and unsetenv come together.
57     unsetenv(name);
58 #else
59     (void)name; // Suppress -Wunused-private-field.
60 #endif
61   }
62 
63  private:
64   const char *const name;
65 };
66 
67 template <typename T, typename Base = cl::opt<T>>
68 class StackOption : public Base {
69 public:
70   template <class... Ts>
71   explicit StackOption(Ts &&... Ms) : Base(std::forward<Ts>(Ms)...) {}
72 
73   ~StackOption() override { this->removeArgument(); }
74 
75   template <class DT> StackOption<T> &operator=(const DT &V) {
76     Base::operator=(V);
77     return *this;
78   }
79 };
80 
81 class StackSubCommand : public cl::SubCommand {
82 public:
83   StackSubCommand(StringRef Name,
84                   StringRef Description = StringRef())
85       : SubCommand(Name, Description) {}
86 
87   StackSubCommand() : SubCommand() {}
88 
89   ~StackSubCommand() { unregisterSubCommand(); }
90 };
91 
92 
93 cl::OptionCategory TestCategory("Test Options", "Description");
94 TEST(CommandLineTest, ModifyExisitingOption) {
95   StackOption<int> TestOption("test-option", cl::desc("old description"));
96 
97   static const char Description[] = "New description";
98   static const char ArgString[] = "new-test-option";
99   static const char ValueString[] = "Integer";
100 
101   StringMap<cl::Option *> &Map =
102       cl::getRegisteredOptions(cl::SubCommand::getTopLevel());
103 
104   ASSERT_EQ(Map.count("test-option"), 1u) << "Could not find option in map.";
105 
106   cl::Option *Retrieved = Map["test-option"];
107   ASSERT_EQ(&TestOption, Retrieved) << "Retrieved wrong option.";
108 
109   ASSERT_NE(Retrieved->Categories.end(),
110             find_if(Retrieved->Categories,
111                     [&](const llvm::cl::OptionCategory *Cat) {
112                       return Cat == &cl::getGeneralCategory();
113                     }))
114       << "Incorrect default option category.";
115 
116   Retrieved->addCategory(TestCategory);
117   ASSERT_NE(Retrieved->Categories.end(),
118             find_if(Retrieved->Categories,
119                     [&](const llvm::cl::OptionCategory *Cat) {
120                       return Cat == &TestCategory;
121                     }))
122       << "Failed to modify option's option category.";
123 
124   Retrieved->setDescription(Description);
125   ASSERT_STREQ(Retrieved->HelpStr.data(), Description)
126       << "Changing option description failed.";
127 
128   Retrieved->setArgStr(ArgString);
129   ASSERT_STREQ(ArgString, Retrieved->ArgStr.data())
130       << "Failed to modify option's Argument string.";
131 
132   Retrieved->setValueStr(ValueString);
133   ASSERT_STREQ(Retrieved->ValueStr.data(), ValueString)
134       << "Failed to modify option's Value string.";
135 
136   Retrieved->setHiddenFlag(cl::Hidden);
137   ASSERT_EQ(cl::Hidden, TestOption.getOptionHiddenFlag()) <<
138     "Failed to modify option's hidden flag.";
139 }
140 
141 TEST(CommandLineTest, UseOptionCategory) {
142   StackOption<int> TestOption2("test-option", cl::cat(TestCategory));
143 
144   ASSERT_NE(TestOption2.Categories.end(),
145             find_if(TestOption2.Categories,
146                          [&](const llvm::cl::OptionCategory *Cat) {
147                            return Cat == &TestCategory;
148                          }))
149       << "Failed to assign Option Category.";
150 }
151 
152 TEST(CommandLineTest, UseMultipleCategories) {
153   StackOption<int> TestOption2("test-option2", cl::cat(TestCategory),
154                                cl::cat(cl::getGeneralCategory()),
155                                cl::cat(cl::getGeneralCategory()));
156 
157   // Make sure cl::getGeneralCategory() wasn't added twice.
158   ASSERT_EQ(TestOption2.Categories.size(), 2U);
159 
160   ASSERT_NE(TestOption2.Categories.end(),
161             find_if(TestOption2.Categories,
162                          [&](const llvm::cl::OptionCategory *Cat) {
163                            return Cat == &TestCategory;
164                          }))
165       << "Failed to assign Option Category.";
166   ASSERT_NE(TestOption2.Categories.end(),
167             find_if(TestOption2.Categories,
168                     [&](const llvm::cl::OptionCategory *Cat) {
169                       return Cat == &cl::getGeneralCategory();
170                     }))
171       << "Failed to assign General Category.";
172 
173   cl::OptionCategory AnotherCategory("Additional test Options", "Description");
174   StackOption<int> TestOption("test-option", cl::cat(TestCategory),
175                               cl::cat(AnotherCategory));
176   ASSERT_EQ(TestOption.Categories.end(),
177             find_if(TestOption.Categories,
178                     [&](const llvm::cl::OptionCategory *Cat) {
179                       return Cat == &cl::getGeneralCategory();
180                     }))
181       << "Failed to remove General Category.";
182   ASSERT_NE(TestOption.Categories.end(),
183             find_if(TestOption.Categories,
184                          [&](const llvm::cl::OptionCategory *Cat) {
185                            return Cat == &TestCategory;
186                          }))
187       << "Failed to assign Option Category.";
188   ASSERT_NE(TestOption.Categories.end(),
189             find_if(TestOption.Categories,
190                          [&](const llvm::cl::OptionCategory *Cat) {
191                            return Cat == &AnotherCategory;
192                          }))
193       << "Failed to assign Another Category.";
194 }
195 
196 typedef void ParserFunction(StringRef Source, StringSaver &Saver,
197                             SmallVectorImpl<const char *> &NewArgv,
198                             bool MarkEOLs);
199 
200 void testCommandLineTokenizer(ParserFunction *parse, StringRef Input,
201                               ArrayRef<const char *> Output,
202                               bool MarkEOLs = false) {
203   SmallVector<const char *, 0> Actual;
204   BumpPtrAllocator A;
205   StringSaver Saver(A);
206   parse(Input, Saver, Actual, MarkEOLs);
207   EXPECT_EQ(Output.size(), Actual.size());
208   for (unsigned I = 0, E = Actual.size(); I != E; ++I) {
209     if (I < Output.size()) {
210       EXPECT_STREQ(Output[I], Actual[I]);
211     }
212   }
213 }
214 
215 TEST(CommandLineTest, TokenizeGNUCommandLine) {
216   const char Input[] =
217       "foo\\ bar \"foo bar\" \'foo bar\' 'foo\\\\bar' -DFOO=bar\\(\\) "
218       "foo\"bar\"baz C:\\\\src\\\\foo.cpp \"C:\\src\\foo.cpp\"";
219   const char *const Output[] = {
220       "foo bar",     "foo bar",   "foo bar",          "foo\\bar",
221       "-DFOO=bar()", "foobarbaz", "C:\\src\\foo.cpp", "C:srcfoo.cpp"};
222   testCommandLineTokenizer(cl::TokenizeGNUCommandLine, Input, Output);
223 }
224 
225 TEST(CommandLineTest, TokenizeWindowsCommandLine1) {
226   const char Input[] =
227       R"(a\b c\\d e\\"f g" h\"i j\\\"k "lmn" o pqr "st \"u" \v)";
228   const char *const Output[] = { "a\\b", "c\\\\d", "e\\f g", "h\"i", "j\\\"k",
229                                  "lmn", "o", "pqr", "st \"u", "\\v" };
230   testCommandLineTokenizer(cl::TokenizeWindowsCommandLine, Input, Output);
231 }
232 
233 TEST(CommandLineTest, TokenizeWindowsCommandLine2) {
234   const char Input[] = "clang -c -DFOO=\"\"\"ABC\"\"\" x.cpp";
235   const char *const Output[] = { "clang", "-c", "-DFOO=\"ABC\"", "x.cpp"};
236   testCommandLineTokenizer(cl::TokenizeWindowsCommandLine, Input, Output);
237 }
238 
239 TEST(CommandLineTest, TokenizeWindowsCommandLineQuotedLastArgument) {
240   // Whitespace at the end of the command line doesn't cause an empty last word
241   const char Input0[] = R"(a b c d )";
242   const char *const Output0[] = {"a", "b", "c", "d"};
243   testCommandLineTokenizer(cl::TokenizeWindowsCommandLine, Input0, Output0);
244 
245   // But an explicit "" does
246   const char Input1[] = R"(a b c d "")";
247   const char *const Output1[] = {"a", "b", "c", "d", ""};
248   testCommandLineTokenizer(cl::TokenizeWindowsCommandLine, Input1, Output1);
249 
250   // An unterminated quoted string is also emitted as an argument word, empty
251   // or not
252   const char Input2[] = R"(a b c d ")";
253   const char *const Output2[] = {"a", "b", "c", "d", ""};
254   testCommandLineTokenizer(cl::TokenizeWindowsCommandLine, Input2, Output2);
255   const char Input3[] = R"(a b c d "text)";
256   const char *const Output3[] = {"a", "b", "c", "d", "text"};
257   testCommandLineTokenizer(cl::TokenizeWindowsCommandLine, Input3, Output3);
258 }
259 
260 TEST(CommandLineTest, TokenizeWindowsCommandLineExeName) {
261   const char Input1[] =
262       R"("C:\Program Files\Whatever\"clang.exe z.c -DY=\"x\")";
263   const char *const Output1[] = {"C:\\Program Files\\Whatever\\clang.exe",
264                                  "z.c", "-DY=\"x\""};
265   testCommandLineTokenizer(cl::TokenizeWindowsCommandLineFull, Input1, Output1);
266 
267   const char Input2[] = "\"a\\\"b c\\\"d\n\"e\\\"f g\\\"h\n";
268   const char *const Output2[] = {"a\\b", "c\"d", nullptr,
269                                  "e\\f", "g\"h", nullptr};
270   testCommandLineTokenizer(cl::TokenizeWindowsCommandLineFull, Input2, Output2,
271                            /*MarkEOLs=*/true);
272 
273   const char Input3[] = R"(\\server\share\subdir\clang.exe)";
274   const char *const Output3[] = {"\\\\server\\share\\subdir\\clang.exe"};
275   testCommandLineTokenizer(cl::TokenizeWindowsCommandLineFull, Input3, Output3);
276 }
277 
278 TEST(CommandLineTest, TokenizeAndMarkEOLs) {
279   // Clang uses EOL marking in response files to support options that consume
280   // the rest of the arguments on the current line, but do not consume arguments
281   // from subsequent lines. For example, given these rsp files contents:
282   // /c /Zi /O2
283   // /Oy- /link /debug /opt:ref
284   // /Zc:ThreadsafeStatics-
285   //
286   // clang-cl needs to treat "/debug /opt:ref" as linker flags, and everything
287   // else as compiler flags. The tokenizer inserts nullptr sentinels into the
288   // output so that clang-cl can find the end of the current line.
289   const char Input[] = "clang -Xclang foo\n\nfoo\"bar\"baz\n x.cpp\n";
290   const char *const Output[] = {"clang", "-Xclang", "foo",
291                                 nullptr, nullptr,   "foobarbaz",
292                                 nullptr, "x.cpp",   nullptr};
293   testCommandLineTokenizer(cl::TokenizeWindowsCommandLine, Input, Output,
294                            /*MarkEOLs=*/true);
295   testCommandLineTokenizer(cl::TokenizeGNUCommandLine, Input, Output,
296                            /*MarkEOLs=*/true);
297 }
298 
299 TEST(CommandLineTest, TokenizeConfigFile1) {
300   const char *Input = "\\";
301   const char *const Output[] = { "\\" };
302   testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output);
303 }
304 
305 TEST(CommandLineTest, TokenizeConfigFile2) {
306   const char *Input = "\\abc";
307   const char *const Output[] = { "abc" };
308   testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output);
309 }
310 
311 TEST(CommandLineTest, TokenizeConfigFile3) {
312   const char *Input = "abc\\";
313   const char *const Output[] = { "abc\\" };
314   testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output);
315 }
316 
317 TEST(CommandLineTest, TokenizeConfigFile4) {
318   const char *Input = "abc\\\n123";
319   const char *const Output[] = { "abc123" };
320   testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output);
321 }
322 
323 TEST(CommandLineTest, TokenizeConfigFile5) {
324   const char *Input = "abc\\\r\n123";
325   const char *const Output[] = { "abc123" };
326   testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output);
327 }
328 
329 TEST(CommandLineTest, TokenizeConfigFile6) {
330   const char *Input = "abc\\\n";
331   const char *const Output[] = { "abc" };
332   testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output);
333 }
334 
335 TEST(CommandLineTest, TokenizeConfigFile7) {
336   const char *Input = "abc\\\r\n";
337   const char *const Output[] = { "abc" };
338   testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output);
339 }
340 
341 TEST(CommandLineTest, TokenizeConfigFile8) {
342   SmallVector<const char *, 0> Actual;
343   BumpPtrAllocator A;
344   StringSaver Saver(A);
345   cl::tokenizeConfigFile("\\\n", Saver, Actual, /*MarkEOLs=*/false);
346   EXPECT_TRUE(Actual.empty());
347 }
348 
349 TEST(CommandLineTest, TokenizeConfigFile9) {
350   SmallVector<const char *, 0> Actual;
351   BumpPtrAllocator A;
352   StringSaver Saver(A);
353   cl::tokenizeConfigFile("\\\r\n", Saver, Actual, /*MarkEOLs=*/false);
354   EXPECT_TRUE(Actual.empty());
355 }
356 
357 TEST(CommandLineTest, TokenizeConfigFile10) {
358   const char *Input = "\\\nabc";
359   const char *const Output[] = { "abc" };
360   testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output);
361 }
362 
363 TEST(CommandLineTest, TokenizeConfigFile11) {
364   const char *Input = "\\\r\nabc";
365   const char *const Output[] = { "abc" };
366   testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output);
367 }
368 
369 TEST(CommandLineTest, AliasesWithArguments) {
370   static const size_t ARGC = 3;
371   const char *const Inputs[][ARGC] = {
372     { "-tool", "-actual=x", "-extra" },
373     { "-tool", "-actual", "x" },
374     { "-tool", "-alias=x", "-extra" },
375     { "-tool", "-alias", "x" }
376   };
377 
378   for (size_t i = 0, e = std::size(Inputs); i < e; ++i) {
379     StackOption<std::string> Actual("actual");
380     StackOption<bool> Extra("extra");
381     StackOption<std::string> Input(cl::Positional);
382 
383     cl::alias Alias("alias", llvm::cl::aliasopt(Actual));
384 
385     cl::ParseCommandLineOptions(ARGC, Inputs[i]);
386     EXPECT_EQ("x", Actual);
387     EXPECT_EQ(0, Input.getNumOccurrences());
388 
389     Alias.removeArgument();
390   }
391 }
392 
393 void testAliasRequired(int argc, const char *const *argv) {
394   StackOption<std::string> Option("option", cl::Required);
395   cl::alias Alias("o", llvm::cl::aliasopt(Option));
396 
397   cl::ParseCommandLineOptions(argc, argv);
398   EXPECT_EQ("x", Option);
399   EXPECT_EQ(1, Option.getNumOccurrences());
400 
401   Alias.removeArgument();
402 }
403 
404 TEST(CommandLineTest, AliasRequired) {
405   const char *opts1[] = { "-tool", "-option=x" };
406   const char *opts2[] = { "-tool", "-o", "x" };
407   testAliasRequired(std::size(opts1), opts1);
408   testAliasRequired(std::size(opts2), opts2);
409 }
410 
411 TEST(CommandLineTest, HideUnrelatedOptions) {
412   StackOption<int> TestOption1("hide-option-1");
413   StackOption<int> TestOption2("hide-option-2", cl::cat(TestCategory));
414 
415   cl::HideUnrelatedOptions(TestCategory);
416 
417   ASSERT_EQ(cl::ReallyHidden, TestOption1.getOptionHiddenFlag())
418       << "Failed to hide extra option.";
419   ASSERT_EQ(cl::NotHidden, TestOption2.getOptionHiddenFlag())
420       << "Hid extra option that should be visable.";
421 
422   StringMap<cl::Option *> &Map =
423       cl::getRegisteredOptions(cl::SubCommand::getTopLevel());
424   ASSERT_TRUE(Map.count("help") == (size_t)0 ||
425               cl::NotHidden == Map["help"]->getOptionHiddenFlag())
426       << "Hid default option that should be visable.";
427 }
428 
429 cl::OptionCategory TestCategory2("Test Options set 2", "Description");
430 
431 TEST(CommandLineTest, HideUnrelatedOptionsMulti) {
432   StackOption<int> TestOption1("multi-hide-option-1");
433   StackOption<int> TestOption2("multi-hide-option-2", cl::cat(TestCategory));
434   StackOption<int> TestOption3("multi-hide-option-3", cl::cat(TestCategory2));
435 
436   const cl::OptionCategory *VisibleCategories[] = {&TestCategory,
437                                                    &TestCategory2};
438 
439   cl::HideUnrelatedOptions(ArrayRef(VisibleCategories));
440 
441   ASSERT_EQ(cl::ReallyHidden, TestOption1.getOptionHiddenFlag())
442       << "Failed to hide extra option.";
443   ASSERT_EQ(cl::NotHidden, TestOption2.getOptionHiddenFlag())
444       << "Hid extra option that should be visable.";
445   ASSERT_EQ(cl::NotHidden, TestOption3.getOptionHiddenFlag())
446       << "Hid extra option that should be visable.";
447 
448   StringMap<cl::Option *> &Map =
449       cl::getRegisteredOptions(cl::SubCommand::getTopLevel());
450   ASSERT_TRUE(Map.count("help") == (size_t)0 ||
451               cl::NotHidden == Map["help"]->getOptionHiddenFlag())
452       << "Hid default option that should be visable.";
453 }
454 
455 TEST(CommandLineTest, SetMultiValues) {
456   StackOption<int> Option("option");
457   const char *args[] = {"prog", "-option=1", "-option=2"};
458   EXPECT_TRUE(cl::ParseCommandLineOptions(std::size(args), args, StringRef(),
459                                           &llvm::nulls()));
460   EXPECT_EQ(Option, 2);
461 }
462 
463 TEST(CommandLineTest, SetValueInSubcategories) {
464   cl::ResetCommandLineParser();
465 
466   StackSubCommand SC1("sc1", "First subcommand");
467   StackSubCommand SC2("sc2", "Second subcommand");
468 
469   StackOption<bool> TopLevelOpt("top-level", cl::init(false));
470   StackOption<bool> SC1Opt("sc1", cl::sub(SC1), cl::init(false));
471   StackOption<bool> SC2Opt("sc2", cl::sub(SC2), cl::init(false));
472 
473   EXPECT_FALSE(TopLevelOpt);
474   EXPECT_FALSE(SC1Opt);
475   EXPECT_FALSE(SC2Opt);
476   const char *args[] = {"prog", "-top-level"};
477   EXPECT_TRUE(
478       cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
479   EXPECT_TRUE(TopLevelOpt);
480   EXPECT_FALSE(SC1Opt);
481   EXPECT_FALSE(SC2Opt);
482 
483   TopLevelOpt = false;
484 
485   cl::ResetAllOptionOccurrences();
486   EXPECT_FALSE(TopLevelOpt);
487   EXPECT_FALSE(SC1Opt);
488   EXPECT_FALSE(SC2Opt);
489   const char *args2[] = {"prog", "sc1", "-sc1"};
490   EXPECT_TRUE(
491       cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
492   EXPECT_FALSE(TopLevelOpt);
493   EXPECT_TRUE(SC1Opt);
494   EXPECT_FALSE(SC2Opt);
495 
496   SC1Opt = false;
497 
498   cl::ResetAllOptionOccurrences();
499   EXPECT_FALSE(TopLevelOpt);
500   EXPECT_FALSE(SC1Opt);
501   EXPECT_FALSE(SC2Opt);
502   const char *args3[] = {"prog", "sc2", "-sc2"};
503   EXPECT_TRUE(
504       cl::ParseCommandLineOptions(3, args3, StringRef(), &llvm::nulls()));
505   EXPECT_FALSE(TopLevelOpt);
506   EXPECT_FALSE(SC1Opt);
507   EXPECT_TRUE(SC2Opt);
508 }
509 
510 TEST(CommandLineTest, LookupFailsInWrongSubCommand) {
511   cl::ResetCommandLineParser();
512 
513   StackSubCommand SC1("sc1", "First subcommand");
514   StackSubCommand SC2("sc2", "Second subcommand");
515 
516   StackOption<bool> SC1Opt("sc1", cl::sub(SC1), cl::init(false));
517   StackOption<bool> SC2Opt("sc2", cl::sub(SC2), cl::init(false));
518 
519   std::string Errs;
520   raw_string_ostream OS(Errs);
521 
522   const char *args[] = {"prog", "sc1", "-sc2"};
523   EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, StringRef(), &OS));
524   OS.flush();
525   EXPECT_FALSE(Errs.empty());
526 }
527 
528 TEST(CommandLineTest, TopLevelOptInSubcommand) {
529   enum LiteralOptionEnum {
530     foo,
531     bar,
532     baz,
533   };
534 
535   cl::ResetCommandLineParser();
536 
537   // This is a top-level option and not associated with a subcommand.
538   // A command line using subcommand should parse both subcommand options and
539   // top-level options.  A valid use case is that users of llvm command line
540   // tools should be able to specify top-level options defined in any library.
541   StackOption<std::string> TopLevelOpt("str", cl::init("txt"),
542                                        cl::desc("A top-level option."));
543 
544   StackSubCommand SC("sc", "Subcommand");
545   StackOption<std::string> PositionalOpt(
546       cl::Positional, cl::desc("positional argument test coverage"),
547       cl::sub(SC));
548   StackOption<LiteralOptionEnum> LiteralOpt(
549       cl::desc("literal argument test coverage"), cl::sub(SC), cl::init(bar),
550       cl::values(clEnumVal(foo, "foo"), clEnumVal(bar, "bar"),
551                  clEnumVal(baz, "baz")));
552   StackOption<bool> EnableOpt("enable", cl::sub(SC), cl::init(false));
553   StackOption<int> ThresholdOpt("threshold", cl::sub(SC), cl::init(1));
554 
555   const char *PositionalOptVal = "input-file";
556   const char *args[] = {"prog",    "sc",        PositionalOptVal,
557                         "-enable", "--str=csv", "--threshold=2"};
558 
559   // cl::ParseCommandLineOptions returns true on success. Otherwise, it will
560   // print the error message to stderr and exit in this setting (`Errs` ostream
561   // is not set).
562   ASSERT_TRUE(cl::ParseCommandLineOptions(sizeof(args) / sizeof(args[0]), args,
563                                           StringRef()));
564   EXPECT_STREQ(PositionalOpt.getValue().c_str(), PositionalOptVal);
565   EXPECT_TRUE(EnableOpt);
566   // Tests that the value of `str` option is `csv` as specified.
567   EXPECT_STREQ(TopLevelOpt.getValue().c_str(), "csv");
568   EXPECT_EQ(ThresholdOpt, 2);
569 
570   for (auto &[LiteralOptVal, WantLiteralOpt] :
571        {std::pair{"--bar", bar}, {"--foo", foo}, {"--baz", baz}}) {
572     const char *args[] = {"prog", "sc", LiteralOptVal};
573     ASSERT_TRUE(cl::ParseCommandLineOptions(sizeof(args) / sizeof(args[0]),
574                                             args, StringRef()));
575 
576     // Tests that literal options are parsed correctly.
577     EXPECT_EQ(LiteralOpt, WantLiteralOpt);
578   }
579 }
580 
581 TEST(CommandLineTest, AddToAllSubCommands) {
582   cl::ResetCommandLineParser();
583 
584   StackSubCommand SC1("sc1", "First subcommand");
585   StackOption<bool> AllOpt("everywhere", cl::sub(cl::SubCommand::getAll()),
586                            cl::init(false));
587   StackSubCommand SC2("sc2", "Second subcommand");
588 
589   const char *args[] = {"prog", "-everywhere"};
590   const char *args2[] = {"prog", "sc1", "-everywhere"};
591   const char *args3[] = {"prog", "sc2", "-everywhere"};
592 
593   std::string Errs;
594   raw_string_ostream OS(Errs);
595 
596   EXPECT_FALSE(AllOpt);
597   EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, StringRef(), &OS));
598   EXPECT_TRUE(AllOpt);
599 
600   AllOpt = false;
601 
602   cl::ResetAllOptionOccurrences();
603   EXPECT_FALSE(AllOpt);
604   EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, StringRef(), &OS));
605   EXPECT_TRUE(AllOpt);
606 
607   AllOpt = false;
608 
609   cl::ResetAllOptionOccurrences();
610   EXPECT_FALSE(AllOpt);
611   EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, StringRef(), &OS));
612   EXPECT_TRUE(AllOpt);
613 
614   // Since all parsing succeeded, the error message should be empty.
615   OS.flush();
616   EXPECT_TRUE(Errs.empty());
617 }
618 
619 TEST(CommandLineTest, ReparseCommandLineOptions) {
620   cl::ResetCommandLineParser();
621 
622   StackOption<bool> TopLevelOpt(
623       "top-level", cl::sub(cl::SubCommand::getTopLevel()), cl::init(false));
624 
625   const char *args[] = {"prog", "-top-level"};
626 
627   EXPECT_FALSE(TopLevelOpt);
628   EXPECT_TRUE(
629       cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
630   EXPECT_TRUE(TopLevelOpt);
631 
632   TopLevelOpt = false;
633 
634   cl::ResetAllOptionOccurrences();
635   EXPECT_FALSE(TopLevelOpt);
636   EXPECT_TRUE(
637       cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
638   EXPECT_TRUE(TopLevelOpt);
639 }
640 
641 TEST(CommandLineTest, RemoveFromRegularSubCommand) {
642   cl::ResetCommandLineParser();
643 
644   StackSubCommand SC("sc", "Subcommand");
645   StackOption<bool> RemoveOption("remove-option", cl::sub(SC), cl::init(false));
646   StackOption<bool> KeepOption("keep-option", cl::sub(SC), cl::init(false));
647 
648   const char *args[] = {"prog", "sc", "-remove-option"};
649 
650   std::string Errs;
651   raw_string_ostream OS(Errs);
652 
653   EXPECT_FALSE(RemoveOption);
654   EXPECT_TRUE(cl::ParseCommandLineOptions(3, args, StringRef(), &OS));
655   EXPECT_TRUE(RemoveOption);
656   OS.flush();
657   EXPECT_TRUE(Errs.empty());
658 
659   RemoveOption.removeArgument();
660 
661   cl::ResetAllOptionOccurrences();
662   EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, StringRef(), &OS));
663   OS.flush();
664   EXPECT_FALSE(Errs.empty());
665 }
666 
667 TEST(CommandLineTest, RemoveFromTopLevelSubCommand) {
668   cl::ResetCommandLineParser();
669 
670   StackOption<bool> TopLevelRemove("top-level-remove",
671                                    cl::sub(cl::SubCommand::getTopLevel()),
672                                    cl::init(false));
673   StackOption<bool> TopLevelKeep("top-level-keep",
674                                  cl::sub(cl::SubCommand::getTopLevel()),
675                                  cl::init(false));
676 
677   const char *args[] = {"prog", "-top-level-remove"};
678 
679   EXPECT_FALSE(TopLevelRemove);
680   EXPECT_TRUE(
681       cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
682   EXPECT_TRUE(TopLevelRemove);
683 
684   TopLevelRemove.removeArgument();
685 
686   cl::ResetAllOptionOccurrences();
687   EXPECT_FALSE(
688       cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
689 }
690 
691 TEST(CommandLineTest, RemoveFromAllSubCommands) {
692   cl::ResetCommandLineParser();
693 
694   StackSubCommand SC1("sc1", "First Subcommand");
695   StackSubCommand SC2("sc2", "Second Subcommand");
696   StackOption<bool> RemoveOption(
697       "remove-option", cl::sub(cl::SubCommand::getAll()), cl::init(false));
698   StackOption<bool> KeepOption("keep-option", cl::sub(cl::SubCommand::getAll()),
699                                cl::init(false));
700 
701   const char *args0[] = {"prog", "-remove-option"};
702   const char *args1[] = {"prog", "sc1", "-remove-option"};
703   const char *args2[] = {"prog", "sc2", "-remove-option"};
704 
705   // It should work for all subcommands including the top-level.
706   EXPECT_FALSE(RemoveOption);
707   EXPECT_TRUE(
708       cl::ParseCommandLineOptions(2, args0, StringRef(), &llvm::nulls()));
709   EXPECT_TRUE(RemoveOption);
710 
711   RemoveOption = false;
712 
713   cl::ResetAllOptionOccurrences();
714   EXPECT_FALSE(RemoveOption);
715   EXPECT_TRUE(
716       cl::ParseCommandLineOptions(3, args1, StringRef(), &llvm::nulls()));
717   EXPECT_TRUE(RemoveOption);
718 
719   RemoveOption = false;
720 
721   cl::ResetAllOptionOccurrences();
722   EXPECT_FALSE(RemoveOption);
723   EXPECT_TRUE(
724       cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
725   EXPECT_TRUE(RemoveOption);
726 
727   RemoveOption.removeArgument();
728 
729   // It should not work for any subcommands including the top-level.
730   cl::ResetAllOptionOccurrences();
731   EXPECT_FALSE(
732       cl::ParseCommandLineOptions(2, args0, StringRef(), &llvm::nulls()));
733   cl::ResetAllOptionOccurrences();
734   EXPECT_FALSE(
735       cl::ParseCommandLineOptions(3, args1, StringRef(), &llvm::nulls()));
736   cl::ResetAllOptionOccurrences();
737   EXPECT_FALSE(
738       cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
739 }
740 
741 TEST(CommandLineTest, GetRegisteredSubcommands) {
742   cl::ResetCommandLineParser();
743 
744   StackSubCommand SC1("sc1", "First Subcommand");
745   StackOption<bool> Opt1("opt1", cl::sub(SC1), cl::init(false));
746   StackSubCommand SC2("sc2", "Second subcommand");
747   StackOption<bool> Opt2("opt2", cl::sub(SC2), cl::init(false));
748 
749   const char *args0[] = {"prog", "sc1"};
750   const char *args1[] = {"prog", "sc2"};
751 
752   EXPECT_TRUE(
753       cl::ParseCommandLineOptions(2, args0, StringRef(), &llvm::nulls()));
754   EXPECT_FALSE(Opt1);
755   EXPECT_FALSE(Opt2);
756   for (auto *S : cl::getRegisteredSubcommands()) {
757     if (*S) {
758       EXPECT_EQ("sc1", S->getName());
759     }
760   }
761 
762   cl::ResetAllOptionOccurrences();
763   EXPECT_TRUE(
764       cl::ParseCommandLineOptions(2, args1, StringRef(), &llvm::nulls()));
765   EXPECT_FALSE(Opt1);
766   EXPECT_FALSE(Opt2);
767   for (auto *S : cl::getRegisteredSubcommands()) {
768     if (*S) {
769       EXPECT_EQ("sc2", S->getName());
770     }
771   }
772 }
773 
774 TEST(CommandLineTest, DefaultOptions) {
775   cl::ResetCommandLineParser();
776 
777   StackOption<std::string> Bar("bar", cl::sub(cl::SubCommand::getAll()),
778                                cl::DefaultOption);
779   StackOption<std::string, cl::alias> Bar_Alias(
780       "b", cl::desc("Alias for -bar"), cl::aliasopt(Bar), cl::DefaultOption);
781 
782   StackOption<bool> Foo("foo", cl::init(false),
783                         cl::sub(cl::SubCommand::getAll()), cl::DefaultOption);
784   StackOption<bool, cl::alias> Foo_Alias("f", cl::desc("Alias for -foo"),
785                                          cl::aliasopt(Foo), cl::DefaultOption);
786 
787   StackSubCommand SC1("sc1", "First Subcommand");
788   // Override "-b" and change type in sc1 SubCommand.
789   StackOption<bool> SC1_B("b", cl::sub(SC1), cl::init(false));
790   StackSubCommand SC2("sc2", "Second subcommand");
791   // Override "-foo" and change type in sc2 SubCommand.  Note that this does not
792   // affect "-f" alias, which continues to work correctly.
793   StackOption<std::string> SC2_Foo("foo", cl::sub(SC2));
794 
795   const char *args0[] = {"prog", "-b", "args0 bar string", "-f"};
796   EXPECT_TRUE(cl::ParseCommandLineOptions(std::size(args0), args0,
797                                           StringRef(), &llvm::nulls()));
798   EXPECT_EQ(Bar, "args0 bar string");
799   EXPECT_TRUE(Foo);
800   EXPECT_FALSE(SC1_B);
801   EXPECT_TRUE(SC2_Foo.empty());
802 
803   cl::ResetAllOptionOccurrences();
804 
805   const char *args1[] = {"prog", "sc1", "-b", "-bar", "args1 bar string", "-f"};
806   EXPECT_TRUE(cl::ParseCommandLineOptions(std::size(args1), args1,
807                                           StringRef(), &llvm::nulls()));
808   EXPECT_EQ(Bar, "args1 bar string");
809   EXPECT_TRUE(Foo);
810   EXPECT_TRUE(SC1_B);
811   EXPECT_TRUE(SC2_Foo.empty());
812   for (auto *S : cl::getRegisteredSubcommands()) {
813     if (*S) {
814       EXPECT_EQ("sc1", S->getName());
815     }
816   }
817 
818   cl::ResetAllOptionOccurrences();
819 
820   const char *args2[] = {"prog", "sc2", "-b", "args2 bar string",
821                          "-f", "-foo", "foo string"};
822   EXPECT_TRUE(cl::ParseCommandLineOptions(std::size(args2), args2,
823                                           StringRef(), &llvm::nulls()));
824   EXPECT_EQ(Bar, "args2 bar string");
825   EXPECT_TRUE(Foo);
826   EXPECT_FALSE(SC1_B);
827   EXPECT_EQ(SC2_Foo, "foo string");
828   for (auto *S : cl::getRegisteredSubcommands()) {
829     if (*S) {
830       EXPECT_EQ("sc2", S->getName());
831     }
832   }
833   cl::ResetCommandLineParser();
834 }
835 
836 TEST(CommandLineTest, ArgumentLimit) {
837   std::string args(32 * 4096, 'a');
838   EXPECT_FALSE(llvm::sys::commandLineFitsWithinSystemLimits("cl", args.data()));
839   std::string args2(256, 'a');
840   EXPECT_TRUE(llvm::sys::commandLineFitsWithinSystemLimits("cl", args2.data()));
841 }
842 
843 TEST(CommandLineTest, ArgumentLimitWindows) {
844   if (!Triple(sys::getProcessTriple()).isOSWindows())
845     GTEST_SKIP();
846   // We use 32000 as a limit for command line length. Program name ('cl'),
847   // separating spaces and termination null character occupy 5 symbols.
848   std::string long_arg(32000 - 5, 'b');
849   EXPECT_TRUE(
850       llvm::sys::commandLineFitsWithinSystemLimits("cl", long_arg.data()));
851   long_arg += 'b';
852   EXPECT_FALSE(
853       llvm::sys::commandLineFitsWithinSystemLimits("cl", long_arg.data()));
854 }
855 
856 TEST(CommandLineTest, ResponseFileWindows) {
857   if (!Triple(sys::getProcessTriple()).isOSWindows())
858     GTEST_SKIP();
859 
860   StackOption<std::string, cl::list<std::string>> InputFilenames(
861       cl::Positional, cl::desc("<input files>"));
862   StackOption<bool> TopLevelOpt("top-level", cl::init(false));
863 
864   // Create response file.
865   TempFile ResponseFile("resp-", ".txt",
866                         "-top-level\npath\\dir\\file1\npath/dir/file2",
867                         /*Unique*/ true);
868 
869   llvm::SmallString<128> RspOpt;
870   RspOpt.append(1, '@');
871   RspOpt.append(ResponseFile.path());
872   const char *args[] = {"prog", RspOpt.c_str()};
873   EXPECT_FALSE(TopLevelOpt);
874   EXPECT_TRUE(
875       cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
876   EXPECT_TRUE(TopLevelOpt);
877   EXPECT_EQ(InputFilenames[0], "path\\dir\\file1");
878   EXPECT_EQ(InputFilenames[1], "path/dir/file2");
879 }
880 
881 TEST(CommandLineTest, ResponseFiles) {
882   vfs::InMemoryFileSystem FS;
883 #ifdef _WIN32
884   const char *TestRoot = "C:\\";
885 #else
886   const char *TestRoot = "/";
887 #endif
888   FS.setCurrentWorkingDirectory(TestRoot);
889 
890   // Create included response file of first level.
891   llvm::StringRef IncludedFileName = "resp1";
892   FS.addFile(IncludedFileName, 0,
893              llvm::MemoryBuffer::getMemBuffer("-option_1 -option_2\n"
894                                               "@incdir/resp2\n"
895                                               "-option_3=abcd\n"
896                                               "@incdir/resp3\n"
897                                               "-option_4=efjk\n"));
898 
899   // Directory for included file.
900   llvm::StringRef IncDir = "incdir";
901 
902   // Create included response file of second level.
903   llvm::SmallString<128> IncludedFileName2;
904   llvm::sys::path::append(IncludedFileName2, IncDir, "resp2");
905   FS.addFile(IncludedFileName2, 0,
906              MemoryBuffer::getMemBuffer("-option_21 -option_22\n"
907                                         "-option_23=abcd\n"));
908 
909   // Create second included response file of second level.
910   llvm::SmallString<128> IncludedFileName3;
911   llvm::sys::path::append(IncludedFileName3, IncDir, "resp3");
912   FS.addFile(IncludedFileName3, 0,
913              MemoryBuffer::getMemBuffer("-option_31 -option_32\n"
914                                         "-option_33=abcd\n"));
915 
916   // Prepare 'file' with reference to response file.
917   SmallString<128> IncRef;
918   IncRef.append(1, '@');
919   IncRef.append(IncludedFileName);
920   llvm::SmallVector<const char *, 4> Argv = {"test/test", "-flag_1",
921                                              IncRef.c_str(), "-flag_2"};
922 
923   // Expand response files.
924   llvm::BumpPtrAllocator A;
925   llvm::cl::ExpansionContext ECtx(A, llvm::cl::TokenizeGNUCommandLine);
926   ECtx.setVFS(&FS).setCurrentDir(TestRoot).setRelativeNames(true);
927   ASSERT_FALSE((bool)ECtx.expandResponseFiles(Argv));
928   EXPECT_THAT(Argv, testing::Pointwise(
929                         StringEquality(),
930                         {"test/test", "-flag_1", "-option_1", "-option_2",
931                          "-option_21", "-option_22", "-option_23=abcd",
932                          "-option_3=abcd", "-option_31", "-option_32",
933                          "-option_33=abcd", "-option_4=efjk", "-flag_2"}));
934 }
935 
936 TEST(CommandLineTest, RecursiveResponseFiles) {
937   vfs::InMemoryFileSystem FS;
938 #ifdef _WIN32
939   const char *TestRoot = "C:\\";
940 #else
941   const char *TestRoot = "/";
942 #endif
943   FS.setCurrentWorkingDirectory(TestRoot);
944 
945   StringRef SelfFilePath = "self.rsp";
946   std::string SelfFileRef = ("@" + SelfFilePath).str();
947 
948   StringRef NestedFilePath = "nested.rsp";
949   std::string NestedFileRef = ("@" + NestedFilePath).str();
950 
951   StringRef FlagFilePath = "flag.rsp";
952   std::string FlagFileRef = ("@" + FlagFilePath).str();
953 
954   std::string SelfFileContents;
955   raw_string_ostream SelfFile(SelfFileContents);
956   SelfFile << "-option_1\n";
957   SelfFile << FlagFileRef << "\n";
958   SelfFile << NestedFileRef << "\n";
959   SelfFile << SelfFileRef << "\n";
960   FS.addFile(SelfFilePath, 0, MemoryBuffer::getMemBuffer(SelfFile.str()));
961 
962   std::string NestedFileContents;
963   raw_string_ostream NestedFile(NestedFileContents);
964   NestedFile << "-option_2\n";
965   NestedFile << FlagFileRef << "\n";
966   NestedFile << SelfFileRef << "\n";
967   NestedFile << NestedFileRef << "\n";
968   FS.addFile(NestedFilePath, 0, MemoryBuffer::getMemBuffer(NestedFile.str()));
969 
970   std::string FlagFileContents;
971   raw_string_ostream FlagFile(FlagFileContents);
972   FlagFile << "-option_x\n";
973   FS.addFile(FlagFilePath, 0, MemoryBuffer::getMemBuffer(FlagFile.str()));
974 
975   // Ensure:
976   // Recursive expansion terminates
977   // Recursive files never expand
978   // Non-recursive repeats are allowed
979   SmallVector<const char *, 4> Argv = {"test/test", SelfFileRef.c_str(),
980                                        "-option_3"};
981   BumpPtrAllocator A;
982 #ifdef _WIN32
983   cl::TokenizerCallback Tokenizer = cl::TokenizeWindowsCommandLine;
984 #else
985   cl::TokenizerCallback Tokenizer = cl::TokenizeGNUCommandLine;
986 #endif
987   llvm::cl::ExpansionContext ECtx(A, Tokenizer);
988   ECtx.setVFS(&FS).setCurrentDir(TestRoot);
989   llvm::Error Err = ECtx.expandResponseFiles(Argv);
990   ASSERT_TRUE((bool)Err);
991   SmallString<128> FilePath = SelfFilePath;
992   std::error_code EC = FS.makeAbsolute(FilePath);
993   ASSERT_FALSE((bool)EC);
994   std::string ExpectedMessage =
995       std::string("recursive expansion of: '") + std::string(FilePath) + "'";
996   ASSERT_TRUE(toString(std::move(Err)) == ExpectedMessage);
997 
998   EXPECT_THAT(Argv,
999               testing::Pointwise(StringEquality(),
1000                                  {"test/test", "-option_1", "-option_x",
1001                                   "-option_2", "-option_x", SelfFileRef.c_str(),
1002                                   NestedFileRef.c_str(), SelfFileRef.c_str(),
1003                                   "-option_3"}));
1004 }
1005 
1006 TEST(CommandLineTest, ResponseFilesAtArguments) {
1007   vfs::InMemoryFileSystem FS;
1008 #ifdef _WIN32
1009   const char *TestRoot = "C:\\";
1010 #else
1011   const char *TestRoot = "/";
1012 #endif
1013   FS.setCurrentWorkingDirectory(TestRoot);
1014 
1015   StringRef ResponseFilePath = "test.rsp";
1016 
1017   std::string ResponseFileContents;
1018   raw_string_ostream ResponseFile(ResponseFileContents);
1019   ResponseFile << "-foo" << "\n";
1020   ResponseFile << "-bar" << "\n";
1021   FS.addFile(ResponseFilePath, 0,
1022              MemoryBuffer::getMemBuffer(ResponseFile.str()));
1023 
1024   // Ensure we expand rsp files after lots of non-rsp arguments starting with @.
1025   constexpr size_t NON_RSP_AT_ARGS = 64;
1026   SmallVector<const char *, 4> Argv = {"test/test"};
1027   Argv.append(NON_RSP_AT_ARGS, "@non_rsp_at_arg");
1028   std::string ResponseFileRef = ("@" + ResponseFilePath).str();
1029   Argv.push_back(ResponseFileRef.c_str());
1030 
1031   BumpPtrAllocator A;
1032   llvm::cl::ExpansionContext ECtx(A, cl::TokenizeGNUCommandLine);
1033   ECtx.setVFS(&FS).setCurrentDir(TestRoot);
1034   ASSERT_FALSE((bool)ECtx.expandResponseFiles(Argv));
1035 
1036   // ASSERT instead of EXPECT to prevent potential out-of-bounds access.
1037   ASSERT_EQ(Argv.size(), 1 + NON_RSP_AT_ARGS + 2);
1038   size_t i = 0;
1039   EXPECT_STREQ(Argv[i++], "test/test");
1040   for (; i < 1 + NON_RSP_AT_ARGS; ++i)
1041     EXPECT_STREQ(Argv[i], "@non_rsp_at_arg");
1042   EXPECT_STREQ(Argv[i++], "-foo");
1043   EXPECT_STREQ(Argv[i++], "-bar");
1044 }
1045 
1046 TEST(CommandLineTest, ResponseFileRelativePath) {
1047   vfs::InMemoryFileSystem FS;
1048 #ifdef _WIN32
1049   const char *TestRoot = "C:\\";
1050 #else
1051   const char *TestRoot = "//net";
1052 #endif
1053   FS.setCurrentWorkingDirectory(TestRoot);
1054 
1055   StringRef OuterFile = "dir/outer.rsp";
1056   StringRef OuterFileContents = "@inner.rsp";
1057   FS.addFile(OuterFile, 0, MemoryBuffer::getMemBuffer(OuterFileContents));
1058 
1059   StringRef InnerFile = "dir/inner.rsp";
1060   StringRef InnerFileContents = "-flag";
1061   FS.addFile(InnerFile, 0, MemoryBuffer::getMemBuffer(InnerFileContents));
1062 
1063   SmallVector<const char *, 2> Argv = {"test/test", "@dir/outer.rsp"};
1064 
1065   BumpPtrAllocator A;
1066   llvm::cl::ExpansionContext ECtx(A, cl::TokenizeGNUCommandLine);
1067   ECtx.setVFS(&FS).setCurrentDir(TestRoot).setRelativeNames(true);
1068   ASSERT_FALSE((bool)ECtx.expandResponseFiles(Argv));
1069   EXPECT_THAT(Argv,
1070               testing::Pointwise(StringEquality(), {"test/test", "-flag"}));
1071 }
1072 
1073 TEST(CommandLineTest, ResponseFileEOLs) {
1074   vfs::InMemoryFileSystem FS;
1075 #ifdef _WIN32
1076   const char *TestRoot = "C:\\";
1077 #else
1078   const char *TestRoot = "//net";
1079 #endif
1080   FS.setCurrentWorkingDirectory(TestRoot);
1081   FS.addFile("eols.rsp", 0,
1082              MemoryBuffer::getMemBuffer("-Xclang -Wno-whatever\n input.cpp"));
1083   SmallVector<const char *, 2> Argv = {"clang", "@eols.rsp"};
1084   BumpPtrAllocator A;
1085   llvm::cl::ExpansionContext ECtx(A, cl::TokenizeWindowsCommandLine);
1086   ECtx.setVFS(&FS).setCurrentDir(TestRoot).setMarkEOLs(true).setRelativeNames(
1087       true);
1088   ASSERT_FALSE((bool)ECtx.expandResponseFiles(Argv));
1089   const char *Expected[] = {"clang", "-Xclang", "-Wno-whatever", nullptr,
1090                             "input.cpp"};
1091   ASSERT_EQ(std::size(Expected), Argv.size());
1092   for (size_t I = 0, E = std::size(Expected); I < E; ++I) {
1093     if (Expected[I] == nullptr) {
1094       ASSERT_EQ(Argv[I], nullptr);
1095     } else {
1096       ASSERT_STREQ(Expected[I], Argv[I]);
1097     }
1098   }
1099 }
1100 
1101 TEST(CommandLineTest, BadResponseFile) {
1102   BumpPtrAllocator A;
1103   StringSaver Saver(A);
1104   TempDir ADir("dir", /*Unique*/ true);
1105   SmallString<128> AFilePath = ADir.path();
1106   llvm::sys::path::append(AFilePath, "file.rsp");
1107   std::string AFileExp = std::string("@") + std::string(AFilePath.str());
1108   SmallVector<const char *, 2> Argv = {"clang", AFileExp.c_str()};
1109 
1110   bool Res = cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Argv);
1111   ASSERT_TRUE(Res);
1112   ASSERT_EQ(2U, Argv.size());
1113   ASSERT_STREQ(Argv[0], "clang");
1114   ASSERT_STREQ(Argv[1], AFileExp.c_str());
1115 
1116 #if !defined(_AIX) && !defined(__MVS__)
1117   std::string ADirExp = std::string("@") + std::string(ADir.path());
1118   Argv = {"clang", ADirExp.c_str()};
1119   Res = cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Argv);
1120   ASSERT_FALSE(Res);
1121   ASSERT_EQ(2U, Argv.size());
1122   ASSERT_STREQ(Argv[0], "clang");
1123   ASSERT_STREQ(Argv[1], ADirExp.c_str());
1124 #endif
1125 }
1126 
1127 TEST(CommandLineTest, SetDefaultValue) {
1128   cl::ResetCommandLineParser();
1129 
1130   StackOption<std::string> Opt1("opt1", cl::init("true"));
1131   StackOption<bool> Opt2("opt2", cl::init(true));
1132   cl::alias Alias("alias", llvm::cl::aliasopt(Opt2));
1133   StackOption<int> Opt3("opt3", cl::init(3));
1134 
1135   llvm::SmallVector<int, 3> IntVals = {1, 2, 3};
1136   llvm::SmallVector<std::string, 3> StrVals = {"foo", "bar", "baz"};
1137 
1138   StackOption<int, cl::list<int>> List1(
1139       "list1", cl::list_init<int>(llvm::ArrayRef<int>(IntVals)),
1140       cl::CommaSeparated);
1141   StackOption<std::string, cl::list<std::string>> List2(
1142       "list2", cl::list_init<std::string>(llvm::ArrayRef<std::string>(StrVals)),
1143       cl::CommaSeparated);
1144   cl::alias ListAlias("list-alias", llvm::cl::aliasopt(List2));
1145 
1146   const char *args[] = {"prog",   "-opt1=false", "-list1", "4",
1147                         "-list1", "5,6",         "-opt2",  "-opt3"};
1148 
1149   EXPECT_TRUE(
1150       cl::ParseCommandLineOptions(7, args, StringRef(), &llvm::nulls()));
1151 
1152   EXPECT_EQ(Opt1, "false");
1153   EXPECT_TRUE(Opt2);
1154   EXPECT_EQ(Opt3, 3);
1155 
1156   for (size_t I = 0, E = IntVals.size(); I < E; ++I) {
1157     EXPECT_EQ(IntVals[I] + 3, List1[I]);
1158     EXPECT_EQ(StrVals[I], List2[I]);
1159   }
1160 
1161   Opt2 = false;
1162   Opt3 = 1;
1163 
1164   cl::ResetAllOptionOccurrences();
1165 
1166   for (auto &OM : cl::getRegisteredOptions(cl::SubCommand::getTopLevel())) {
1167     cl::Option *O = OM.second;
1168     if (O->ArgStr == "opt2") {
1169       continue;
1170     }
1171     O->setDefault();
1172   }
1173 
1174   EXPECT_EQ(Opt1, "true");
1175   EXPECT_TRUE(Opt2);
1176   EXPECT_EQ(Opt3, 3);
1177   for (size_t I = 0, E = IntVals.size(); I < E; ++I) {
1178     EXPECT_EQ(IntVals[I], List1[I]);
1179     EXPECT_EQ(StrVals[I], List2[I]);
1180   }
1181 
1182   Alias.removeArgument();
1183   ListAlias.removeArgument();
1184 }
1185 
1186 TEST(CommandLineTest, ReadConfigFile) {
1187   llvm::SmallVector<const char *, 1> Argv;
1188 
1189   TempDir TestDir("unittest", /*Unique*/ true);
1190   TempDir TestSubDir(TestDir.path("subdir"), /*Unique*/ false);
1191 
1192   llvm::SmallString<128> TestCfg = TestDir.path("foo");
1193   TempFile ConfigFile(TestCfg, "",
1194                       "# Comment\n"
1195                       "-option_1\n"
1196                       "-option_2=<CFGDIR>/dir1\n"
1197                       "-option_3=<CFGDIR>\n"
1198                       "-option_4 <CFGDIR>\n"
1199                       "-option_5=<CFG\\\n"
1200                       "DIR>\n"
1201                       "-option_6=<CFGDIR>/dir1,<CFGDIR>/dir2\n"
1202                       "@subconfig\n"
1203                       "-option_11=abcd\n"
1204                       "-option_12=\\\n"
1205                       "cdef\n");
1206 
1207   llvm::SmallString<128> TestCfg2 = TestDir.path("subconfig");
1208   TempFile ConfigFile2(TestCfg2, "",
1209                        "-option_7\n"
1210                        "-option_8=<CFGDIR>/dir2\n"
1211                        "@subdir/subfoo\n"
1212                        "\n"
1213                        "   # comment\n");
1214 
1215   llvm::SmallString<128> TestCfg3 = TestSubDir.path("subfoo");
1216   TempFile ConfigFile3(TestCfg3, "",
1217                        "-option_9=<CFGDIR>/dir3\n"
1218                        "@<CFGDIR>/subfoo2\n");
1219 
1220   llvm::SmallString<128> TestCfg4 = TestSubDir.path("subfoo2");
1221   TempFile ConfigFile4(TestCfg4, "", "-option_10\n");
1222 
1223   // Make sure the current directory is not the directory where config files
1224   // resides. In this case the code that expands response files will not find
1225   // 'subconfig' unless it resolves nested inclusions relative to the including
1226   // file.
1227   llvm::SmallString<128> CurrDir;
1228   std::error_code EC = llvm::sys::fs::current_path(CurrDir);
1229   EXPECT_TRUE(!EC);
1230   EXPECT_NE(CurrDir.str(), TestDir.path());
1231 
1232   llvm::BumpPtrAllocator A;
1233   llvm::cl::ExpansionContext ECtx(A, cl::tokenizeConfigFile);
1234   llvm::Error Result = ECtx.readConfigFile(ConfigFile.path(), Argv);
1235 
1236   EXPECT_FALSE((bool)Result);
1237   EXPECT_EQ(Argv.size(), 13U);
1238   EXPECT_STREQ(Argv[0], "-option_1");
1239   EXPECT_STREQ(Argv[1],
1240                ("-option_2=" + TestDir.path() + "/dir1").str().c_str());
1241   EXPECT_STREQ(Argv[2], ("-option_3=" + TestDir.path()).str().c_str());
1242   EXPECT_STREQ(Argv[3], "-option_4");
1243   EXPECT_STREQ(Argv[4], TestDir.path().str().c_str());
1244   EXPECT_STREQ(Argv[5], ("-option_5=" + TestDir.path()).str().c_str());
1245   EXPECT_STREQ(Argv[6], ("-option_6=" + TestDir.path() + "/dir1," +
1246                          TestDir.path() + "/dir2")
1247                             .str()
1248                             .c_str());
1249   EXPECT_STREQ(Argv[7], "-option_7");
1250   EXPECT_STREQ(Argv[8],
1251                ("-option_8=" + TestDir.path() + "/dir2").str().c_str());
1252   EXPECT_STREQ(Argv[9],
1253                ("-option_9=" + TestSubDir.path() + "/dir3").str().c_str());
1254   EXPECT_STREQ(Argv[10], "-option_10");
1255   EXPECT_STREQ(Argv[11], "-option_11=abcd");
1256   EXPECT_STREQ(Argv[12], "-option_12=cdef");
1257 }
1258 
1259 TEST(CommandLineTest, PositionalEatArgsError) {
1260   cl::ResetCommandLineParser();
1261 
1262   StackOption<std::string, cl::list<std::string>> PosEatArgs(
1263       "positional-eat-args", cl::Positional, cl::desc("<arguments>..."),
1264       cl::PositionalEatsArgs);
1265   StackOption<std::string, cl::list<std::string>> PosEatArgs2(
1266       "positional-eat-args2", cl::Positional, cl::desc("Some strings"),
1267       cl::PositionalEatsArgs);
1268 
1269   const char *args[] = {"prog", "-positional-eat-args=XXXX"};
1270   const char *args2[] = {"prog", "-positional-eat-args=XXXX", "-foo"};
1271   const char *args3[] = {"prog", "-positional-eat-args", "-foo"};
1272   const char *args4[] = {"prog", "-positional-eat-args",
1273                          "-foo", "-positional-eat-args2",
1274                          "-bar", "foo"};
1275 
1276   std::string Errs;
1277   raw_string_ostream OS(Errs);
1278   EXPECT_FALSE(cl::ParseCommandLineOptions(2, args, StringRef(), &OS)); OS.flush();
1279   EXPECT_FALSE(Errs.empty()); Errs.clear();
1280   EXPECT_FALSE(cl::ParseCommandLineOptions(3, args2, StringRef(), &OS)); OS.flush();
1281   EXPECT_FALSE(Errs.empty()); Errs.clear();
1282   EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, StringRef(), &OS)); OS.flush();
1283   EXPECT_TRUE(Errs.empty()); Errs.clear();
1284 
1285   cl::ResetAllOptionOccurrences();
1286   EXPECT_TRUE(cl::ParseCommandLineOptions(6, args4, StringRef(), &OS)); OS.flush();
1287   EXPECT_EQ(PosEatArgs.size(), 1u);
1288   EXPECT_EQ(PosEatArgs2.size(), 2u);
1289   EXPECT_TRUE(Errs.empty());
1290 }
1291 
1292 #ifdef _WIN32
1293 void checkSeparators(StringRef Path) {
1294   char UndesiredSeparator = sys::path::get_separator()[0] == '/' ? '\\' : '/';
1295   ASSERT_EQ(Path.find(UndesiredSeparator), StringRef::npos);
1296 }
1297 
1298 TEST(CommandLineTest, GetCommandLineArguments) {
1299   int argc = __argc;
1300   char **argv = __argv;
1301 
1302   // GetCommandLineArguments is called in InitLLVM.
1303   llvm::InitLLVM X(argc, argv);
1304 
1305   EXPECT_EQ(llvm::sys::path::is_absolute(argv[0]),
1306             llvm::sys::path::is_absolute(__argv[0]));
1307   checkSeparators(argv[0]);
1308 
1309   EXPECT_TRUE(
1310       llvm::sys::path::filename(argv[0]).equals_insensitive("supporttests.exe"))
1311       << "Filename of test executable is "
1312       << llvm::sys::path::filename(argv[0]);
1313 }
1314 #endif
1315 
1316 class OutputRedirector {
1317 public:
1318   OutputRedirector(int RedirectFD)
1319       : RedirectFD(RedirectFD), OldFD(dup(RedirectFD)) {
1320     if (OldFD == -1 ||
1321         sys::fs::createTemporaryFile("unittest-redirect", "", NewFD,
1322                                      FilePath) ||
1323         dup2(NewFD, RedirectFD) == -1)
1324       Valid = false;
1325   }
1326 
1327   ~OutputRedirector() {
1328     dup2(OldFD, RedirectFD);
1329     close(OldFD);
1330     close(NewFD);
1331   }
1332 
1333   SmallVector<char, 128> FilePath;
1334   bool Valid = true;
1335 
1336 private:
1337   int RedirectFD;
1338   int OldFD;
1339   int NewFD;
1340 };
1341 
1342 struct AutoDeleteFile {
1343   SmallVector<char, 128> FilePath;
1344   ~AutoDeleteFile() {
1345     if (!FilePath.empty())
1346       sys::fs::remove(std::string(FilePath.data(), FilePath.size()));
1347   }
1348 };
1349 
1350 static std::string interceptStdout(std::function<void()> F) {
1351   outs().flush(); // flush any output from previous tests
1352   AutoDeleteFile File;
1353   {
1354     OutputRedirector Stdout(fileno(stdout));
1355     if (!Stdout.Valid)
1356       return "";
1357     File.FilePath = Stdout.FilePath;
1358     F();
1359     outs().flush();
1360   }
1361   auto Buffer = MemoryBuffer::getFile(File.FilePath);
1362   if (!Buffer)
1363     return "";
1364   return Buffer->get()->getBuffer().str();
1365 }
1366 
1367 template <void (*Func)(const cl::Option &)>
1368 class PrintOptionTestBase : public ::testing::Test {
1369 public:
1370   // Return std::string because the output of a failing EXPECT check is
1371   // unreadable for StringRef. It also avoids any lifetime issues.
1372   template <typename... Ts> std::string runTest(Ts... OptionAttributes) {
1373     StackOption<OptionValue> TestOption(Opt, cl::desc(HelpText),
1374                                         OptionAttributes...);
1375     return interceptStdout([&]() { Func(TestOption); });
1376   }
1377 
1378   enum class OptionValue { Val };
1379   const StringRef Opt = "some-option";
1380   const StringRef HelpText = "some help";
1381 };
1382 
1383   // This is a workaround for cl::Option sub-classes having their
1384   // printOptionInfo functions private.
1385 void printOptionInfo(const cl::Option &O) {
1386   O.printOptionInfo(/*GlobalWidth=*/26);
1387 }
1388 
1389 using PrintOptionInfoTest = PrintOptionTestBase<printOptionInfo>;
1390 
1391 TEST_F(PrintOptionInfoTest, PrintOptionInfoValueOptionalWithoutSentinel) {
1392   std::string Output =
1393       runTest(cl::ValueOptional,
1394               cl::values(clEnumValN(OptionValue::Val, "v1", "desc1")));
1395 
1396   // clang-format off
1397   EXPECT_EQ(Output, ("  --" + Opt + "=<value> - " + HelpText + "\n"
1398                      "    =v1                 -   desc1\n")
1399                         .str());
1400   // clang-format on
1401 }
1402 
1403 TEST_F(PrintOptionInfoTest, PrintOptionInfoValueOptionalWithSentinel) {
1404   std::string Output = runTest(
1405       cl::ValueOptional, cl::values(clEnumValN(OptionValue::Val, "v1", "desc1"),
1406                                     clEnumValN(OptionValue::Val, "", "")));
1407 
1408   // clang-format off
1409   EXPECT_EQ(Output,
1410             ("  --" + Opt + "         - " + HelpText + "\n"
1411              "  --" + Opt + "=<value> - " + HelpText + "\n"
1412              "    =v1                 -   desc1\n")
1413                 .str());
1414   // clang-format on
1415 }
1416 
1417 TEST_F(PrintOptionInfoTest, PrintOptionInfoValueOptionalWithSentinelWithHelp) {
1418   std::string Output = runTest(
1419       cl::ValueOptional, cl::values(clEnumValN(OptionValue::Val, "v1", "desc1"),
1420                                     clEnumValN(OptionValue::Val, "", "desc2")));
1421 
1422   // clang-format off
1423   EXPECT_EQ(Output, ("  --" + Opt + "         - " + HelpText + "\n"
1424                      "  --" + Opt + "=<value> - " + HelpText + "\n"
1425                      "    =v1                 -   desc1\n"
1426                      "    =<empty>            -   desc2\n")
1427                         .str());
1428   // clang-format on
1429 }
1430 
1431 TEST_F(PrintOptionInfoTest, PrintOptionInfoValueRequiredWithEmptyValueName) {
1432   std::string Output = runTest(
1433       cl::ValueRequired, cl::values(clEnumValN(OptionValue::Val, "v1", "desc1"),
1434                                     clEnumValN(OptionValue::Val, "", "")));
1435 
1436   // clang-format off
1437   EXPECT_EQ(Output, ("  --" + Opt + "=<value> - " + HelpText + "\n"
1438                      "    =v1                 -   desc1\n"
1439                      "    =<empty>\n")
1440                         .str());
1441   // clang-format on
1442 }
1443 
1444 TEST_F(PrintOptionInfoTest, PrintOptionInfoEmptyValueDescription) {
1445   std::string Output = runTest(
1446       cl::ValueRequired, cl::values(clEnumValN(OptionValue::Val, "v1", "")));
1447 
1448   // clang-format off
1449   EXPECT_EQ(Output,
1450             ("  --" + Opt + "=<value> - " + HelpText + "\n"
1451              "    =v1\n").str());
1452   // clang-format on
1453 }
1454 
1455 TEST_F(PrintOptionInfoTest, PrintOptionInfoMultilineValueDescription) {
1456   std::string Output =
1457       runTest(cl::ValueRequired,
1458               cl::values(clEnumValN(OptionValue::Val, "v1",
1459                                     "This is the first enum value\n"
1460                                     "which has a really long description\n"
1461                                     "thus it is multi-line."),
1462                          clEnumValN(OptionValue::Val, "",
1463                                     "This is an unnamed enum value\n"
1464                                     "Should be indented as well")));
1465 
1466   // clang-format off
1467   EXPECT_EQ(Output,
1468             ("  --" + Opt + "=<value> - " + HelpText + "\n"
1469              "    =v1                 -   This is the first enum value\n"
1470              "                            which has a really long description\n"
1471              "                            thus it is multi-line.\n"
1472              "    =<empty>            -   This is an unnamed enum value\n"
1473              "                            Should be indented as well\n").str());
1474   // clang-format on
1475 }
1476 
1477 void printOptionValue(const cl::Option &O) {
1478   O.printOptionValue(/*GlobalWidth=*/12, /*Force=*/true);
1479 }
1480 
1481 using PrintOptionValueTest = PrintOptionTestBase<printOptionValue>;
1482 
1483 TEST_F(PrintOptionValueTest, PrintOptionDefaultValue) {
1484   std::string Output =
1485       runTest(cl::init(OptionValue::Val),
1486               cl::values(clEnumValN(OptionValue::Val, "v1", "desc1")));
1487 
1488   EXPECT_EQ(Output, ("    --" + Opt + " = v1       (default: v1)\n").str());
1489 }
1490 
1491 TEST_F(PrintOptionValueTest, PrintOptionNoDefaultValue) {
1492   std::string Output =
1493       runTest(cl::values(clEnumValN(OptionValue::Val, "v1", "desc1")));
1494 
1495   // Note: the option still has a (zero-initialized) value, but the default
1496   // is invalid and doesn't match any value.
1497   EXPECT_EQ(Output, ("    --" + Opt + " = v1       (default: )\n").str());
1498 }
1499 
1500 TEST_F(PrintOptionValueTest, PrintOptionUnknownValue) {
1501   std::string Output = runTest(cl::init(OptionValue::Val));
1502 
1503   EXPECT_EQ(Output, ("    --" + Opt + " = *unknown option value*\n").str());
1504 }
1505 
1506 class GetOptionWidthTest : public ::testing::Test {
1507 public:
1508   enum class OptionValue { Val };
1509 
1510   template <typename... Ts>
1511   size_t runTest(StringRef ArgName, Ts... OptionAttributes) {
1512     StackOption<OptionValue> TestOption(ArgName, cl::desc("some help"),
1513                                         OptionAttributes...);
1514     return getOptionWidth(TestOption);
1515   }
1516 
1517 private:
1518   // This is a workaround for cl::Option sub-classes having their
1519   // printOptionInfo
1520   // functions private.
1521   size_t getOptionWidth(const cl::Option &O) { return O.getOptionWidth(); }
1522 };
1523 
1524 TEST_F(GetOptionWidthTest, GetOptionWidthArgNameLonger) {
1525   StringRef ArgName("a-long-argument-name");
1526   size_t ExpectedStrSize = ("  --" + ArgName + "=<value> - ").str().size();
1527   EXPECT_EQ(
1528       runTest(ArgName, cl::values(clEnumValN(OptionValue::Val, "v", "help"))),
1529       ExpectedStrSize);
1530 }
1531 
1532 TEST_F(GetOptionWidthTest, GetOptionWidthFirstOptionNameLonger) {
1533   StringRef OptName("a-long-option-name");
1534   size_t ExpectedStrSize = ("    =" + OptName + " - ").str().size();
1535   EXPECT_EQ(
1536       runTest("a", cl::values(clEnumValN(OptionValue::Val, OptName, "help"),
1537                               clEnumValN(OptionValue::Val, "b", "help"))),
1538       ExpectedStrSize);
1539 }
1540 
1541 TEST_F(GetOptionWidthTest, GetOptionWidthSecondOptionNameLonger) {
1542   StringRef OptName("a-long-option-name");
1543   size_t ExpectedStrSize = ("    =" + OptName + " - ").str().size();
1544   EXPECT_EQ(
1545       runTest("a", cl::values(clEnumValN(OptionValue::Val, "b", "help"),
1546                               clEnumValN(OptionValue::Val, OptName, "help"))),
1547       ExpectedStrSize);
1548 }
1549 
1550 TEST_F(GetOptionWidthTest, GetOptionWidthEmptyOptionNameLonger) {
1551   size_t ExpectedStrSize = StringRef("    =<empty> - ").size();
1552   // The length of a=<value> (including indentation) is actually the same as the
1553   // =<empty> string, so it is impossible to distinguish via testing the case
1554   // where the empty string is picked from where the option name is picked.
1555   EXPECT_EQ(runTest("a", cl::values(clEnumValN(OptionValue::Val, "b", "help"),
1556                                     clEnumValN(OptionValue::Val, "", "help"))),
1557             ExpectedStrSize);
1558 }
1559 
1560 TEST_F(GetOptionWidthTest,
1561        GetOptionWidthValueOptionalEmptyOptionWithNoDescription) {
1562   StringRef ArgName("a");
1563   // The length of a=<value> (including indentation) is actually the same as the
1564   // =<empty> string, so it is impossible to distinguish via testing the case
1565   // where the empty string is ignored from where it is not ignored.
1566   // The dash will not actually be printed, but the space it would take up is
1567   // included to ensure a consistent column width.
1568   size_t ExpectedStrSize = ("  -" + ArgName + "=<value> - ").str().size();
1569   EXPECT_EQ(runTest(ArgName, cl::ValueOptional,
1570                     cl::values(clEnumValN(OptionValue::Val, "value", "help"),
1571                                clEnumValN(OptionValue::Val, "", ""))),
1572             ExpectedStrSize);
1573 }
1574 
1575 TEST_F(GetOptionWidthTest,
1576        GetOptionWidthValueRequiredEmptyOptionWithNoDescription) {
1577   // The length of a=<value> (including indentation) is actually the same as the
1578   // =<empty> string, so it is impossible to distinguish via testing the case
1579   // where the empty string is picked from where the option name is picked
1580   size_t ExpectedStrSize = StringRef("    =<empty> - ").size();
1581   EXPECT_EQ(runTest("a", cl::ValueRequired,
1582                     cl::values(clEnumValN(OptionValue::Val, "value", "help"),
1583                                clEnumValN(OptionValue::Val, "", ""))),
1584             ExpectedStrSize);
1585 }
1586 
1587 TEST(CommandLineTest, PrefixOptions) {
1588   cl::ResetCommandLineParser();
1589 
1590   StackOption<std::string, cl::list<std::string>> IncludeDirs(
1591       "I", cl::Prefix, cl::desc("Declare an include directory"));
1592 
1593   // Test non-prefixed variant works with cl::Prefix options.
1594   EXPECT_TRUE(IncludeDirs.empty());
1595   const char *args[] = {"prog", "-I=/usr/include"};
1596   EXPECT_TRUE(
1597       cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
1598   EXPECT_EQ(IncludeDirs.size(), 1u);
1599   EXPECT_EQ(IncludeDirs.front().compare("/usr/include"), 0);
1600 
1601   IncludeDirs.erase(IncludeDirs.begin());
1602   cl::ResetAllOptionOccurrences();
1603 
1604   // Test non-prefixed variant works with cl::Prefix options when value is
1605   // passed in following argument.
1606   EXPECT_TRUE(IncludeDirs.empty());
1607   const char *args2[] = {"prog", "-I", "/usr/include"};
1608   EXPECT_TRUE(
1609       cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
1610   EXPECT_EQ(IncludeDirs.size(), 1u);
1611   EXPECT_EQ(IncludeDirs.front().compare("/usr/include"), 0);
1612 
1613   IncludeDirs.erase(IncludeDirs.begin());
1614   cl::ResetAllOptionOccurrences();
1615 
1616   // Test prefixed variant works with cl::Prefix options.
1617   EXPECT_TRUE(IncludeDirs.empty());
1618   const char *args3[] = {"prog", "-I/usr/include"};
1619   EXPECT_TRUE(
1620       cl::ParseCommandLineOptions(2, args3, StringRef(), &llvm::nulls()));
1621   EXPECT_EQ(IncludeDirs.size(), 1u);
1622   EXPECT_EQ(IncludeDirs.front().compare("/usr/include"), 0);
1623 
1624   StackOption<std::string, cl::list<std::string>> MacroDefs(
1625       "D", cl::AlwaysPrefix, cl::desc("Define a macro"),
1626       cl::value_desc("MACRO[=VALUE]"));
1627 
1628   cl::ResetAllOptionOccurrences();
1629 
1630   // Test non-prefixed variant does not work with cl::AlwaysPrefix options:
1631   // equal sign is part of the value.
1632   EXPECT_TRUE(MacroDefs.empty());
1633   const char *args4[] = {"prog", "-D=HAVE_FOO"};
1634   EXPECT_TRUE(
1635       cl::ParseCommandLineOptions(2, args4, StringRef(), &llvm::nulls()));
1636   EXPECT_EQ(MacroDefs.size(), 1u);
1637   EXPECT_EQ(MacroDefs.front().compare("=HAVE_FOO"), 0);
1638 
1639   MacroDefs.erase(MacroDefs.begin());
1640   cl::ResetAllOptionOccurrences();
1641 
1642   // Test non-prefixed variant does not allow value to be passed in following
1643   // argument with cl::AlwaysPrefix options.
1644   EXPECT_TRUE(MacroDefs.empty());
1645   const char *args5[] = {"prog", "-D", "HAVE_FOO"};
1646   EXPECT_FALSE(
1647       cl::ParseCommandLineOptions(3, args5, StringRef(), &llvm::nulls()));
1648   EXPECT_TRUE(MacroDefs.empty());
1649 
1650   cl::ResetAllOptionOccurrences();
1651 
1652   // Test prefixed variant works with cl::AlwaysPrefix options.
1653   EXPECT_TRUE(MacroDefs.empty());
1654   const char *args6[] = {"prog", "-DHAVE_FOO"};
1655   EXPECT_TRUE(
1656       cl::ParseCommandLineOptions(2, args6, StringRef(), &llvm::nulls()));
1657   EXPECT_EQ(MacroDefs.size(), 1u);
1658   EXPECT_EQ(MacroDefs.front().compare("HAVE_FOO"), 0);
1659 }
1660 
1661 TEST(CommandLineTest, GroupingWithValue) {
1662   cl::ResetCommandLineParser();
1663 
1664   StackOption<bool> OptF("f", cl::Grouping, cl::desc("Some flag"));
1665   StackOption<bool> OptB("b", cl::Grouping, cl::desc("Another flag"));
1666   StackOption<bool> OptD("d", cl::Grouping, cl::ValueDisallowed,
1667                          cl::desc("ValueDisallowed option"));
1668   StackOption<std::string> OptV("v", cl::Grouping,
1669                                 cl::desc("ValueRequired option"));
1670   StackOption<std::string> OptO("o", cl::Grouping, cl::ValueOptional,
1671                                 cl::desc("ValueOptional option"));
1672 
1673   // Should be possible to use an option which requires a value
1674   // at the end of a group.
1675   const char *args1[] = {"prog", "-fv", "val1"};
1676   EXPECT_TRUE(
1677       cl::ParseCommandLineOptions(3, args1, StringRef(), &llvm::nulls()));
1678   EXPECT_TRUE(OptF);
1679   EXPECT_STREQ("val1", OptV.c_str());
1680   OptV.clear();
1681   cl::ResetAllOptionOccurrences();
1682 
1683   // Should not crash if it is accidentally used elsewhere in the group.
1684   const char *args2[] = {"prog", "-vf", "val2"};
1685   EXPECT_FALSE(
1686       cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
1687   OptV.clear();
1688   cl::ResetAllOptionOccurrences();
1689 
1690   // Should allow the "opt=value" form at the end of the group
1691   const char *args3[] = {"prog", "-fv=val3"};
1692   EXPECT_TRUE(
1693       cl::ParseCommandLineOptions(2, args3, StringRef(), &llvm::nulls()));
1694   EXPECT_TRUE(OptF);
1695   EXPECT_STREQ("val3", OptV.c_str());
1696   OptV.clear();
1697   cl::ResetAllOptionOccurrences();
1698 
1699   // Should allow assigning a value for a ValueOptional option
1700   // at the end of the group
1701   const char *args4[] = {"prog", "-fo=val4"};
1702   EXPECT_TRUE(
1703       cl::ParseCommandLineOptions(2, args4, StringRef(), &llvm::nulls()));
1704   EXPECT_TRUE(OptF);
1705   EXPECT_STREQ("val4", OptO.c_str());
1706   OptO.clear();
1707   cl::ResetAllOptionOccurrences();
1708 
1709   // Should assign an empty value if a ValueOptional option is used elsewhere
1710   // in the group.
1711   const char *args5[] = {"prog", "-fob"};
1712   EXPECT_TRUE(
1713       cl::ParseCommandLineOptions(2, args5, StringRef(), &llvm::nulls()));
1714   EXPECT_TRUE(OptF);
1715   EXPECT_EQ(1, OptO.getNumOccurrences());
1716   EXPECT_EQ(1, OptB.getNumOccurrences());
1717   EXPECT_TRUE(OptO.empty());
1718   cl::ResetAllOptionOccurrences();
1719 
1720   // Should not allow an assignment for a ValueDisallowed option.
1721   const char *args6[] = {"prog", "-fd=false"};
1722   EXPECT_FALSE(
1723       cl::ParseCommandLineOptions(2, args6, StringRef(), &llvm::nulls()));
1724 }
1725 
1726 TEST(CommandLineTest, GroupingAndPrefix) {
1727   cl::ResetCommandLineParser();
1728 
1729   StackOption<bool> OptF("f", cl::Grouping, cl::desc("Some flag"));
1730   StackOption<bool> OptB("b", cl::Grouping, cl::desc("Another flag"));
1731   StackOption<std::string> OptP("p", cl::Prefix, cl::Grouping,
1732                                 cl::desc("Prefix and Grouping"));
1733   StackOption<std::string> OptA("a", cl::AlwaysPrefix, cl::Grouping,
1734                                 cl::desc("AlwaysPrefix and Grouping"));
1735 
1736   // Should be possible to use a cl::Prefix option without grouping.
1737   const char *args1[] = {"prog", "-pval1"};
1738   EXPECT_TRUE(
1739       cl::ParseCommandLineOptions(2, args1, StringRef(), &llvm::nulls()));
1740   EXPECT_STREQ("val1", OptP.c_str());
1741   OptP.clear();
1742   cl::ResetAllOptionOccurrences();
1743 
1744   // Should be possible to pass a value in a separate argument.
1745   const char *args2[] = {"prog", "-p", "val2"};
1746   EXPECT_TRUE(
1747       cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
1748   EXPECT_STREQ("val2", OptP.c_str());
1749   OptP.clear();
1750   cl::ResetAllOptionOccurrences();
1751 
1752   // The "-opt=value" form should work, too.
1753   const char *args3[] = {"prog", "-p=val3"};
1754   EXPECT_TRUE(
1755       cl::ParseCommandLineOptions(2, args3, StringRef(), &llvm::nulls()));
1756   EXPECT_STREQ("val3", OptP.c_str());
1757   OptP.clear();
1758   cl::ResetAllOptionOccurrences();
1759 
1760   // All three previous cases should work the same way if an option with both
1761   // cl::Prefix and cl::Grouping modifiers is used at the end of a group.
1762   const char *args4[] = {"prog", "-fpval4"};
1763   EXPECT_TRUE(
1764       cl::ParseCommandLineOptions(2, args4, StringRef(), &llvm::nulls()));
1765   EXPECT_TRUE(OptF);
1766   EXPECT_STREQ("val4", OptP.c_str());
1767   OptP.clear();
1768   cl::ResetAllOptionOccurrences();
1769 
1770   const char *args5[] = {"prog", "-fp", "val5"};
1771   EXPECT_TRUE(
1772       cl::ParseCommandLineOptions(3, args5, StringRef(), &llvm::nulls()));
1773   EXPECT_TRUE(OptF);
1774   EXPECT_STREQ("val5", OptP.c_str());
1775   OptP.clear();
1776   cl::ResetAllOptionOccurrences();
1777 
1778   const char *args6[] = {"prog", "-fp=val6"};
1779   EXPECT_TRUE(
1780       cl::ParseCommandLineOptions(2, args6, StringRef(), &llvm::nulls()));
1781   EXPECT_TRUE(OptF);
1782   EXPECT_STREQ("val6", OptP.c_str());
1783   OptP.clear();
1784   cl::ResetAllOptionOccurrences();
1785 
1786   // Should assign a value even if the part after a cl::Prefix option is equal
1787   // to the name of another option.
1788   const char *args7[] = {"prog", "-fpb"};
1789   EXPECT_TRUE(
1790       cl::ParseCommandLineOptions(2, args7, StringRef(), &llvm::nulls()));
1791   EXPECT_TRUE(OptF);
1792   EXPECT_STREQ("b", OptP.c_str());
1793   EXPECT_FALSE(OptB);
1794   OptP.clear();
1795   cl::ResetAllOptionOccurrences();
1796 
1797   // Should be possible to use a cl::AlwaysPrefix option without grouping.
1798   const char *args8[] = {"prog", "-aval8"};
1799   EXPECT_TRUE(
1800       cl::ParseCommandLineOptions(2, args8, StringRef(), &llvm::nulls()));
1801   EXPECT_STREQ("val8", OptA.c_str());
1802   OptA.clear();
1803   cl::ResetAllOptionOccurrences();
1804 
1805   // Should not be possible to pass a value in a separate argument.
1806   const char *args9[] = {"prog", "-a", "val9"};
1807   EXPECT_FALSE(
1808       cl::ParseCommandLineOptions(3, args9, StringRef(), &llvm::nulls()));
1809   cl::ResetAllOptionOccurrences();
1810 
1811   // With the "-opt=value" form, the "=" symbol should be preserved.
1812   const char *args10[] = {"prog", "-a=val10"};
1813   EXPECT_TRUE(
1814       cl::ParseCommandLineOptions(2, args10, StringRef(), &llvm::nulls()));
1815   EXPECT_STREQ("=val10", OptA.c_str());
1816   OptA.clear();
1817   cl::ResetAllOptionOccurrences();
1818 
1819   // All three previous cases should work the same way if an option with both
1820   // cl::AlwaysPrefix and cl::Grouping modifiers is used at the end of a group.
1821   const char *args11[] = {"prog", "-faval11"};
1822   EXPECT_TRUE(
1823       cl::ParseCommandLineOptions(2, args11, StringRef(), &llvm::nulls()));
1824   EXPECT_TRUE(OptF);
1825   EXPECT_STREQ("val11", OptA.c_str());
1826   OptA.clear();
1827   cl::ResetAllOptionOccurrences();
1828 
1829   const char *args12[] = {"prog", "-fa", "val12"};
1830   EXPECT_FALSE(
1831       cl::ParseCommandLineOptions(3, args12, StringRef(), &llvm::nulls()));
1832   cl::ResetAllOptionOccurrences();
1833 
1834   const char *args13[] = {"prog", "-fa=val13"};
1835   EXPECT_TRUE(
1836       cl::ParseCommandLineOptions(2, args13, StringRef(), &llvm::nulls()));
1837   EXPECT_TRUE(OptF);
1838   EXPECT_STREQ("=val13", OptA.c_str());
1839   OptA.clear();
1840   cl::ResetAllOptionOccurrences();
1841 
1842   // Should assign a value even if the part after a cl::AlwaysPrefix option
1843   // is equal to the name of another option.
1844   const char *args14[] = {"prog", "-fab"};
1845   EXPECT_TRUE(
1846       cl::ParseCommandLineOptions(2, args14, StringRef(), &llvm::nulls()));
1847   EXPECT_TRUE(OptF);
1848   EXPECT_STREQ("b", OptA.c_str());
1849   EXPECT_FALSE(OptB);
1850   OptA.clear();
1851   cl::ResetAllOptionOccurrences();
1852 }
1853 
1854 TEST(CommandLineTest, LongOptions) {
1855   cl::ResetCommandLineParser();
1856 
1857   StackOption<bool> OptA("a", cl::desc("Some flag"));
1858   StackOption<bool> OptBLong("long-flag", cl::desc("Some long flag"));
1859   StackOption<bool, cl::alias> OptB("b", cl::desc("Alias to --long-flag"),
1860                                     cl::aliasopt(OptBLong));
1861   StackOption<std::string> OptAB("ab", cl::desc("Another long option"));
1862 
1863   std::string Errs;
1864   raw_string_ostream OS(Errs);
1865 
1866   const char *args1[] = {"prog", "-a", "-ab", "val1"};
1867   const char *args2[] = {"prog", "-a", "--ab", "val1"};
1868   const char *args3[] = {"prog", "-ab", "--ab", "val1"};
1869 
1870   //
1871   // The following tests treat `-` and `--` the same, and always match the
1872   // longest string.
1873   //
1874 
1875   EXPECT_TRUE(
1876       cl::ParseCommandLineOptions(4, args1, StringRef(), &OS)); OS.flush();
1877   EXPECT_TRUE(OptA);
1878   EXPECT_FALSE(OptBLong);
1879   EXPECT_STREQ("val1", OptAB.c_str());
1880   EXPECT_TRUE(Errs.empty()); Errs.clear();
1881   cl::ResetAllOptionOccurrences();
1882 
1883   EXPECT_TRUE(
1884       cl::ParseCommandLineOptions(4, args2, StringRef(), &OS)); OS.flush();
1885   EXPECT_TRUE(OptA);
1886   EXPECT_FALSE(OptBLong);
1887   EXPECT_STREQ("val1", OptAB.c_str());
1888   EXPECT_TRUE(Errs.empty()); Errs.clear();
1889   cl::ResetAllOptionOccurrences();
1890 
1891   // Fails because `-ab` and `--ab` are treated the same and appear more than
1892   // once.  Also, `val1` is unexpected.
1893   EXPECT_FALSE(
1894       cl::ParseCommandLineOptions(4, args3, StringRef(), &OS)); OS.flush();
1895   outs()<< Errs << "\n";
1896   EXPECT_FALSE(Errs.empty()); Errs.clear();
1897   cl::ResetAllOptionOccurrences();
1898 
1899   //
1900   // The following tests treat `-` and `--` differently, with `-` for short, and
1901   // `--` for long options.
1902   //
1903 
1904   // Fails because `-ab` is treated as `-a -b`, so `-a` is seen twice, and
1905   // `val1` is unexpected.
1906   EXPECT_FALSE(cl::ParseCommandLineOptions(4, args1, StringRef(),
1907                                            &OS, nullptr, true)); OS.flush();
1908   EXPECT_FALSE(Errs.empty()); Errs.clear();
1909   cl::ResetAllOptionOccurrences();
1910 
1911   // Works because `-a` is treated differently than `--ab`.
1912   EXPECT_TRUE(cl::ParseCommandLineOptions(4, args2, StringRef(),
1913                                            &OS, nullptr, true)); OS.flush();
1914   EXPECT_TRUE(Errs.empty()); Errs.clear();
1915   cl::ResetAllOptionOccurrences();
1916 
1917   // Works because `-ab` is treated as `-a -b`, and `--ab` is a long option.
1918   EXPECT_TRUE(cl::ParseCommandLineOptions(4, args3, StringRef(),
1919                                            &OS, nullptr, true));
1920   EXPECT_TRUE(OptA);
1921   EXPECT_TRUE(OptBLong);
1922   EXPECT_STREQ("val1", OptAB.c_str());
1923   OS.flush();
1924   EXPECT_TRUE(Errs.empty()); Errs.clear();
1925   cl::ResetAllOptionOccurrences();
1926 }
1927 
1928 TEST(CommandLineTest, OptionErrorMessage) {
1929   // When there is an error, we expect some error message like:
1930   //   prog: for the -a option: [...]
1931   //
1932   // Test whether the "for the -a option"-part is correctly formatted.
1933   cl::ResetCommandLineParser();
1934 
1935   StackOption<bool> OptA("a", cl::desc("Some option"));
1936   StackOption<bool> OptLong("long", cl::desc("Some long option"));
1937 
1938   std::string Errs;
1939   raw_string_ostream OS(Errs);
1940 
1941   OptA.error("custom error", OS);
1942   OS.flush();
1943   EXPECT_NE(Errs.find("for the -a option:"), std::string::npos);
1944   Errs.clear();
1945 
1946   OptLong.error("custom error", OS);
1947   OS.flush();
1948   EXPECT_NE(Errs.find("for the --long option:"), std::string::npos);
1949   Errs.clear();
1950 
1951   cl::ResetAllOptionOccurrences();
1952 }
1953 
1954 TEST(CommandLineTest, OptionErrorMessageSuggest) {
1955   // When there is an error, and the edit-distance is not very large,
1956   // we expect some error message like:
1957   //   prog: did you mean '--option'?
1958   //
1959   // Test whether this message is well-formatted.
1960   cl::ResetCommandLineParser();
1961 
1962   StackOption<bool> OptLong("aluminium", cl::desc("Some long option"));
1963 
1964   const char *args[] = {"prog", "--aluminum"};
1965 
1966   std::string Errs;
1967   raw_string_ostream OS(Errs);
1968 
1969   EXPECT_FALSE(cl::ParseCommandLineOptions(2, args, StringRef(), &OS));
1970   OS.flush();
1971   EXPECT_NE(Errs.find("prog: Did you mean '--aluminium'?\n"),
1972             std::string::npos);
1973   Errs.clear();
1974 
1975   cl::ResetAllOptionOccurrences();
1976 }
1977 
1978 TEST(CommandLineTest, OptionErrorMessageSuggestNoHidden) {
1979   // We expect that 'really hidden' option do not show up in option
1980   // suggestions.
1981   cl::ResetCommandLineParser();
1982 
1983   StackOption<bool> OptLong("aluminium", cl::desc("Some long option"));
1984   StackOption<bool> OptLong2("aluminum", cl::desc("Bad option"),
1985                              cl::ReallyHidden);
1986 
1987   const char *args[] = {"prog", "--alumnum"};
1988 
1989   std::string Errs;
1990   raw_string_ostream OS(Errs);
1991 
1992   EXPECT_FALSE(cl::ParseCommandLineOptions(2, args, StringRef(), &OS));
1993   OS.flush();
1994   EXPECT_NE(Errs.find("prog: Did you mean '--aluminium'?\n"),
1995             std::string::npos);
1996   Errs.clear();
1997 
1998   cl::ResetAllOptionOccurrences();
1999 }
2000 
2001 TEST(CommandLineTest, Callback) {
2002   cl::ResetCommandLineParser();
2003 
2004   StackOption<bool> OptA("a", cl::desc("option a"));
2005   StackOption<bool> OptB(
2006       "b", cl::desc("option b -- This option turns on option a"),
2007       cl::callback([&](const bool &) { OptA = true; }));
2008   StackOption<bool> OptC(
2009       "c", cl::desc("option c -- This option turns on options a and b"),
2010       cl::callback([&](const bool &) { OptB = true; }));
2011   StackOption<std::string, cl::list<std::string>> List(
2012       "list",
2013       cl::desc("option list -- This option turns on options a, b, and c when "
2014                "'foo' is included in list"),
2015       cl::CommaSeparated,
2016       cl::callback([&](const std::string &Str) {
2017         if (Str == "foo")
2018           OptC = true;
2019       }));
2020 
2021   const char *args1[] = {"prog", "-a"};
2022   EXPECT_TRUE(cl::ParseCommandLineOptions(2, args1));
2023   EXPECT_TRUE(OptA);
2024   EXPECT_FALSE(OptB);
2025   EXPECT_FALSE(OptC);
2026   EXPECT_EQ(List.size(), 0u);
2027   cl::ResetAllOptionOccurrences();
2028 
2029   const char *args2[] = {"prog", "-b"};
2030   EXPECT_TRUE(cl::ParseCommandLineOptions(2, args2));
2031   EXPECT_TRUE(OptA);
2032   EXPECT_TRUE(OptB);
2033   EXPECT_FALSE(OptC);
2034   EXPECT_EQ(List.size(), 0u);
2035   cl::ResetAllOptionOccurrences();
2036 
2037   const char *args3[] = {"prog", "-c"};
2038   EXPECT_TRUE(cl::ParseCommandLineOptions(2, args3));
2039   EXPECT_TRUE(OptA);
2040   EXPECT_TRUE(OptB);
2041   EXPECT_TRUE(OptC);
2042   EXPECT_EQ(List.size(), 0u);
2043   cl::ResetAllOptionOccurrences();
2044 
2045   const char *args4[] = {"prog", "--list=foo,bar"};
2046   EXPECT_TRUE(cl::ParseCommandLineOptions(2, args4));
2047   EXPECT_TRUE(OptA);
2048   EXPECT_TRUE(OptB);
2049   EXPECT_TRUE(OptC);
2050   EXPECT_EQ(List.size(), 2u);
2051   cl::ResetAllOptionOccurrences();
2052 
2053   const char *args5[] = {"prog", "--list=bar"};
2054   EXPECT_TRUE(cl::ParseCommandLineOptions(2, args5));
2055   EXPECT_FALSE(OptA);
2056   EXPECT_FALSE(OptB);
2057   EXPECT_FALSE(OptC);
2058   EXPECT_EQ(List.size(), 1u);
2059 
2060   cl::ResetAllOptionOccurrences();
2061 }
2062 
2063 enum Enum { Val1, Val2 };
2064 static cl::bits<Enum> ExampleBits(
2065     cl::desc("An example cl::bits to ensure it compiles"),
2066     cl::values(
2067       clEnumValN(Val1, "bits-val1", "The Val1 value"),
2068       clEnumValN(Val1, "bits-val2", "The Val2 value")));
2069 
2070 TEST(CommandLineTest, ConsumeAfterOnePositional) {
2071   cl::ResetCommandLineParser();
2072 
2073   // input [args]
2074   StackOption<std::string, cl::opt<std::string>> Input(cl::Positional,
2075                                                        cl::Required);
2076   StackOption<std::string, cl::list<std::string>> ExtraArgs(cl::ConsumeAfter);
2077 
2078   const char *Args[] = {"prog", "input", "arg1", "arg2"};
2079 
2080   std::string Errs;
2081   raw_string_ostream OS(Errs);
2082   EXPECT_TRUE(cl::ParseCommandLineOptions(4, Args, StringRef(), &OS));
2083   OS.flush();
2084   EXPECT_EQ("input", Input);
2085   EXPECT_EQ(ExtraArgs.size(), 2u);
2086   EXPECT_EQ(ExtraArgs[0], "arg1");
2087   EXPECT_EQ(ExtraArgs[1], "arg2");
2088   EXPECT_TRUE(Errs.empty());
2089 }
2090 
2091 TEST(CommandLineTest, ConsumeAfterTwoPositionals) {
2092   cl::ResetCommandLineParser();
2093 
2094   // input1 input2 [args]
2095   StackOption<std::string, cl::opt<std::string>> Input1(cl::Positional,
2096                                                         cl::Required);
2097   StackOption<std::string, cl::opt<std::string>> Input2(cl::Positional,
2098                                                         cl::Required);
2099   StackOption<std::string, cl::list<std::string>> ExtraArgs(cl::ConsumeAfter);
2100 
2101   const char *Args[] = {"prog", "input1", "input2", "arg1", "arg2"};
2102 
2103   std::string Errs;
2104   raw_string_ostream OS(Errs);
2105   EXPECT_TRUE(cl::ParseCommandLineOptions(5, Args, StringRef(), &OS));
2106   OS.flush();
2107   EXPECT_EQ("input1", Input1);
2108   EXPECT_EQ("input2", Input2);
2109   EXPECT_EQ(ExtraArgs.size(), 2u);
2110   EXPECT_EQ(ExtraArgs[0], "arg1");
2111   EXPECT_EQ(ExtraArgs[1], "arg2");
2112   EXPECT_TRUE(Errs.empty());
2113 }
2114 
2115 TEST(CommandLineTest, ResetAllOptionOccurrences) {
2116   cl::ResetCommandLineParser();
2117 
2118   // -option -str -enableA -enableC [sink] input [args]
2119   StackOption<bool> Option("option");
2120   StackOption<std::string> Str("str");
2121   enum Vals { ValA, ValB, ValC };
2122   StackOption<Vals, cl::bits<Vals>> Bits(
2123       cl::values(clEnumValN(ValA, "enableA", "Enable A"),
2124                  clEnumValN(ValB, "enableB", "Enable B"),
2125                  clEnumValN(ValC, "enableC", "Enable C")));
2126   StackOption<std::string, cl::list<std::string>> Sink(cl::Sink);
2127   StackOption<std::string> Input(cl::Positional);
2128   StackOption<std::string, cl::list<std::string>> ExtraArgs(cl::ConsumeAfter);
2129 
2130   const char *Args[] = {"prog",     "-option",  "-str=STR", "-enableA",
2131                         "-enableC", "-unknown", "input",    "-arg"};
2132 
2133   std::string Errs;
2134   raw_string_ostream OS(Errs);
2135   EXPECT_TRUE(cl::ParseCommandLineOptions(8, Args, StringRef(), &OS));
2136   EXPECT_TRUE(OS.str().empty());
2137 
2138   EXPECT_TRUE(Option);
2139   EXPECT_EQ("STR", Str);
2140   EXPECT_EQ((1u << ValA) | (1u << ValC), Bits.getBits());
2141   EXPECT_EQ(1u, Sink.size());
2142   EXPECT_EQ("-unknown", Sink[0]);
2143   EXPECT_EQ("input", Input);
2144   EXPECT_EQ(1u, ExtraArgs.size());
2145   EXPECT_EQ("-arg", ExtraArgs[0]);
2146 
2147   cl::ResetAllOptionOccurrences();
2148   EXPECT_FALSE(Option);
2149   EXPECT_EQ("", Str);
2150   EXPECT_EQ(0u, Bits.getBits());
2151   EXPECT_EQ(0u, Sink.size());
2152   EXPECT_EQ(0, Input.getNumOccurrences());
2153   EXPECT_EQ(0u, ExtraArgs.size());
2154 }
2155 
2156 TEST(CommandLineTest, DefaultValue) {
2157   cl::ResetCommandLineParser();
2158 
2159   StackOption<bool> BoolOption("bool-option");
2160   StackOption<std::string> StrOption("str-option");
2161   StackOption<bool> BoolInitOption("bool-init-option", cl::init(true));
2162   StackOption<std::string> StrInitOption("str-init-option",
2163                                          cl::init("str-default-value"));
2164 
2165   const char *Args[] = {"prog"}; // no options
2166 
2167   std::string Errs;
2168   raw_string_ostream OS(Errs);
2169   EXPECT_TRUE(cl::ParseCommandLineOptions(1, Args, StringRef(), &OS));
2170   EXPECT_TRUE(OS.str().empty());
2171 
2172   EXPECT_TRUE(!BoolOption);
2173   EXPECT_FALSE(BoolOption.Default.hasValue());
2174   EXPECT_EQ(0, BoolOption.getNumOccurrences());
2175 
2176   EXPECT_EQ("", StrOption);
2177   EXPECT_FALSE(StrOption.Default.hasValue());
2178   EXPECT_EQ(0, StrOption.getNumOccurrences());
2179 
2180   EXPECT_TRUE(BoolInitOption);
2181   EXPECT_TRUE(BoolInitOption.Default.hasValue());
2182   EXPECT_EQ(0, BoolInitOption.getNumOccurrences());
2183 
2184   EXPECT_EQ("str-default-value", StrInitOption);
2185   EXPECT_TRUE(StrInitOption.Default.hasValue());
2186   EXPECT_EQ(0, StrInitOption.getNumOccurrences());
2187 
2188   const char *Args2[] = {"prog", "-bool-option", "-str-option=str-value",
2189                          "-bool-init-option=0",
2190                          "-str-init-option=str-init-value"};
2191 
2192   EXPECT_TRUE(cl::ParseCommandLineOptions(5, Args2, StringRef(), &OS));
2193   EXPECT_TRUE(OS.str().empty());
2194 
2195   EXPECT_TRUE(BoolOption);
2196   EXPECT_FALSE(BoolOption.Default.hasValue());
2197   EXPECT_EQ(1, BoolOption.getNumOccurrences());
2198 
2199   EXPECT_EQ("str-value", StrOption);
2200   EXPECT_FALSE(StrOption.Default.hasValue());
2201   EXPECT_EQ(1, StrOption.getNumOccurrences());
2202 
2203   EXPECT_FALSE(BoolInitOption);
2204   EXPECT_TRUE(BoolInitOption.Default.hasValue());
2205   EXPECT_EQ(1, BoolInitOption.getNumOccurrences());
2206 
2207   EXPECT_EQ("str-init-value", StrInitOption);
2208   EXPECT_TRUE(StrInitOption.Default.hasValue());
2209   EXPECT_EQ(1, StrInitOption.getNumOccurrences());
2210 }
2211 
2212 TEST(CommandLineTest, HelpWithoutSubcommands) {
2213   // Check that the help message does not contain the "[subcommand]" placeholder
2214   // and the "SUBCOMMANDS" section if there are no subcommands.
2215   cl::ResetCommandLineParser();
2216   StackOption<bool> Opt("opt", cl::init(false));
2217   const char *args[] = {"prog"};
2218   EXPECT_TRUE(cl::ParseCommandLineOptions(std::size(args), args, StringRef(),
2219                                           &llvm::nulls()));
2220   auto Output = interceptStdout([]() { cl::PrintHelpMessage(); });
2221   EXPECT_NE(std::string::npos, Output.find("USAGE: prog [options]")) << Output;
2222   EXPECT_EQ(std::string::npos, Output.find("SUBCOMMANDS:")) << Output;
2223   cl::ResetCommandLineParser();
2224 }
2225 
2226 TEST(CommandLineTest, HelpWithSubcommands) {
2227   // Check that the help message contains the "[subcommand]" placeholder in the
2228   // "USAGE" line and describes subcommands.
2229   cl::ResetCommandLineParser();
2230   StackSubCommand SC1("sc1", "First Subcommand");
2231   StackSubCommand SC2("sc2", "Second Subcommand");
2232   StackOption<bool> SC1Opt("sc1", cl::sub(SC1), cl::init(false));
2233   StackOption<bool> SC2Opt("sc2", cl::sub(SC2), cl::init(false));
2234   const char *args[] = {"prog"};
2235   EXPECT_TRUE(cl::ParseCommandLineOptions(std::size(args), args, StringRef(),
2236                                           &llvm::nulls()));
2237   auto Output = interceptStdout([]() { cl::PrintHelpMessage(); });
2238   EXPECT_NE(std::string::npos,
2239             Output.find("USAGE: prog [subcommand] [options]"))
2240       << Output;
2241   EXPECT_NE(std::string::npos, Output.find("SUBCOMMANDS:")) << Output;
2242   EXPECT_NE(std::string::npos, Output.find("sc1 - First Subcommand")) << Output;
2243   EXPECT_NE(std::string::npos, Output.find("sc2 - Second Subcommand"))
2244       << Output;
2245   cl::ResetCommandLineParser();
2246 }
2247 
2248 } // anonymous namespace
2249