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/ADT/Triple.h"
14 #include "llvm/Config/config.h"
15 #include "llvm/Support/Allocator.h"
16 #include "llvm/Support/FileSystem.h"
17 #include "llvm/Support/Host.h"
18 #include "llvm/Support/InitLLVM.h"
19 #include "llvm/Support/MemoryBuffer.h"
20 #include "llvm/Support/Path.h"
21 #include "llvm/Support/Program.h"
22 #include "llvm/Support/StringSaver.h"
23 #include "llvm/Support/VirtualFileSystem.h"
24 #include "llvm/Support/raw_ostream.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:
TempEnvVar(const char * name,const char * value)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 
~TempEnvVar()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>
StackOption(Ts &&...Ms)71   explicit StackOption(Ts &&... Ms) : Base(std::forward<Ts>(Ms)...) {}
72 
~StackOption()73   ~StackOption() override { this->removeArgument(); }
74 
operator =(const DT & V)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:
StackSubCommand(StringRef Name,StringRef Description=StringRef ())83   StackSubCommand(StringRef Name,
84                   StringRef Description = StringRef())
85       : SubCommand(Name, Description) {}
86 
StackSubCommand()87   StackSubCommand() : SubCommand() {}
88 
~StackSubCommand()89   ~StackSubCommand() { unregisterSubCommand(); }
90 };
91 
92 
93 cl::OptionCategory TestCategory("Test Options", "Description");
TEST(CommandLineTest,ModifyExisitingOption)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::TopLevelSubCommand);
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 
TEST(CommandLineTest,UseOptionCategory)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 
TEST(CommandLineTest,UseMultipleCategories)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 
testCommandLineTokenizer(ParserFunction * parse,StringRef Input,ArrayRef<const char * > Output,bool MarkEOLs=false)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 
TEST(CommandLineTest,TokenizeGNUCommandLine)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 
TEST(CommandLineTest,TokenizeWindowsCommandLine1)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 
TEST(CommandLineTest,TokenizeWindowsCommandLine2)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 
TEST(CommandLineTest,TokenizeWindowsCommandLineQuotedLastArgument)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 
TEST(CommandLineTest,TokenizeWindowsCommandLineExeName)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 
TEST(CommandLineTest,TokenizeAndMarkEOLs)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 
TEST(CommandLineTest,TokenizeConfigFile1)299 TEST(CommandLineTest, TokenizeConfigFile1) {
300   const char *Input = "\\";
301   const char *const Output[] = { "\\" };
302   testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output);
303 }
304 
TEST(CommandLineTest,TokenizeConfigFile2)305 TEST(CommandLineTest, TokenizeConfigFile2) {
306   const char *Input = "\\abc";
307   const char *const Output[] = { "abc" };
308   testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output);
309 }
310 
TEST(CommandLineTest,TokenizeConfigFile3)311 TEST(CommandLineTest, TokenizeConfigFile3) {
312   const char *Input = "abc\\";
313   const char *const Output[] = { "abc\\" };
314   testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output);
315 }
316 
TEST(CommandLineTest,TokenizeConfigFile4)317 TEST(CommandLineTest, TokenizeConfigFile4) {
318   const char *Input = "abc\\\n123";
319   const char *const Output[] = { "abc123" };
320   testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output);
321 }
322 
TEST(CommandLineTest,TokenizeConfigFile5)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 
TEST(CommandLineTest,TokenizeConfigFile6)329 TEST(CommandLineTest, TokenizeConfigFile6) {
330   const char *Input = "abc\\\n";
331   const char *const Output[] = { "abc" };
332   testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output);
333 }
334 
TEST(CommandLineTest,TokenizeConfigFile7)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 
TEST(CommandLineTest,TokenizeConfigFile8)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 
TEST(CommandLineTest,TokenizeConfigFile9)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 
TEST(CommandLineTest,TokenizeConfigFile10)357 TEST(CommandLineTest, TokenizeConfigFile10) {
358   const char *Input = "\\\nabc";
359   const char *const Output[] = { "abc" };
360   testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output);
361 }
362 
TEST(CommandLineTest,TokenizeConfigFile11)363 TEST(CommandLineTest, TokenizeConfigFile11) {
364   const char *Input = "\\\r\nabc";
365   const char *const Output[] = { "abc" };
366   testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output);
367 }
368 
TEST(CommandLineTest,AliasesWithArguments)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 = array_lengthof(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 
testAliasRequired(int argc,const char * const * argv)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 
TEST(CommandLineTest,AliasRequired)404 TEST(CommandLineTest, AliasRequired) {
405   const char *opts1[] = { "-tool", "-option=x" };
406   const char *opts2[] = { "-tool", "-o", "x" };
407   testAliasRequired(array_lengthof(opts1), opts1);
408   testAliasRequired(array_lengthof(opts2), opts2);
409 }
410 
TEST(CommandLineTest,HideUnrelatedOptions)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::TopLevelSubCommand);
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 
TEST(CommandLineTest,HideUnrelatedOptionsMulti)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(makeArrayRef(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::TopLevelSubCommand);
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 
TEST(CommandLineTest,SetMultiValues)455 TEST(CommandLineTest, SetMultiValues) {
456   StackOption<int> Option("option");
457   const char *args[] = {"prog", "-option=1", "-option=2"};
458   EXPECT_TRUE(cl::ParseCommandLineOptions(array_lengthof(args), args,
459                                           StringRef(), &llvm::nulls()));
460   EXPECT_EQ(Option, 2);
461 }
462 
TEST(CommandLineTest,SetValueInSubcategories)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 
TEST(CommandLineTest,LookupFailsInWrongSubCommand)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 
TEST(CommandLineTest,AddToAllSubCommands)528 TEST(CommandLineTest, AddToAllSubCommands) {
529   cl::ResetCommandLineParser();
530 
531   StackSubCommand SC1("sc1", "First subcommand");
532   StackOption<bool> AllOpt("everywhere", cl::sub(*cl::AllSubCommands),
533                            cl::init(false));
534   StackSubCommand SC2("sc2", "Second subcommand");
535 
536   const char *args[] = {"prog", "-everywhere"};
537   const char *args2[] = {"prog", "sc1", "-everywhere"};
538   const char *args3[] = {"prog", "sc2", "-everywhere"};
539 
540   std::string Errs;
541   raw_string_ostream OS(Errs);
542 
543   EXPECT_FALSE(AllOpt);
544   EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, StringRef(), &OS));
545   EXPECT_TRUE(AllOpt);
546 
547   AllOpt = false;
548 
549   cl::ResetAllOptionOccurrences();
550   EXPECT_FALSE(AllOpt);
551   EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, StringRef(), &OS));
552   EXPECT_TRUE(AllOpt);
553 
554   AllOpt = false;
555 
556   cl::ResetAllOptionOccurrences();
557   EXPECT_FALSE(AllOpt);
558   EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, StringRef(), &OS));
559   EXPECT_TRUE(AllOpt);
560 
561   // Since all parsing succeeded, the error message should be empty.
562   OS.flush();
563   EXPECT_TRUE(Errs.empty());
564 }
565 
TEST(CommandLineTest,ReparseCommandLineOptions)566 TEST(CommandLineTest, ReparseCommandLineOptions) {
567   cl::ResetCommandLineParser();
568 
569   StackOption<bool> TopLevelOpt("top-level", cl::sub(*cl::TopLevelSubCommand),
570                                 cl::init(false));
571 
572   const char *args[] = {"prog", "-top-level"};
573 
574   EXPECT_FALSE(TopLevelOpt);
575   EXPECT_TRUE(
576       cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
577   EXPECT_TRUE(TopLevelOpt);
578 
579   TopLevelOpt = false;
580 
581   cl::ResetAllOptionOccurrences();
582   EXPECT_FALSE(TopLevelOpt);
583   EXPECT_TRUE(
584       cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
585   EXPECT_TRUE(TopLevelOpt);
586 }
587 
TEST(CommandLineTest,RemoveFromRegularSubCommand)588 TEST(CommandLineTest, RemoveFromRegularSubCommand) {
589   cl::ResetCommandLineParser();
590 
591   StackSubCommand SC("sc", "Subcommand");
592   StackOption<bool> RemoveOption("remove-option", cl::sub(SC), cl::init(false));
593   StackOption<bool> KeepOption("keep-option", cl::sub(SC), cl::init(false));
594 
595   const char *args[] = {"prog", "sc", "-remove-option"};
596 
597   std::string Errs;
598   raw_string_ostream OS(Errs);
599 
600   EXPECT_FALSE(RemoveOption);
601   EXPECT_TRUE(cl::ParseCommandLineOptions(3, args, StringRef(), &OS));
602   EXPECT_TRUE(RemoveOption);
603   OS.flush();
604   EXPECT_TRUE(Errs.empty());
605 
606   RemoveOption.removeArgument();
607 
608   cl::ResetAllOptionOccurrences();
609   EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, StringRef(), &OS));
610   OS.flush();
611   EXPECT_FALSE(Errs.empty());
612 }
613 
TEST(CommandLineTest,RemoveFromTopLevelSubCommand)614 TEST(CommandLineTest, RemoveFromTopLevelSubCommand) {
615   cl::ResetCommandLineParser();
616 
617   StackOption<bool> TopLevelRemove(
618       "top-level-remove", cl::sub(*cl::TopLevelSubCommand), cl::init(false));
619   StackOption<bool> TopLevelKeep(
620       "top-level-keep", cl::sub(*cl::TopLevelSubCommand), cl::init(false));
621 
622   const char *args[] = {"prog", "-top-level-remove"};
623 
624   EXPECT_FALSE(TopLevelRemove);
625   EXPECT_TRUE(
626       cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
627   EXPECT_TRUE(TopLevelRemove);
628 
629   TopLevelRemove.removeArgument();
630 
631   cl::ResetAllOptionOccurrences();
632   EXPECT_FALSE(
633       cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
634 }
635 
TEST(CommandLineTest,RemoveFromAllSubCommands)636 TEST(CommandLineTest, RemoveFromAllSubCommands) {
637   cl::ResetCommandLineParser();
638 
639   StackSubCommand SC1("sc1", "First Subcommand");
640   StackSubCommand SC2("sc2", "Second Subcommand");
641   StackOption<bool> RemoveOption("remove-option", cl::sub(*cl::AllSubCommands),
642                                  cl::init(false));
643   StackOption<bool> KeepOption("keep-option", cl::sub(*cl::AllSubCommands),
644                                cl::init(false));
645 
646   const char *args0[] = {"prog", "-remove-option"};
647   const char *args1[] = {"prog", "sc1", "-remove-option"};
648   const char *args2[] = {"prog", "sc2", "-remove-option"};
649 
650   // It should work for all subcommands including the top-level.
651   EXPECT_FALSE(RemoveOption);
652   EXPECT_TRUE(
653       cl::ParseCommandLineOptions(2, args0, StringRef(), &llvm::nulls()));
654   EXPECT_TRUE(RemoveOption);
655 
656   RemoveOption = false;
657 
658   cl::ResetAllOptionOccurrences();
659   EXPECT_FALSE(RemoveOption);
660   EXPECT_TRUE(
661       cl::ParseCommandLineOptions(3, args1, StringRef(), &llvm::nulls()));
662   EXPECT_TRUE(RemoveOption);
663 
664   RemoveOption = false;
665 
666   cl::ResetAllOptionOccurrences();
667   EXPECT_FALSE(RemoveOption);
668   EXPECT_TRUE(
669       cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
670   EXPECT_TRUE(RemoveOption);
671 
672   RemoveOption.removeArgument();
673 
674   // It should not work for any subcommands including the top-level.
675   cl::ResetAllOptionOccurrences();
676   EXPECT_FALSE(
677       cl::ParseCommandLineOptions(2, args0, StringRef(), &llvm::nulls()));
678   cl::ResetAllOptionOccurrences();
679   EXPECT_FALSE(
680       cl::ParseCommandLineOptions(3, args1, StringRef(), &llvm::nulls()));
681   cl::ResetAllOptionOccurrences();
682   EXPECT_FALSE(
683       cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
684 }
685 
TEST(CommandLineTest,GetRegisteredSubcommands)686 TEST(CommandLineTest, GetRegisteredSubcommands) {
687   cl::ResetCommandLineParser();
688 
689   StackSubCommand SC1("sc1", "First Subcommand");
690   StackOption<bool> Opt1("opt1", cl::sub(SC1), cl::init(false));
691   StackSubCommand SC2("sc2", "Second subcommand");
692   StackOption<bool> Opt2("opt2", cl::sub(SC2), cl::init(false));
693 
694   const char *args0[] = {"prog", "sc1"};
695   const char *args1[] = {"prog", "sc2"};
696 
697   EXPECT_TRUE(
698       cl::ParseCommandLineOptions(2, args0, StringRef(), &llvm::nulls()));
699   EXPECT_FALSE(Opt1);
700   EXPECT_FALSE(Opt2);
701   for (auto *S : cl::getRegisteredSubcommands()) {
702     if (*S) {
703       EXPECT_EQ("sc1", S->getName());
704     }
705   }
706 
707   cl::ResetAllOptionOccurrences();
708   EXPECT_TRUE(
709       cl::ParseCommandLineOptions(2, args1, StringRef(), &llvm::nulls()));
710   EXPECT_FALSE(Opt1);
711   EXPECT_FALSE(Opt2);
712   for (auto *S : cl::getRegisteredSubcommands()) {
713     if (*S) {
714       EXPECT_EQ("sc2", S->getName());
715     }
716   }
717 }
718 
TEST(CommandLineTest,DefaultOptions)719 TEST(CommandLineTest, DefaultOptions) {
720   cl::ResetCommandLineParser();
721 
722   StackOption<std::string> Bar("bar", cl::sub(*cl::AllSubCommands),
723                                cl::DefaultOption);
724   StackOption<std::string, cl::alias> Bar_Alias(
725       "b", cl::desc("Alias for -bar"), cl::aliasopt(Bar), cl::DefaultOption);
726 
727   StackOption<bool> Foo("foo", cl::init(false), cl::sub(*cl::AllSubCommands),
728                         cl::DefaultOption);
729   StackOption<bool, cl::alias> Foo_Alias("f", cl::desc("Alias for -foo"),
730                                          cl::aliasopt(Foo), cl::DefaultOption);
731 
732   StackSubCommand SC1("sc1", "First Subcommand");
733   // Override "-b" and change type in sc1 SubCommand.
734   StackOption<bool> SC1_B("b", cl::sub(SC1), cl::init(false));
735   StackSubCommand SC2("sc2", "Second subcommand");
736   // Override "-foo" and change type in sc2 SubCommand.  Note that this does not
737   // affect "-f" alias, which continues to work correctly.
738   StackOption<std::string> SC2_Foo("foo", cl::sub(SC2));
739 
740   const char *args0[] = {"prog", "-b", "args0 bar string", "-f"};
741   EXPECT_TRUE(cl::ParseCommandLineOptions(sizeof(args0) / sizeof(char *), args0,
742                                           StringRef(), &llvm::nulls()));
743   EXPECT_EQ(Bar, "args0 bar string");
744   EXPECT_TRUE(Foo);
745   EXPECT_FALSE(SC1_B);
746   EXPECT_TRUE(SC2_Foo.empty());
747 
748   cl::ResetAllOptionOccurrences();
749 
750   const char *args1[] = {"prog", "sc1", "-b", "-bar", "args1 bar string", "-f"};
751   EXPECT_TRUE(cl::ParseCommandLineOptions(sizeof(args1) / sizeof(char *), args1,
752                                           StringRef(), &llvm::nulls()));
753   EXPECT_EQ(Bar, "args1 bar string");
754   EXPECT_TRUE(Foo);
755   EXPECT_TRUE(SC1_B);
756   EXPECT_TRUE(SC2_Foo.empty());
757   for (auto *S : cl::getRegisteredSubcommands()) {
758     if (*S) {
759       EXPECT_EQ("sc1", S->getName());
760     }
761   }
762 
763   cl::ResetAllOptionOccurrences();
764 
765   const char *args2[] = {"prog", "sc2", "-b", "args2 bar string",
766                          "-f", "-foo", "foo string"};
767   EXPECT_TRUE(cl::ParseCommandLineOptions(sizeof(args2) / sizeof(char *), args2,
768                                           StringRef(), &llvm::nulls()));
769   EXPECT_EQ(Bar, "args2 bar string");
770   EXPECT_TRUE(Foo);
771   EXPECT_FALSE(SC1_B);
772   EXPECT_EQ(SC2_Foo, "foo string");
773   for (auto *S : cl::getRegisteredSubcommands()) {
774     if (*S) {
775       EXPECT_EQ("sc2", S->getName());
776     }
777   }
778   cl::ResetCommandLineParser();
779 }
780 
TEST(CommandLineTest,ArgumentLimit)781 TEST(CommandLineTest, ArgumentLimit) {
782   std::string args(32 * 4096, 'a');
783   EXPECT_FALSE(llvm::sys::commandLineFitsWithinSystemLimits("cl", args.data()));
784   std::string args2(256, 'a');
785   EXPECT_TRUE(llvm::sys::commandLineFitsWithinSystemLimits("cl", args2.data()));
786 }
787 
TEST(CommandLineTest,ArgumentLimitWindows)788 TEST(CommandLineTest, ArgumentLimitWindows) {
789   if (!Triple(sys::getProcessTriple()).isOSWindows())
790     GTEST_SKIP();
791   // We use 32000 as a limit for command line length. Program name ('cl'),
792   // separating spaces and termination null character occupy 5 symbols.
793   std::string long_arg(32000 - 5, 'b');
794   EXPECT_TRUE(
795       llvm::sys::commandLineFitsWithinSystemLimits("cl", long_arg.data()));
796   long_arg += 'b';
797   EXPECT_FALSE(
798       llvm::sys::commandLineFitsWithinSystemLimits("cl", long_arg.data()));
799 }
800 
TEST(CommandLineTest,ResponseFileWindows)801 TEST(CommandLineTest, ResponseFileWindows) {
802   if (!Triple(sys::getProcessTriple()).isOSWindows())
803     GTEST_SKIP();
804 
805   StackOption<std::string, cl::list<std::string>> InputFilenames(
806       cl::Positional, cl::desc("<input files>"));
807   StackOption<bool> TopLevelOpt("top-level", cl::init(false));
808 
809   // Create response file.
810   TempFile ResponseFile("resp-", ".txt",
811                         "-top-level\npath\\dir\\file1\npath/dir/file2",
812                         /*Unique*/ true);
813 
814   llvm::SmallString<128> RspOpt;
815   RspOpt.append(1, '@');
816   RspOpt.append(ResponseFile.path());
817   const char *args[] = {"prog", RspOpt.c_str()};
818   EXPECT_FALSE(TopLevelOpt);
819   EXPECT_TRUE(
820       cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
821   EXPECT_TRUE(TopLevelOpt);
822   EXPECT_EQ(InputFilenames[0], "path\\dir\\file1");
823   EXPECT_EQ(InputFilenames[1], "path/dir/file2");
824 }
825 
TEST(CommandLineTest,ResponseFiles)826 TEST(CommandLineTest, ResponseFiles) {
827   vfs::InMemoryFileSystem FS;
828 #ifdef _WIN32
829   const char *TestRoot = "C:\\";
830 #else
831   const char *TestRoot = "/";
832 #endif
833   FS.setCurrentWorkingDirectory(TestRoot);
834 
835   // Create included response file of first level.
836   llvm::StringRef IncludedFileName = "resp1";
837   FS.addFile(IncludedFileName, 0,
838              llvm::MemoryBuffer::getMemBuffer("-option_1 -option_2\n"
839                                               "@incdir/resp2\n"
840                                               "-option_3=abcd\n"
841                                               "@incdir/resp3\n"
842                                               "-option_4=efjk\n"));
843 
844   // Directory for included file.
845   llvm::StringRef IncDir = "incdir";
846 
847   // Create included response file of second level.
848   llvm::SmallString<128> IncludedFileName2;
849   llvm::sys::path::append(IncludedFileName2, IncDir, "resp2");
850   FS.addFile(IncludedFileName2, 0,
851              MemoryBuffer::getMemBuffer("-option_21 -option_22\n"
852                                         "-option_23=abcd\n"));
853 
854   // Create second included response file of second level.
855   llvm::SmallString<128> IncludedFileName3;
856   llvm::sys::path::append(IncludedFileName3, IncDir, "resp3");
857   FS.addFile(IncludedFileName3, 0,
858              MemoryBuffer::getMemBuffer("-option_31 -option_32\n"
859                                         "-option_33=abcd\n"));
860 
861   // Prepare 'file' with reference to response file.
862   SmallString<128> IncRef;
863   IncRef.append(1, '@');
864   IncRef.append(IncludedFileName);
865   llvm::SmallVector<const char *, 4> Argv = {"test/test", "-flag_1",
866                                              IncRef.c_str(), "-flag_2"};
867 
868   // Expand response files.
869   llvm::BumpPtrAllocator A;
870   llvm::StringSaver Saver(A);
871   ASSERT_TRUE(llvm::cl::ExpandResponseFiles(
872       Saver, llvm::cl::TokenizeGNUCommandLine, Argv, false, true, false,
873       /*CurrentDir=*/StringRef(TestRoot), FS));
874   EXPECT_THAT(Argv, testing::Pointwise(
875                         StringEquality(),
876                         {"test/test", "-flag_1", "-option_1", "-option_2",
877                          "-option_21", "-option_22", "-option_23=abcd",
878                          "-option_3=abcd", "-option_31", "-option_32",
879                          "-option_33=abcd", "-option_4=efjk", "-flag_2"}));
880 }
881 
TEST(CommandLineTest,RecursiveResponseFiles)882 TEST(CommandLineTest, RecursiveResponseFiles) {
883   vfs::InMemoryFileSystem FS;
884 #ifdef _WIN32
885   const char *TestRoot = "C:\\";
886 #else
887   const char *TestRoot = "/";
888 #endif
889   FS.setCurrentWorkingDirectory(TestRoot);
890 
891   StringRef SelfFilePath = "self.rsp";
892   std::string SelfFileRef = ("@" + SelfFilePath).str();
893 
894   StringRef NestedFilePath = "nested.rsp";
895   std::string NestedFileRef = ("@" + NestedFilePath).str();
896 
897   StringRef FlagFilePath = "flag.rsp";
898   std::string FlagFileRef = ("@" + FlagFilePath).str();
899 
900   std::string SelfFileContents;
901   raw_string_ostream SelfFile(SelfFileContents);
902   SelfFile << "-option_1\n";
903   SelfFile << FlagFileRef << "\n";
904   SelfFile << NestedFileRef << "\n";
905   SelfFile << SelfFileRef << "\n";
906   FS.addFile(SelfFilePath, 0, MemoryBuffer::getMemBuffer(SelfFile.str()));
907 
908   std::string NestedFileContents;
909   raw_string_ostream NestedFile(NestedFileContents);
910   NestedFile << "-option_2\n";
911   NestedFile << FlagFileRef << "\n";
912   NestedFile << SelfFileRef << "\n";
913   NestedFile << NestedFileRef << "\n";
914   FS.addFile(NestedFilePath, 0, MemoryBuffer::getMemBuffer(NestedFile.str()));
915 
916   std::string FlagFileContents;
917   raw_string_ostream FlagFile(FlagFileContents);
918   FlagFile << "-option_x\n";
919   FS.addFile(FlagFilePath, 0, MemoryBuffer::getMemBuffer(FlagFile.str()));
920 
921   // Ensure:
922   // Recursive expansion terminates
923   // Recursive files never expand
924   // Non-recursive repeats are allowed
925   SmallVector<const char *, 4> Argv = {"test/test", SelfFileRef.c_str(),
926                                        "-option_3"};
927   BumpPtrAllocator A;
928   StringSaver Saver(A);
929 #ifdef _WIN32
930   cl::TokenizerCallback Tokenizer = cl::TokenizeWindowsCommandLine;
931 #else
932   cl::TokenizerCallback Tokenizer = cl::TokenizeGNUCommandLine;
933 #endif
934   ASSERT_FALSE(
935       cl::ExpandResponseFiles(Saver, Tokenizer, Argv, false, false, false,
936                               /*CurrentDir=*/llvm::StringRef(TestRoot), FS));
937 
938   EXPECT_THAT(Argv,
939               testing::Pointwise(StringEquality(),
940                                  {"test/test", "-option_1", "-option_x",
941                                   "-option_2", "-option_x", SelfFileRef.c_str(),
942                                   NestedFileRef.c_str(), SelfFileRef.c_str(),
943                                   "-option_3"}));
944 }
945 
TEST(CommandLineTest,ResponseFilesAtArguments)946 TEST(CommandLineTest, ResponseFilesAtArguments) {
947   vfs::InMemoryFileSystem FS;
948 #ifdef _WIN32
949   const char *TestRoot = "C:\\";
950 #else
951   const char *TestRoot = "/";
952 #endif
953   FS.setCurrentWorkingDirectory(TestRoot);
954 
955   StringRef ResponseFilePath = "test.rsp";
956 
957   std::string ResponseFileContents;
958   raw_string_ostream ResponseFile(ResponseFileContents);
959   ResponseFile << "-foo" << "\n";
960   ResponseFile << "-bar" << "\n";
961   FS.addFile(ResponseFilePath, 0,
962              MemoryBuffer::getMemBuffer(ResponseFile.str()));
963 
964   // Ensure we expand rsp files after lots of non-rsp arguments starting with @.
965   constexpr size_t NON_RSP_AT_ARGS = 64;
966   SmallVector<const char *, 4> Argv = {"test/test"};
967   Argv.append(NON_RSP_AT_ARGS, "@non_rsp_at_arg");
968   std::string ResponseFileRef = ("@" + ResponseFilePath).str();
969   Argv.push_back(ResponseFileRef.c_str());
970 
971   BumpPtrAllocator A;
972   StringSaver Saver(A);
973   ASSERT_FALSE(cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Argv,
974                                        false, false, false,
975                                        /*CurrentDir=*/StringRef(TestRoot), FS));
976 
977   // ASSERT instead of EXPECT to prevent potential out-of-bounds access.
978   ASSERT_EQ(Argv.size(), 1 + NON_RSP_AT_ARGS + 2);
979   size_t i = 0;
980   EXPECT_STREQ(Argv[i++], "test/test");
981   for (; i < 1 + NON_RSP_AT_ARGS; ++i)
982     EXPECT_STREQ(Argv[i], "@non_rsp_at_arg");
983   EXPECT_STREQ(Argv[i++], "-foo");
984   EXPECT_STREQ(Argv[i++], "-bar");
985 }
986 
TEST(CommandLineTest,ResponseFileRelativePath)987 TEST(CommandLineTest, ResponseFileRelativePath) {
988   vfs::InMemoryFileSystem FS;
989 #ifdef _WIN32
990   const char *TestRoot = "C:\\";
991 #else
992   const char *TestRoot = "//net";
993 #endif
994   FS.setCurrentWorkingDirectory(TestRoot);
995 
996   StringRef OuterFile = "dir/outer.rsp";
997   StringRef OuterFileContents = "@inner.rsp";
998   FS.addFile(OuterFile, 0, MemoryBuffer::getMemBuffer(OuterFileContents));
999 
1000   StringRef InnerFile = "dir/inner.rsp";
1001   StringRef InnerFileContents = "-flag";
1002   FS.addFile(InnerFile, 0, MemoryBuffer::getMemBuffer(InnerFileContents));
1003 
1004   SmallVector<const char *, 2> Argv = {"test/test", "@dir/outer.rsp"};
1005 
1006   BumpPtrAllocator A;
1007   StringSaver Saver(A);
1008   ASSERT_TRUE(cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Argv,
1009                                       false, true, false,
1010                                       /*CurrentDir=*/StringRef(TestRoot), FS));
1011   EXPECT_THAT(Argv,
1012               testing::Pointwise(StringEquality(), {"test/test", "-flag"}));
1013 }
1014 
TEST(CommandLineTest,ResponseFileEOLs)1015 TEST(CommandLineTest, ResponseFileEOLs) {
1016   vfs::InMemoryFileSystem FS;
1017 #ifdef _WIN32
1018   const char *TestRoot = "C:\\";
1019 #else
1020   const char *TestRoot = "//net";
1021 #endif
1022   FS.setCurrentWorkingDirectory(TestRoot);
1023   FS.addFile("eols.rsp", 0,
1024              MemoryBuffer::getMemBuffer("-Xclang -Wno-whatever\n input.cpp"));
1025   SmallVector<const char *, 2> Argv = {"clang", "@eols.rsp"};
1026   BumpPtrAllocator A;
1027   StringSaver Saver(A);
1028   ASSERT_TRUE(cl::ExpandResponseFiles(Saver, cl::TokenizeWindowsCommandLine,
1029                                       Argv, true, true, false,
1030                                       /*CurrentDir=*/StringRef(TestRoot), FS));
1031   const char *Expected[] = {"clang", "-Xclang", "-Wno-whatever", nullptr,
1032                             "input.cpp"};
1033   ASSERT_EQ(array_lengthof(Expected), Argv.size());
1034   for (size_t I = 0, E = array_lengthof(Expected); I < E; ++I) {
1035     if (Expected[I] == nullptr) {
1036       ASSERT_EQ(Argv[I], nullptr);
1037     } else {
1038       ASSERT_STREQ(Expected[I], Argv[I]);
1039     }
1040   }
1041 }
1042 
TEST(CommandLineTest,SetDefautValue)1043 TEST(CommandLineTest, SetDefautValue) {
1044   cl::ResetCommandLineParser();
1045 
1046   StackOption<std::string> Opt1("opt1", cl::init("true"));
1047   StackOption<bool> Opt2("opt2", cl::init(true));
1048   cl::alias Alias("alias", llvm::cl::aliasopt(Opt2));
1049   StackOption<int> Opt3("opt3", cl::init(3));
1050 
1051   const char *args[] = {"prog", "-opt1=false", "-opt2", "-opt3"};
1052 
1053   EXPECT_TRUE(
1054     cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
1055 
1056   EXPECT_EQ(Opt1, "false");
1057   EXPECT_TRUE(Opt2);
1058   EXPECT_EQ(Opt3, 3);
1059 
1060   Opt2 = false;
1061   Opt3 = 1;
1062 
1063   cl::ResetAllOptionOccurrences();
1064 
1065   for (auto &OM : cl::getRegisteredOptions(*cl::TopLevelSubCommand)) {
1066     cl::Option *O = OM.second;
1067     if (O->ArgStr == "opt2") {
1068       continue;
1069     }
1070     O->setDefault();
1071   }
1072 
1073   EXPECT_EQ(Opt1, "true");
1074   EXPECT_TRUE(Opt2);
1075   EXPECT_EQ(Opt3, 3);
1076   Alias.removeArgument();
1077 }
1078 
TEST(CommandLineTest,ReadConfigFile)1079 TEST(CommandLineTest, ReadConfigFile) {
1080   llvm::SmallVector<const char *, 1> Argv;
1081 
1082   TempDir TestDir("unittest", /*Unique*/ true);
1083   TempDir TestSubDir(TestDir.path("subdir"), /*Unique*/ false);
1084 
1085   llvm::SmallString<128> TestCfg = TestDir.path("foo");
1086   TempFile ConfigFile(TestCfg, "",
1087                       "# Comment\n"
1088                       "-option_1\n"
1089                       "-option_2=<CFGDIR>/dir1\n"
1090                       "-option_3=<CFGDIR>\n"
1091                       "-option_4 <CFGDIR>\n"
1092                       "-option_5=<CFG\\\n"
1093                       "DIR>\n"
1094                       "-option_6=<CFGDIR>/dir1,<CFGDIR>/dir2\n"
1095                       "@subconfig\n"
1096                       "-option_11=abcd\n"
1097                       "-option_12=\\\n"
1098                       "cdef\n");
1099 
1100   llvm::SmallString<128> TestCfg2 = TestDir.path("subconfig");
1101   TempFile ConfigFile2(TestCfg2, "",
1102                        "-option_7\n"
1103                        "-option_8=<CFGDIR>/dir2\n"
1104                        "@subdir/subfoo\n"
1105                        "\n"
1106                        "   # comment\n");
1107 
1108   llvm::SmallString<128> TestCfg3 = TestSubDir.path("subfoo");
1109   TempFile ConfigFile3(TestCfg3, "",
1110                        "-option_9=<CFGDIR>/dir3\n"
1111                        "@<CFGDIR>/subfoo2\n");
1112 
1113   llvm::SmallString<128> TestCfg4 = TestSubDir.path("subfoo2");
1114   TempFile ConfigFile4(TestCfg4, "", "-option_10\n");
1115 
1116   // Make sure the current directory is not the directory where config files
1117   // resides. In this case the code that expands response files will not find
1118   // 'subconfig' unless it resolves nested inclusions relative to the including
1119   // file.
1120   llvm::SmallString<128> CurrDir;
1121   std::error_code EC = llvm::sys::fs::current_path(CurrDir);
1122   EXPECT_TRUE(!EC);
1123   EXPECT_NE(CurrDir.str(), TestDir.path());
1124 
1125   llvm::BumpPtrAllocator A;
1126   llvm::StringSaver Saver(A);
1127   bool Result = llvm::cl::readConfigFile(ConfigFile.path(), Saver, Argv);
1128 
1129   EXPECT_TRUE(Result);
1130   EXPECT_EQ(Argv.size(), 13U);
1131   EXPECT_STREQ(Argv[0], "-option_1");
1132   EXPECT_STREQ(Argv[1],
1133                ("-option_2=" + TestDir.path() + "/dir1").str().c_str());
1134   EXPECT_STREQ(Argv[2], ("-option_3=" + TestDir.path()).str().c_str());
1135   EXPECT_STREQ(Argv[3], "-option_4");
1136   EXPECT_STREQ(Argv[4], TestDir.path().str().c_str());
1137   EXPECT_STREQ(Argv[5], ("-option_5=" + TestDir.path()).str().c_str());
1138   EXPECT_STREQ(Argv[6], ("-option_6=" + TestDir.path() + "/dir1," +
1139                          TestDir.path() + "/dir2")
1140                             .str()
1141                             .c_str());
1142   EXPECT_STREQ(Argv[7], "-option_7");
1143   EXPECT_STREQ(Argv[8],
1144                ("-option_8=" + TestDir.path() + "/dir2").str().c_str());
1145   EXPECT_STREQ(Argv[9],
1146                ("-option_9=" + TestSubDir.path() + "/dir3").str().c_str());
1147   EXPECT_STREQ(Argv[10], "-option_10");
1148   EXPECT_STREQ(Argv[11], "-option_11=abcd");
1149   EXPECT_STREQ(Argv[12], "-option_12=cdef");
1150 }
1151 
TEST(CommandLineTest,PositionalEatArgsError)1152 TEST(CommandLineTest, PositionalEatArgsError) {
1153   cl::ResetCommandLineParser();
1154 
1155   StackOption<std::string, cl::list<std::string>> PosEatArgs(
1156       "positional-eat-args", cl::Positional, cl::desc("<arguments>..."),
1157       cl::PositionalEatsArgs);
1158   StackOption<std::string, cl::list<std::string>> PosEatArgs2(
1159       "positional-eat-args2", cl::Positional, cl::desc("Some strings"),
1160       cl::PositionalEatsArgs);
1161 
1162   const char *args[] = {"prog", "-positional-eat-args=XXXX"};
1163   const char *args2[] = {"prog", "-positional-eat-args=XXXX", "-foo"};
1164   const char *args3[] = {"prog", "-positional-eat-args", "-foo"};
1165   const char *args4[] = {"prog", "-positional-eat-args",
1166                          "-foo", "-positional-eat-args2",
1167                          "-bar", "foo"};
1168 
1169   std::string Errs;
1170   raw_string_ostream OS(Errs);
1171   EXPECT_FALSE(cl::ParseCommandLineOptions(2, args, StringRef(), &OS)); OS.flush();
1172   EXPECT_FALSE(Errs.empty()); Errs.clear();
1173   EXPECT_FALSE(cl::ParseCommandLineOptions(3, args2, StringRef(), &OS)); OS.flush();
1174   EXPECT_FALSE(Errs.empty()); Errs.clear();
1175   EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, StringRef(), &OS)); OS.flush();
1176   EXPECT_TRUE(Errs.empty()); Errs.clear();
1177 
1178   cl::ResetAllOptionOccurrences();
1179   EXPECT_TRUE(cl::ParseCommandLineOptions(6, args4, StringRef(), &OS)); OS.flush();
1180   EXPECT_EQ(PosEatArgs.size(), 1u);
1181   EXPECT_EQ(PosEatArgs2.size(), 2u);
1182   EXPECT_TRUE(Errs.empty());
1183 }
1184 
1185 #ifdef _WIN32
checkSeparators(StringRef Path)1186 void checkSeparators(StringRef Path) {
1187   char UndesiredSeparator = sys::path::get_separator()[0] == '/' ? '\\' : '/';
1188   ASSERT_EQ(Path.find(UndesiredSeparator), StringRef::npos);
1189 }
1190 
TEST(CommandLineTest,GetCommandLineArguments)1191 TEST(CommandLineTest, GetCommandLineArguments) {
1192   int argc = __argc;
1193   char **argv = __argv;
1194 
1195   // GetCommandLineArguments is called in InitLLVM.
1196   llvm::InitLLVM X(argc, argv);
1197 
1198   EXPECT_EQ(llvm::sys::path::is_absolute(argv[0]),
1199             llvm::sys::path::is_absolute(__argv[0]));
1200   checkSeparators(argv[0]);
1201 
1202   EXPECT_TRUE(
1203       llvm::sys::path::filename(argv[0]).equals_insensitive("supporttests.exe"))
1204       << "Filename of test executable is "
1205       << llvm::sys::path::filename(argv[0]);
1206 }
1207 #endif
1208 
1209 class OutputRedirector {
1210 public:
OutputRedirector(int RedirectFD)1211   OutputRedirector(int RedirectFD)
1212       : RedirectFD(RedirectFD), OldFD(dup(RedirectFD)) {
1213     if (OldFD == -1 ||
1214         sys::fs::createTemporaryFile("unittest-redirect", "", NewFD,
1215                                      FilePath) ||
1216         dup2(NewFD, RedirectFD) == -1)
1217       Valid = false;
1218   }
1219 
~OutputRedirector()1220   ~OutputRedirector() {
1221     dup2(OldFD, RedirectFD);
1222     close(OldFD);
1223     close(NewFD);
1224   }
1225 
1226   SmallVector<char, 128> FilePath;
1227   bool Valid = true;
1228 
1229 private:
1230   int RedirectFD;
1231   int OldFD;
1232   int NewFD;
1233 };
1234 
1235 struct AutoDeleteFile {
1236   SmallVector<char, 128> FilePath;
~AutoDeleteFile__anon6509acef0111::AutoDeleteFile1237   ~AutoDeleteFile() {
1238     if (!FilePath.empty())
1239       sys::fs::remove(std::string(FilePath.data(), FilePath.size()));
1240   }
1241 };
1242 
1243 class PrintOptionInfoTest : public ::testing::Test {
1244 public:
1245   // Return std::string because the output of a failing EXPECT check is
1246   // unreadable for StringRef. It also avoids any lifetime issues.
runTest(Ts...OptionAttributes)1247   template <typename... Ts> std::string runTest(Ts... OptionAttributes) {
1248     outs().flush();  // flush any output from previous tests
1249     AutoDeleteFile File;
1250     {
1251       OutputRedirector Stdout(fileno(stdout));
1252       if (!Stdout.Valid)
1253         return "";
1254       File.FilePath = Stdout.FilePath;
1255 
1256       StackOption<OptionValue> TestOption(Opt, cl::desc(HelpText),
1257                                           OptionAttributes...);
1258       printOptionInfo(TestOption, 26);
1259       outs().flush();
1260     }
1261     auto Buffer = MemoryBuffer::getFile(File.FilePath);
1262     if (!Buffer)
1263       return "";
1264     return Buffer->get()->getBuffer().str();
1265   }
1266 
1267   enum class OptionValue { Val };
1268   const StringRef Opt = "some-option";
1269   const StringRef HelpText = "some help";
1270 
1271 private:
1272   // This is a workaround for cl::Option sub-classes having their
1273   // printOptionInfo functions private.
printOptionInfo(const cl::Option & O,size_t Width)1274   void printOptionInfo(const cl::Option &O, size_t Width) {
1275     O.printOptionInfo(Width);
1276   }
1277 };
1278 
TEST_F(PrintOptionInfoTest,PrintOptionInfoValueOptionalWithoutSentinel)1279 TEST_F(PrintOptionInfoTest, PrintOptionInfoValueOptionalWithoutSentinel) {
1280   std::string Output =
1281       runTest(cl::ValueOptional,
1282               cl::values(clEnumValN(OptionValue::Val, "v1", "desc1")));
1283 
1284   // clang-format off
1285   EXPECT_EQ(Output, ("  --" + Opt + "=<value> - " + HelpText + "\n"
1286                      "    =v1                 -   desc1\n")
1287                         .str());
1288   // clang-format on
1289 }
1290 
TEST_F(PrintOptionInfoTest,PrintOptionInfoValueOptionalWithSentinel)1291 TEST_F(PrintOptionInfoTest, PrintOptionInfoValueOptionalWithSentinel) {
1292   std::string Output = runTest(
1293       cl::ValueOptional, cl::values(clEnumValN(OptionValue::Val, "v1", "desc1"),
1294                                     clEnumValN(OptionValue::Val, "", "")));
1295 
1296   // clang-format off
1297   EXPECT_EQ(Output,
1298             ("  --" + Opt + "         - " + HelpText + "\n"
1299              "  --" + Opt + "=<value> - " + HelpText + "\n"
1300              "    =v1                 -   desc1\n")
1301                 .str());
1302   // clang-format on
1303 }
1304 
TEST_F(PrintOptionInfoTest,PrintOptionInfoValueOptionalWithSentinelWithHelp)1305 TEST_F(PrintOptionInfoTest, PrintOptionInfoValueOptionalWithSentinelWithHelp) {
1306   std::string Output = runTest(
1307       cl::ValueOptional, cl::values(clEnumValN(OptionValue::Val, "v1", "desc1"),
1308                                     clEnumValN(OptionValue::Val, "", "desc2")));
1309 
1310   // clang-format off
1311   EXPECT_EQ(Output, ("  --" + Opt + "         - " + HelpText + "\n"
1312                      "  --" + Opt + "=<value> - " + HelpText + "\n"
1313                      "    =v1                 -   desc1\n"
1314                      "    =<empty>            -   desc2\n")
1315                         .str());
1316   // clang-format on
1317 }
1318 
TEST_F(PrintOptionInfoTest,PrintOptionInfoValueRequiredWithEmptyValueName)1319 TEST_F(PrintOptionInfoTest, PrintOptionInfoValueRequiredWithEmptyValueName) {
1320   std::string Output = runTest(
1321       cl::ValueRequired, cl::values(clEnumValN(OptionValue::Val, "v1", "desc1"),
1322                                     clEnumValN(OptionValue::Val, "", "")));
1323 
1324   // clang-format off
1325   EXPECT_EQ(Output, ("  --" + Opt + "=<value> - " + HelpText + "\n"
1326                      "    =v1                 -   desc1\n"
1327                      "    =<empty>\n")
1328                         .str());
1329   // clang-format on
1330 }
1331 
TEST_F(PrintOptionInfoTest,PrintOptionInfoEmptyValueDescription)1332 TEST_F(PrintOptionInfoTest, PrintOptionInfoEmptyValueDescription) {
1333   std::string Output = runTest(
1334       cl::ValueRequired, cl::values(clEnumValN(OptionValue::Val, "v1", "")));
1335 
1336   // clang-format off
1337   EXPECT_EQ(Output,
1338             ("  --" + Opt + "=<value> - " + HelpText + "\n"
1339              "    =v1\n").str());
1340   // clang-format on
1341 }
1342 
TEST_F(PrintOptionInfoTest,PrintOptionInfoMultilineValueDescription)1343 TEST_F(PrintOptionInfoTest, PrintOptionInfoMultilineValueDescription) {
1344   std::string Output =
1345       runTest(cl::ValueRequired,
1346               cl::values(clEnumValN(OptionValue::Val, "v1",
1347                                     "This is the first enum value\n"
1348                                     "which has a really long description\n"
1349                                     "thus it is multi-line."),
1350                          clEnumValN(OptionValue::Val, "",
1351                                     "This is an unnamed enum value option\n"
1352                                     "Should be indented as well")));
1353 
1354   // clang-format off
1355   EXPECT_EQ(Output,
1356             ("  --" + Opt + "=<value> - " + HelpText + "\n"
1357              "    =v1                 -   This is the first enum value\n"
1358              "                            which has a really long description\n"
1359              "                            thus it is multi-line.\n"
1360              "    =<empty>            -   This is an unnamed enum value option\n"
1361              "                            Should be indented as well\n").str());
1362   // clang-format on
1363 }
1364 
1365 class GetOptionWidthTest : public ::testing::Test {
1366 public:
1367   enum class OptionValue { Val };
1368 
1369   template <typename... Ts>
runTest(StringRef ArgName,Ts...OptionAttributes)1370   size_t runTest(StringRef ArgName, Ts... OptionAttributes) {
1371     StackOption<OptionValue> TestOption(ArgName, cl::desc("some help"),
1372                                         OptionAttributes...);
1373     return getOptionWidth(TestOption);
1374   }
1375 
1376 private:
1377   // This is a workaround for cl::Option sub-classes having their
1378   // printOptionInfo
1379   // functions private.
getOptionWidth(const cl::Option & O)1380   size_t getOptionWidth(const cl::Option &O) { return O.getOptionWidth(); }
1381 };
1382 
TEST_F(GetOptionWidthTest,GetOptionWidthArgNameLonger)1383 TEST_F(GetOptionWidthTest, GetOptionWidthArgNameLonger) {
1384   StringRef ArgName("a-long-argument-name");
1385   size_t ExpectedStrSize = ("  --" + ArgName + "=<value> - ").str().size();
1386   EXPECT_EQ(
1387       runTest(ArgName, cl::values(clEnumValN(OptionValue::Val, "v", "help"))),
1388       ExpectedStrSize);
1389 }
1390 
TEST_F(GetOptionWidthTest,GetOptionWidthFirstOptionNameLonger)1391 TEST_F(GetOptionWidthTest, GetOptionWidthFirstOptionNameLonger) {
1392   StringRef OptName("a-long-option-name");
1393   size_t ExpectedStrSize = ("    =" + OptName + " - ").str().size();
1394   EXPECT_EQ(
1395       runTest("a", cl::values(clEnumValN(OptionValue::Val, OptName, "help"),
1396                               clEnumValN(OptionValue::Val, "b", "help"))),
1397       ExpectedStrSize);
1398 }
1399 
TEST_F(GetOptionWidthTest,GetOptionWidthSecondOptionNameLonger)1400 TEST_F(GetOptionWidthTest, GetOptionWidthSecondOptionNameLonger) {
1401   StringRef OptName("a-long-option-name");
1402   size_t ExpectedStrSize = ("    =" + OptName + " - ").str().size();
1403   EXPECT_EQ(
1404       runTest("a", cl::values(clEnumValN(OptionValue::Val, "b", "help"),
1405                               clEnumValN(OptionValue::Val, OptName, "help"))),
1406       ExpectedStrSize);
1407 }
1408 
TEST_F(GetOptionWidthTest,GetOptionWidthEmptyOptionNameLonger)1409 TEST_F(GetOptionWidthTest, GetOptionWidthEmptyOptionNameLonger) {
1410   size_t ExpectedStrSize = StringRef("    =<empty> - ").size();
1411   // The length of a=<value> (including indentation) is actually the same as the
1412   // =<empty> string, so it is impossible to distinguish via testing the case
1413   // where the empty string is picked from where the option name is picked.
1414   EXPECT_EQ(runTest("a", cl::values(clEnumValN(OptionValue::Val, "b", "help"),
1415                                     clEnumValN(OptionValue::Val, "", "help"))),
1416             ExpectedStrSize);
1417 }
1418 
TEST_F(GetOptionWidthTest,GetOptionWidthValueOptionalEmptyOptionWithNoDescription)1419 TEST_F(GetOptionWidthTest,
1420        GetOptionWidthValueOptionalEmptyOptionWithNoDescription) {
1421   StringRef ArgName("a");
1422   // The length of a=<value> (including indentation) is actually the same as the
1423   // =<empty> string, so it is impossible to distinguish via testing the case
1424   // where the empty string is ignored from where it is not ignored.
1425   // The dash will not actually be printed, but the space it would take up is
1426   // included to ensure a consistent column width.
1427   size_t ExpectedStrSize = ("  -" + ArgName + "=<value> - ").str().size();
1428   EXPECT_EQ(runTest(ArgName, cl::ValueOptional,
1429                     cl::values(clEnumValN(OptionValue::Val, "value", "help"),
1430                                clEnumValN(OptionValue::Val, "", ""))),
1431             ExpectedStrSize);
1432 }
1433 
TEST_F(GetOptionWidthTest,GetOptionWidthValueRequiredEmptyOptionWithNoDescription)1434 TEST_F(GetOptionWidthTest,
1435        GetOptionWidthValueRequiredEmptyOptionWithNoDescription) {
1436   // The length of a=<value> (including indentation) is actually the same as the
1437   // =<empty> string, so it is impossible to distinguish via testing the case
1438   // where the empty string is picked from where the option name is picked
1439   size_t ExpectedStrSize = StringRef("    =<empty> - ").size();
1440   EXPECT_EQ(runTest("a", cl::ValueRequired,
1441                     cl::values(clEnumValN(OptionValue::Val, "value", "help"),
1442                                clEnumValN(OptionValue::Val, "", ""))),
1443             ExpectedStrSize);
1444 }
1445 
TEST(CommandLineTest,PrefixOptions)1446 TEST(CommandLineTest, PrefixOptions) {
1447   cl::ResetCommandLineParser();
1448 
1449   StackOption<std::string, cl::list<std::string>> IncludeDirs(
1450       "I", cl::Prefix, cl::desc("Declare an include directory"));
1451 
1452   // Test non-prefixed variant works with cl::Prefix options.
1453   EXPECT_TRUE(IncludeDirs.empty());
1454   const char *args[] = {"prog", "-I=/usr/include"};
1455   EXPECT_TRUE(
1456       cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
1457   EXPECT_EQ(IncludeDirs.size(), 1u);
1458   EXPECT_EQ(IncludeDirs.front().compare("/usr/include"), 0);
1459 
1460   IncludeDirs.erase(IncludeDirs.begin());
1461   cl::ResetAllOptionOccurrences();
1462 
1463   // Test non-prefixed variant works with cl::Prefix options when value is
1464   // passed in following argument.
1465   EXPECT_TRUE(IncludeDirs.empty());
1466   const char *args2[] = {"prog", "-I", "/usr/include"};
1467   EXPECT_TRUE(
1468       cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
1469   EXPECT_EQ(IncludeDirs.size(), 1u);
1470   EXPECT_EQ(IncludeDirs.front().compare("/usr/include"), 0);
1471 
1472   IncludeDirs.erase(IncludeDirs.begin());
1473   cl::ResetAllOptionOccurrences();
1474 
1475   // Test prefixed variant works with cl::Prefix options.
1476   EXPECT_TRUE(IncludeDirs.empty());
1477   const char *args3[] = {"prog", "-I/usr/include"};
1478   EXPECT_TRUE(
1479       cl::ParseCommandLineOptions(2, args3, StringRef(), &llvm::nulls()));
1480   EXPECT_EQ(IncludeDirs.size(), 1u);
1481   EXPECT_EQ(IncludeDirs.front().compare("/usr/include"), 0);
1482 
1483   StackOption<std::string, cl::list<std::string>> MacroDefs(
1484       "D", cl::AlwaysPrefix, cl::desc("Define a macro"),
1485       cl::value_desc("MACRO[=VALUE]"));
1486 
1487   cl::ResetAllOptionOccurrences();
1488 
1489   // Test non-prefixed variant does not work with cl::AlwaysPrefix options:
1490   // equal sign is part of the value.
1491   EXPECT_TRUE(MacroDefs.empty());
1492   const char *args4[] = {"prog", "-D=HAVE_FOO"};
1493   EXPECT_TRUE(
1494       cl::ParseCommandLineOptions(2, args4, StringRef(), &llvm::nulls()));
1495   EXPECT_EQ(MacroDefs.size(), 1u);
1496   EXPECT_EQ(MacroDefs.front().compare("=HAVE_FOO"), 0);
1497 
1498   MacroDefs.erase(MacroDefs.begin());
1499   cl::ResetAllOptionOccurrences();
1500 
1501   // Test non-prefixed variant does not allow value to be passed in following
1502   // argument with cl::AlwaysPrefix options.
1503   EXPECT_TRUE(MacroDefs.empty());
1504   const char *args5[] = {"prog", "-D", "HAVE_FOO"};
1505   EXPECT_FALSE(
1506       cl::ParseCommandLineOptions(3, args5, StringRef(), &llvm::nulls()));
1507   EXPECT_TRUE(MacroDefs.empty());
1508 
1509   cl::ResetAllOptionOccurrences();
1510 
1511   // Test prefixed variant works with cl::AlwaysPrefix options.
1512   EXPECT_TRUE(MacroDefs.empty());
1513   const char *args6[] = {"prog", "-DHAVE_FOO"};
1514   EXPECT_TRUE(
1515       cl::ParseCommandLineOptions(2, args6, StringRef(), &llvm::nulls()));
1516   EXPECT_EQ(MacroDefs.size(), 1u);
1517   EXPECT_EQ(MacroDefs.front().compare("HAVE_FOO"), 0);
1518 }
1519 
TEST(CommandLineTest,GroupingWithValue)1520 TEST(CommandLineTest, GroupingWithValue) {
1521   cl::ResetCommandLineParser();
1522 
1523   StackOption<bool> OptF("f", cl::Grouping, cl::desc("Some flag"));
1524   StackOption<bool> OptB("b", cl::Grouping, cl::desc("Another flag"));
1525   StackOption<bool> OptD("d", cl::Grouping, cl::ValueDisallowed,
1526                          cl::desc("ValueDisallowed option"));
1527   StackOption<std::string> OptV("v", cl::Grouping,
1528                                 cl::desc("ValueRequired option"));
1529   StackOption<std::string> OptO("o", cl::Grouping, cl::ValueOptional,
1530                                 cl::desc("ValueOptional option"));
1531 
1532   // Should be possible to use an option which requires a value
1533   // at the end of a group.
1534   const char *args1[] = {"prog", "-fv", "val1"};
1535   EXPECT_TRUE(
1536       cl::ParseCommandLineOptions(3, args1, StringRef(), &llvm::nulls()));
1537   EXPECT_TRUE(OptF);
1538   EXPECT_STREQ("val1", OptV.c_str());
1539   OptV.clear();
1540   cl::ResetAllOptionOccurrences();
1541 
1542   // Should not crash if it is accidentally used elsewhere in the group.
1543   const char *args2[] = {"prog", "-vf", "val2"};
1544   EXPECT_FALSE(
1545       cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
1546   OptV.clear();
1547   cl::ResetAllOptionOccurrences();
1548 
1549   // Should allow the "opt=value" form at the end of the group
1550   const char *args3[] = {"prog", "-fv=val3"};
1551   EXPECT_TRUE(
1552       cl::ParseCommandLineOptions(2, args3, StringRef(), &llvm::nulls()));
1553   EXPECT_TRUE(OptF);
1554   EXPECT_STREQ("val3", OptV.c_str());
1555   OptV.clear();
1556   cl::ResetAllOptionOccurrences();
1557 
1558   // Should allow assigning a value for a ValueOptional option
1559   // at the end of the group
1560   const char *args4[] = {"prog", "-fo=val4"};
1561   EXPECT_TRUE(
1562       cl::ParseCommandLineOptions(2, args4, StringRef(), &llvm::nulls()));
1563   EXPECT_TRUE(OptF);
1564   EXPECT_STREQ("val4", OptO.c_str());
1565   OptO.clear();
1566   cl::ResetAllOptionOccurrences();
1567 
1568   // Should assign an empty value if a ValueOptional option is used elsewhere
1569   // in the group.
1570   const char *args5[] = {"prog", "-fob"};
1571   EXPECT_TRUE(
1572       cl::ParseCommandLineOptions(2, args5, StringRef(), &llvm::nulls()));
1573   EXPECT_TRUE(OptF);
1574   EXPECT_EQ(1, OptO.getNumOccurrences());
1575   EXPECT_EQ(1, OptB.getNumOccurrences());
1576   EXPECT_TRUE(OptO.empty());
1577   cl::ResetAllOptionOccurrences();
1578 
1579   // Should not allow an assignment for a ValueDisallowed option.
1580   const char *args6[] = {"prog", "-fd=false"};
1581   EXPECT_FALSE(
1582       cl::ParseCommandLineOptions(2, args6, StringRef(), &llvm::nulls()));
1583 }
1584 
TEST(CommandLineTest,GroupingAndPrefix)1585 TEST(CommandLineTest, GroupingAndPrefix) {
1586   cl::ResetCommandLineParser();
1587 
1588   StackOption<bool> OptF("f", cl::Grouping, cl::desc("Some flag"));
1589   StackOption<bool> OptB("b", cl::Grouping, cl::desc("Another flag"));
1590   StackOption<std::string> OptP("p", cl::Prefix, cl::Grouping,
1591                                 cl::desc("Prefix and Grouping"));
1592   StackOption<std::string> OptA("a", cl::AlwaysPrefix, cl::Grouping,
1593                                 cl::desc("AlwaysPrefix and Grouping"));
1594 
1595   // Should be possible to use a cl::Prefix option without grouping.
1596   const char *args1[] = {"prog", "-pval1"};
1597   EXPECT_TRUE(
1598       cl::ParseCommandLineOptions(2, args1, StringRef(), &llvm::nulls()));
1599   EXPECT_STREQ("val1", OptP.c_str());
1600   OptP.clear();
1601   cl::ResetAllOptionOccurrences();
1602 
1603   // Should be possible to pass a value in a separate argument.
1604   const char *args2[] = {"prog", "-p", "val2"};
1605   EXPECT_TRUE(
1606       cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
1607   EXPECT_STREQ("val2", OptP.c_str());
1608   OptP.clear();
1609   cl::ResetAllOptionOccurrences();
1610 
1611   // The "-opt=value" form should work, too.
1612   const char *args3[] = {"prog", "-p=val3"};
1613   EXPECT_TRUE(
1614       cl::ParseCommandLineOptions(2, args3, StringRef(), &llvm::nulls()));
1615   EXPECT_STREQ("val3", OptP.c_str());
1616   OptP.clear();
1617   cl::ResetAllOptionOccurrences();
1618 
1619   // All three previous cases should work the same way if an option with both
1620   // cl::Prefix and cl::Grouping modifiers is used at the end of a group.
1621   const char *args4[] = {"prog", "-fpval4"};
1622   EXPECT_TRUE(
1623       cl::ParseCommandLineOptions(2, args4, StringRef(), &llvm::nulls()));
1624   EXPECT_TRUE(OptF);
1625   EXPECT_STREQ("val4", OptP.c_str());
1626   OptP.clear();
1627   cl::ResetAllOptionOccurrences();
1628 
1629   const char *args5[] = {"prog", "-fp", "val5"};
1630   EXPECT_TRUE(
1631       cl::ParseCommandLineOptions(3, args5, StringRef(), &llvm::nulls()));
1632   EXPECT_TRUE(OptF);
1633   EXPECT_STREQ("val5", OptP.c_str());
1634   OptP.clear();
1635   cl::ResetAllOptionOccurrences();
1636 
1637   const char *args6[] = {"prog", "-fp=val6"};
1638   EXPECT_TRUE(
1639       cl::ParseCommandLineOptions(2, args6, StringRef(), &llvm::nulls()));
1640   EXPECT_TRUE(OptF);
1641   EXPECT_STREQ("val6", OptP.c_str());
1642   OptP.clear();
1643   cl::ResetAllOptionOccurrences();
1644 
1645   // Should assign a value even if the part after a cl::Prefix option is equal
1646   // to the name of another option.
1647   const char *args7[] = {"prog", "-fpb"};
1648   EXPECT_TRUE(
1649       cl::ParseCommandLineOptions(2, args7, StringRef(), &llvm::nulls()));
1650   EXPECT_TRUE(OptF);
1651   EXPECT_STREQ("b", OptP.c_str());
1652   EXPECT_FALSE(OptB);
1653   OptP.clear();
1654   cl::ResetAllOptionOccurrences();
1655 
1656   // Should be possible to use a cl::AlwaysPrefix option without grouping.
1657   const char *args8[] = {"prog", "-aval8"};
1658   EXPECT_TRUE(
1659       cl::ParseCommandLineOptions(2, args8, StringRef(), &llvm::nulls()));
1660   EXPECT_STREQ("val8", OptA.c_str());
1661   OptA.clear();
1662   cl::ResetAllOptionOccurrences();
1663 
1664   // Should not be possible to pass a value in a separate argument.
1665   const char *args9[] = {"prog", "-a", "val9"};
1666   EXPECT_FALSE(
1667       cl::ParseCommandLineOptions(3, args9, StringRef(), &llvm::nulls()));
1668   cl::ResetAllOptionOccurrences();
1669 
1670   // With the "-opt=value" form, the "=" symbol should be preserved.
1671   const char *args10[] = {"prog", "-a=val10"};
1672   EXPECT_TRUE(
1673       cl::ParseCommandLineOptions(2, args10, StringRef(), &llvm::nulls()));
1674   EXPECT_STREQ("=val10", OptA.c_str());
1675   OptA.clear();
1676   cl::ResetAllOptionOccurrences();
1677 
1678   // All three previous cases should work the same way if an option with both
1679   // cl::AlwaysPrefix and cl::Grouping modifiers is used at the end of a group.
1680   const char *args11[] = {"prog", "-faval11"};
1681   EXPECT_TRUE(
1682       cl::ParseCommandLineOptions(2, args11, StringRef(), &llvm::nulls()));
1683   EXPECT_TRUE(OptF);
1684   EXPECT_STREQ("val11", OptA.c_str());
1685   OptA.clear();
1686   cl::ResetAllOptionOccurrences();
1687 
1688   const char *args12[] = {"prog", "-fa", "val12"};
1689   EXPECT_FALSE(
1690       cl::ParseCommandLineOptions(3, args12, StringRef(), &llvm::nulls()));
1691   cl::ResetAllOptionOccurrences();
1692 
1693   const char *args13[] = {"prog", "-fa=val13"};
1694   EXPECT_TRUE(
1695       cl::ParseCommandLineOptions(2, args13, StringRef(), &llvm::nulls()));
1696   EXPECT_TRUE(OptF);
1697   EXPECT_STREQ("=val13", OptA.c_str());
1698   OptA.clear();
1699   cl::ResetAllOptionOccurrences();
1700 
1701   // Should assign a value even if the part after a cl::AlwaysPrefix option
1702   // is equal to the name of another option.
1703   const char *args14[] = {"prog", "-fab"};
1704   EXPECT_TRUE(
1705       cl::ParseCommandLineOptions(2, args14, StringRef(), &llvm::nulls()));
1706   EXPECT_TRUE(OptF);
1707   EXPECT_STREQ("b", OptA.c_str());
1708   EXPECT_FALSE(OptB);
1709   OptA.clear();
1710   cl::ResetAllOptionOccurrences();
1711 }
1712 
TEST(CommandLineTest,LongOptions)1713 TEST(CommandLineTest, LongOptions) {
1714   cl::ResetCommandLineParser();
1715 
1716   StackOption<bool> OptA("a", cl::desc("Some flag"));
1717   StackOption<bool> OptBLong("long-flag", cl::desc("Some long flag"));
1718   StackOption<bool, cl::alias> OptB("b", cl::desc("Alias to --long-flag"),
1719                                     cl::aliasopt(OptBLong));
1720   StackOption<std::string> OptAB("ab", cl::desc("Another long option"));
1721 
1722   std::string Errs;
1723   raw_string_ostream OS(Errs);
1724 
1725   const char *args1[] = {"prog", "-a", "-ab", "val1"};
1726   const char *args2[] = {"prog", "-a", "--ab", "val1"};
1727   const char *args3[] = {"prog", "-ab", "--ab", "val1"};
1728 
1729   //
1730   // The following tests treat `-` and `--` the same, and always match the
1731   // longest string.
1732   //
1733 
1734   EXPECT_TRUE(
1735       cl::ParseCommandLineOptions(4, args1, StringRef(), &OS)); OS.flush();
1736   EXPECT_TRUE(OptA);
1737   EXPECT_FALSE(OptBLong);
1738   EXPECT_STREQ("val1", OptAB.c_str());
1739   EXPECT_TRUE(Errs.empty()); Errs.clear();
1740   cl::ResetAllOptionOccurrences();
1741 
1742   EXPECT_TRUE(
1743       cl::ParseCommandLineOptions(4, args2, StringRef(), &OS)); OS.flush();
1744   EXPECT_TRUE(OptA);
1745   EXPECT_FALSE(OptBLong);
1746   EXPECT_STREQ("val1", OptAB.c_str());
1747   EXPECT_TRUE(Errs.empty()); Errs.clear();
1748   cl::ResetAllOptionOccurrences();
1749 
1750   // Fails because `-ab` and `--ab` are treated the same and appear more than
1751   // once.  Also, `val1` is unexpected.
1752   EXPECT_FALSE(
1753       cl::ParseCommandLineOptions(4, args3, StringRef(), &OS)); OS.flush();
1754   outs()<< Errs << "\n";
1755   EXPECT_FALSE(Errs.empty()); Errs.clear();
1756   cl::ResetAllOptionOccurrences();
1757 
1758   //
1759   // The following tests treat `-` and `--` differently, with `-` for short, and
1760   // `--` for long options.
1761   //
1762 
1763   // Fails because `-ab` is treated as `-a -b`, so `-a` is seen twice, and
1764   // `val1` is unexpected.
1765   EXPECT_FALSE(cl::ParseCommandLineOptions(4, args1, StringRef(),
1766                                            &OS, nullptr, true)); OS.flush();
1767   EXPECT_FALSE(Errs.empty()); Errs.clear();
1768   cl::ResetAllOptionOccurrences();
1769 
1770   // Works because `-a` is treated differently than `--ab`.
1771   EXPECT_TRUE(cl::ParseCommandLineOptions(4, args2, StringRef(),
1772                                            &OS, nullptr, true)); OS.flush();
1773   EXPECT_TRUE(Errs.empty()); Errs.clear();
1774   cl::ResetAllOptionOccurrences();
1775 
1776   // Works because `-ab` is treated as `-a -b`, and `--ab` is a long option.
1777   EXPECT_TRUE(cl::ParseCommandLineOptions(4, args3, StringRef(),
1778                                            &OS, nullptr, true));
1779   EXPECT_TRUE(OptA);
1780   EXPECT_TRUE(OptBLong);
1781   EXPECT_STREQ("val1", OptAB.c_str());
1782   OS.flush();
1783   EXPECT_TRUE(Errs.empty()); Errs.clear();
1784   cl::ResetAllOptionOccurrences();
1785 }
1786 
TEST(CommandLineTest,OptionErrorMessage)1787 TEST(CommandLineTest, OptionErrorMessage) {
1788   // When there is an error, we expect some error message like:
1789   //   prog: for the -a option: [...]
1790   //
1791   // Test whether the "for the -a option"-part is correctly formatted.
1792   cl::ResetCommandLineParser();
1793 
1794   StackOption<bool> OptA("a", cl::desc("Some option"));
1795   StackOption<bool> OptLong("long", cl::desc("Some long option"));
1796 
1797   std::string Errs;
1798   raw_string_ostream OS(Errs);
1799 
1800   OptA.error("custom error", OS);
1801   OS.flush();
1802   EXPECT_NE(Errs.find("for the -a option:"), std::string::npos);
1803   Errs.clear();
1804 
1805   OptLong.error("custom error", OS);
1806   OS.flush();
1807   EXPECT_NE(Errs.find("for the --long option:"), std::string::npos);
1808   Errs.clear();
1809 
1810   cl::ResetAllOptionOccurrences();
1811 }
1812 
TEST(CommandLineTest,OptionErrorMessageSuggest)1813 TEST(CommandLineTest, OptionErrorMessageSuggest) {
1814   // When there is an error, and the edit-distance is not very large,
1815   // we expect some error message like:
1816   //   prog: did you mean '--option'?
1817   //
1818   // Test whether this message is well-formatted.
1819   cl::ResetCommandLineParser();
1820 
1821   StackOption<bool> OptLong("aluminium", cl::desc("Some long option"));
1822 
1823   const char *args[] = {"prog", "--aluminum"};
1824 
1825   std::string Errs;
1826   raw_string_ostream OS(Errs);
1827 
1828   EXPECT_FALSE(cl::ParseCommandLineOptions(2, args, StringRef(), &OS));
1829   OS.flush();
1830   EXPECT_NE(Errs.find("prog: Did you mean '--aluminium'?\n"),
1831             std::string::npos);
1832   Errs.clear();
1833 
1834   cl::ResetAllOptionOccurrences();
1835 }
1836 
TEST(CommandLineTest,OptionErrorMessageSuggestNoHidden)1837 TEST(CommandLineTest, OptionErrorMessageSuggestNoHidden) {
1838   // We expect that 'really hidden' option do not show up in option
1839   // suggestions.
1840   cl::ResetCommandLineParser();
1841 
1842   StackOption<bool> OptLong("aluminium", cl::desc("Some long option"));
1843   StackOption<bool> OptLong2("aluminum", cl::desc("Bad option"),
1844                              cl::ReallyHidden);
1845 
1846   const char *args[] = {"prog", "--alumnum"};
1847 
1848   std::string Errs;
1849   raw_string_ostream OS(Errs);
1850 
1851   EXPECT_FALSE(cl::ParseCommandLineOptions(2, args, StringRef(), &OS));
1852   OS.flush();
1853   EXPECT_NE(Errs.find("prog: Did you mean '--aluminium'?\n"),
1854             std::string::npos);
1855   Errs.clear();
1856 
1857   cl::ResetAllOptionOccurrences();
1858 }
1859 
TEST(CommandLineTest,Callback)1860 TEST(CommandLineTest, Callback) {
1861   cl::ResetCommandLineParser();
1862 
1863   StackOption<bool> OptA("a", cl::desc("option a"));
1864   StackOption<bool> OptB(
1865       "b", cl::desc("option b -- This option turns on option a"),
1866       cl::callback([&](const bool &) { OptA = true; }));
1867   StackOption<bool> OptC(
1868       "c", cl::desc("option c -- This option turns on options a and b"),
1869       cl::callback([&](const bool &) { OptB = true; }));
1870   StackOption<std::string, cl::list<std::string>> List(
1871       "list",
1872       cl::desc("option list -- This option turns on options a, b, and c when "
1873                "'foo' is included in list"),
1874       cl::CommaSeparated,
1875       cl::callback([&](const std::string &Str) {
1876         if (Str == "foo")
1877           OptC = true;
1878       }));
1879 
1880   const char *args1[] = {"prog", "-a"};
1881   EXPECT_TRUE(cl::ParseCommandLineOptions(2, args1));
1882   EXPECT_TRUE(OptA);
1883   EXPECT_FALSE(OptB);
1884   EXPECT_FALSE(OptC);
1885   EXPECT_EQ(List.size(), 0u);
1886   cl::ResetAllOptionOccurrences();
1887 
1888   const char *args2[] = {"prog", "-b"};
1889   EXPECT_TRUE(cl::ParseCommandLineOptions(2, args2));
1890   EXPECT_TRUE(OptA);
1891   EXPECT_TRUE(OptB);
1892   EXPECT_FALSE(OptC);
1893   EXPECT_EQ(List.size(), 0u);
1894   cl::ResetAllOptionOccurrences();
1895 
1896   const char *args3[] = {"prog", "-c"};
1897   EXPECT_TRUE(cl::ParseCommandLineOptions(2, args3));
1898   EXPECT_TRUE(OptA);
1899   EXPECT_TRUE(OptB);
1900   EXPECT_TRUE(OptC);
1901   EXPECT_EQ(List.size(), 0u);
1902   cl::ResetAllOptionOccurrences();
1903 
1904   const char *args4[] = {"prog", "--list=foo,bar"};
1905   EXPECT_TRUE(cl::ParseCommandLineOptions(2, args4));
1906   EXPECT_TRUE(OptA);
1907   EXPECT_TRUE(OptB);
1908   EXPECT_TRUE(OptC);
1909   EXPECT_EQ(List.size(), 2u);
1910   cl::ResetAllOptionOccurrences();
1911 
1912   const char *args5[] = {"prog", "--list=bar"};
1913   EXPECT_TRUE(cl::ParseCommandLineOptions(2, args5));
1914   EXPECT_FALSE(OptA);
1915   EXPECT_FALSE(OptB);
1916   EXPECT_FALSE(OptC);
1917   EXPECT_EQ(List.size(), 1u);
1918 
1919   cl::ResetAllOptionOccurrences();
1920 }
1921 
1922 enum Enum { Val1, Val2 };
1923 static cl::bits<Enum> ExampleBits(
1924     cl::desc("An example cl::bits to ensure it compiles"),
1925     cl::values(
1926       clEnumValN(Val1, "bits-val1", "The Val1 value"),
1927       clEnumValN(Val1, "bits-val2", "The Val2 value")));
1928 
TEST(CommandLineTest,ConsumeAfterOnePositional)1929 TEST(CommandLineTest, ConsumeAfterOnePositional) {
1930   cl::ResetCommandLineParser();
1931 
1932   // input [args]
1933   StackOption<std::string, cl::opt<std::string>> Input(cl::Positional,
1934                                                        cl::Required);
1935   StackOption<std::string, cl::list<std::string>> ExtraArgs(cl::ConsumeAfter);
1936 
1937   const char *Args[] = {"prog", "input", "arg1", "arg2"};
1938 
1939   std::string Errs;
1940   raw_string_ostream OS(Errs);
1941   EXPECT_TRUE(cl::ParseCommandLineOptions(4, Args, StringRef(), &OS));
1942   OS.flush();
1943   EXPECT_EQ("input", Input);
1944   EXPECT_EQ(ExtraArgs.size(), 2u);
1945   EXPECT_EQ(ExtraArgs[0], "arg1");
1946   EXPECT_EQ(ExtraArgs[1], "arg2");
1947   EXPECT_TRUE(Errs.empty());
1948 }
1949 
TEST(CommandLineTest,ConsumeAfterTwoPositionals)1950 TEST(CommandLineTest, ConsumeAfterTwoPositionals) {
1951   cl::ResetCommandLineParser();
1952 
1953   // input1 input2 [args]
1954   StackOption<std::string, cl::opt<std::string>> Input1(cl::Positional,
1955                                                         cl::Required);
1956   StackOption<std::string, cl::opt<std::string>> Input2(cl::Positional,
1957                                                         cl::Required);
1958   StackOption<std::string, cl::list<std::string>> ExtraArgs(cl::ConsumeAfter);
1959 
1960   const char *Args[] = {"prog", "input1", "input2", "arg1", "arg2"};
1961 
1962   std::string Errs;
1963   raw_string_ostream OS(Errs);
1964   EXPECT_TRUE(cl::ParseCommandLineOptions(5, Args, StringRef(), &OS));
1965   OS.flush();
1966   EXPECT_EQ("input1", Input1);
1967   EXPECT_EQ("input2", Input2);
1968   EXPECT_EQ(ExtraArgs.size(), 2u);
1969   EXPECT_EQ(ExtraArgs[0], "arg1");
1970   EXPECT_EQ(ExtraArgs[1], "arg2");
1971   EXPECT_TRUE(Errs.empty());
1972 }
1973 
TEST(CommandLineTest,ResetAllOptionOccurrences)1974 TEST(CommandLineTest, ResetAllOptionOccurrences) {
1975   cl::ResetCommandLineParser();
1976 
1977   // -option -str -enableA -enableC [sink] input [args]
1978   StackOption<bool> Option("option");
1979   StackOption<std::string> Str("str");
1980   enum Vals { ValA, ValB, ValC };
1981   StackOption<Vals, cl::bits<Vals>> Bits(
1982       cl::values(clEnumValN(ValA, "enableA", "Enable A"),
1983                  clEnumValN(ValB, "enableB", "Enable B"),
1984                  clEnumValN(ValC, "enableC", "Enable C")));
1985   StackOption<std::string, cl::list<std::string>> Sink(cl::Sink);
1986   StackOption<std::string> Input(cl::Positional);
1987   StackOption<std::string, cl::list<std::string>> ExtraArgs(cl::ConsumeAfter);
1988 
1989   const char *Args[] = {"prog",     "-option",  "-str=STR", "-enableA",
1990                         "-enableC", "-unknown", "input",    "-arg"};
1991 
1992   std::string Errs;
1993   raw_string_ostream OS(Errs);
1994   EXPECT_TRUE(cl::ParseCommandLineOptions(8, Args, StringRef(), &OS));
1995   EXPECT_TRUE(OS.str().empty());
1996 
1997   EXPECT_TRUE(Option);
1998   EXPECT_EQ("STR", Str);
1999   EXPECT_EQ((1u << ValA) | (1u << ValC), Bits.getBits());
2000   EXPECT_EQ(1u, Sink.size());
2001   EXPECT_EQ("-unknown", Sink[0]);
2002   EXPECT_EQ("input", Input);
2003   EXPECT_EQ(1u, ExtraArgs.size());
2004   EXPECT_EQ("-arg", ExtraArgs[0]);
2005 
2006   cl::ResetAllOptionOccurrences();
2007   EXPECT_FALSE(Option);
2008   EXPECT_EQ("", Str);
2009   EXPECT_EQ(0u, Bits.getBits());
2010   EXPECT_EQ(0u, Sink.size());
2011   EXPECT_EQ(0, Input.getNumOccurrences());
2012   EXPECT_EQ(0u, ExtraArgs.size());
2013 }
2014 
TEST(CommandLineTest,DefaultValue)2015 TEST(CommandLineTest, DefaultValue) {
2016   cl::ResetCommandLineParser();
2017 
2018   StackOption<bool> BoolOption("bool-option");
2019   StackOption<std::string> StrOption("str-option");
2020   StackOption<bool> BoolInitOption("bool-init-option", cl::init(true));
2021   StackOption<std::string> StrInitOption("str-init-option",
2022                                          cl::init("str-default-value"));
2023 
2024   const char *Args[] = {"prog"}; // no options
2025 
2026   std::string Errs;
2027   raw_string_ostream OS(Errs);
2028   EXPECT_TRUE(cl::ParseCommandLineOptions(1, Args, StringRef(), &OS));
2029   EXPECT_TRUE(OS.str().empty());
2030 
2031   EXPECT_TRUE(!BoolOption);
2032   EXPECT_FALSE(BoolOption.Default.hasValue());
2033   EXPECT_EQ(0, BoolOption.getNumOccurrences());
2034 
2035   EXPECT_EQ("", StrOption);
2036   EXPECT_FALSE(StrOption.Default.hasValue());
2037   EXPECT_EQ(0, StrOption.getNumOccurrences());
2038 
2039   EXPECT_TRUE(BoolInitOption);
2040   EXPECT_TRUE(BoolInitOption.Default.hasValue());
2041   EXPECT_EQ(0, BoolInitOption.getNumOccurrences());
2042 
2043   EXPECT_EQ("str-default-value", StrInitOption);
2044   EXPECT_TRUE(StrInitOption.Default.hasValue());
2045   EXPECT_EQ(0, StrInitOption.getNumOccurrences());
2046 
2047   const char *Args2[] = {"prog", "-bool-option", "-str-option=str-value",
2048                          "-bool-init-option=0",
2049                          "-str-init-option=str-init-value"};
2050 
2051   EXPECT_TRUE(cl::ParseCommandLineOptions(5, Args2, StringRef(), &OS));
2052   EXPECT_TRUE(OS.str().empty());
2053 
2054   EXPECT_TRUE(BoolOption);
2055   EXPECT_FALSE(BoolOption.Default.hasValue());
2056   EXPECT_EQ(1, BoolOption.getNumOccurrences());
2057 
2058   EXPECT_EQ("str-value", StrOption);
2059   EXPECT_FALSE(StrOption.Default.hasValue());
2060   EXPECT_EQ(1, StrOption.getNumOccurrences());
2061 
2062   EXPECT_FALSE(BoolInitOption);
2063   EXPECT_TRUE(BoolInitOption.Default.hasValue());
2064   EXPECT_EQ(1, BoolInitOption.getNumOccurrences());
2065 
2066   EXPECT_EQ("str-init-value", StrInitOption);
2067   EXPECT_TRUE(StrInitOption.Default.hasValue());
2068   EXPECT_EQ(1, StrInitOption.getNumOccurrences());
2069 }
2070 
2071 } // anonymous namespace
2072