CommandLineTest.cpp 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656
  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. #include "llvm/Support/CommandLine.h"
  9. #include "llvm/ADT/STLExtras.h"
  10. #include "llvm/ADT/SmallString.h"
  11. #include "llvm/ADT/Triple.h"
  12. #include "llvm/Config/config.h"
  13. #include "llvm/Support/FileSystem.h"
  14. #include "llvm/Support/InitLLVM.h"
  15. #include "llvm/Support/MemoryBuffer.h"
  16. #include "llvm/Support/Path.h"
  17. #include "llvm/Support/Program.h"
  18. #include "llvm/Support/StringSaver.h"
  19. #include "gtest/gtest.h"
  20. #include <fstream>
  21. #include <stdlib.h>
  22. #include <string>
  23. using namespace llvm;
  24. namespace {
  25. class TempEnvVar {
  26. public:
  27. TempEnvVar(const char *name, const char *value)
  28. : name(name) {
  29. const char *old_value = getenv(name);
  30. EXPECT_EQ(nullptr, old_value) << old_value;
  31. #if HAVE_SETENV
  32. setenv(name, value, true);
  33. #else
  34. # define SKIP_ENVIRONMENT_TESTS
  35. #endif
  36. }
  37. ~TempEnvVar() {
  38. #if HAVE_SETENV
  39. // Assume setenv and unsetenv come together.
  40. unsetenv(name);
  41. #else
  42. (void)name; // Suppress -Wunused-private-field.
  43. #endif
  44. }
  45. private:
  46. const char *const name;
  47. };
  48. template <typename T, typename Base = cl::opt<T>>
  49. class StackOption : public Base {
  50. public:
  51. template <class... Ts>
  52. explicit StackOption(Ts &&... Ms) : Base(std::forward<Ts>(Ms)...) {}
  53. ~StackOption() override { this->removeArgument(); }
  54. template <class DT> StackOption<T> &operator=(const DT &V) {
  55. this->setValue(V);
  56. return *this;
  57. }
  58. };
  59. class StackSubCommand : public cl::SubCommand {
  60. public:
  61. StackSubCommand(StringRef Name,
  62. StringRef Description = StringRef())
  63. : SubCommand(Name, Description) {}
  64. StackSubCommand() : SubCommand() {}
  65. ~StackSubCommand() { unregisterSubCommand(); }
  66. };
  67. cl::OptionCategory TestCategory("Test Options", "Description");
  68. TEST(CommandLineTest, ModifyExisitingOption) {
  69. StackOption<int> TestOption("test-option", cl::desc("old description"));
  70. static const char Description[] = "New description";
  71. static const char ArgString[] = "new-test-option";
  72. static const char ValueString[] = "Integer";
  73. StringMap<cl::Option *> &Map =
  74. cl::getRegisteredOptions(*cl::TopLevelSubCommand);
  75. ASSERT_TRUE(Map.count("test-option") == 1) <<
  76. "Could not find option in map.";
  77. cl::Option *Retrieved = Map["test-option"];
  78. ASSERT_EQ(&TestOption, Retrieved) << "Retrieved wrong option.";
  79. ASSERT_NE(Retrieved->Categories.end(),
  80. find_if(Retrieved->Categories,
  81. [&](const llvm::cl::OptionCategory *Cat) {
  82. return Cat == &cl::GeneralCategory;
  83. }))
  84. << "Incorrect default option category.";
  85. Retrieved->addCategory(TestCategory);
  86. ASSERT_NE(Retrieved->Categories.end(),
  87. find_if(Retrieved->Categories,
  88. [&](const llvm::cl::OptionCategory *Cat) {
  89. return Cat == &TestCategory;
  90. }))
  91. << "Failed to modify option's option category.";
  92. Retrieved->setDescription(Description);
  93. ASSERT_STREQ(Retrieved->HelpStr.data(), Description)
  94. << "Changing option description failed.";
  95. Retrieved->setArgStr(ArgString);
  96. ASSERT_STREQ(ArgString, Retrieved->ArgStr.data())
  97. << "Failed to modify option's Argument string.";
  98. Retrieved->setValueStr(ValueString);
  99. ASSERT_STREQ(Retrieved->ValueStr.data(), ValueString)
  100. << "Failed to modify option's Value string.";
  101. Retrieved->setHiddenFlag(cl::Hidden);
  102. ASSERT_EQ(cl::Hidden, TestOption.getOptionHiddenFlag()) <<
  103. "Failed to modify option's hidden flag.";
  104. }
  105. #ifndef SKIP_ENVIRONMENT_TESTS
  106. const char test_env_var[] = "LLVM_TEST_COMMAND_LINE_FLAGS";
  107. cl::opt<std::string> EnvironmentTestOption("env-test-opt");
  108. TEST(CommandLineTest, ParseEnvironment) {
  109. TempEnvVar TEV(test_env_var, "-env-test-opt=hello");
  110. EXPECT_EQ("", EnvironmentTestOption);
  111. cl::ParseEnvironmentOptions("CommandLineTest", test_env_var);
  112. EXPECT_EQ("hello", EnvironmentTestOption);
  113. }
  114. // This test used to make valgrind complain
  115. // ("Conditional jump or move depends on uninitialised value(s)")
  116. //
  117. // Warning: Do not run any tests after this one that try to gain access to
  118. // registered command line options because this will likely result in a
  119. // SEGFAULT. This can occur because the cl::opt in the test below is declared
  120. // on the stack which will be destroyed after the test completes but the
  121. // command line system will still hold a pointer to a deallocated cl::Option.
  122. TEST(CommandLineTest, ParseEnvironmentToLocalVar) {
  123. // Put cl::opt on stack to check for proper initialization of fields.
  124. StackOption<std::string> EnvironmentTestOptionLocal("env-test-opt-local");
  125. TempEnvVar TEV(test_env_var, "-env-test-opt-local=hello-local");
  126. EXPECT_EQ("", EnvironmentTestOptionLocal);
  127. cl::ParseEnvironmentOptions("CommandLineTest", test_env_var);
  128. EXPECT_EQ("hello-local", EnvironmentTestOptionLocal);
  129. }
  130. #endif // SKIP_ENVIRONMENT_TESTS
  131. TEST(CommandLineTest, UseOptionCategory) {
  132. StackOption<int> TestOption2("test-option", cl::cat(TestCategory));
  133. ASSERT_NE(TestOption2.Categories.end(),
  134. find_if(TestOption2.Categories,
  135. [&](const llvm::cl::OptionCategory *Cat) {
  136. return Cat == &TestCategory;
  137. }))
  138. << "Failed to assign Option Category.";
  139. }
  140. TEST(CommandLineTest, UseMultipleCategories) {
  141. StackOption<int> TestOption2("test-option2", cl::cat(TestCategory),
  142. cl::cat(cl::GeneralCategory),
  143. cl::cat(cl::GeneralCategory));
  144. // Make sure cl::GeneralCategory wasn't added twice.
  145. ASSERT_EQ(TestOption2.Categories.size(), 2U);
  146. ASSERT_NE(TestOption2.Categories.end(),
  147. find_if(TestOption2.Categories,
  148. [&](const llvm::cl::OptionCategory *Cat) {
  149. return Cat == &TestCategory;
  150. }))
  151. << "Failed to assign Option Category.";
  152. ASSERT_NE(TestOption2.Categories.end(),
  153. find_if(TestOption2.Categories,
  154. [&](const llvm::cl::OptionCategory *Cat) {
  155. return Cat == &cl::GeneralCategory;
  156. }))
  157. << "Failed to assign General Category.";
  158. cl::OptionCategory AnotherCategory("Additional test Options", "Description");
  159. StackOption<int> TestOption("test-option", cl::cat(TestCategory),
  160. cl::cat(AnotherCategory));
  161. ASSERT_EQ(TestOption.Categories.end(),
  162. find_if(TestOption.Categories,
  163. [&](const llvm::cl::OptionCategory *Cat) {
  164. return Cat == &cl::GeneralCategory;
  165. }))
  166. << "Failed to remove General Category.";
  167. ASSERT_NE(TestOption.Categories.end(),
  168. find_if(TestOption.Categories,
  169. [&](const llvm::cl::OptionCategory *Cat) {
  170. return Cat == &TestCategory;
  171. }))
  172. << "Failed to assign Option Category.";
  173. ASSERT_NE(TestOption.Categories.end(),
  174. find_if(TestOption.Categories,
  175. [&](const llvm::cl::OptionCategory *Cat) {
  176. return Cat == &AnotherCategory;
  177. }))
  178. << "Failed to assign Another Category.";
  179. }
  180. typedef void ParserFunction(StringRef Source, StringSaver &Saver,
  181. SmallVectorImpl<const char *> &NewArgv,
  182. bool MarkEOLs);
  183. void testCommandLineTokenizer(ParserFunction *parse, StringRef Input,
  184. const char *const Output[], size_t OutputSize) {
  185. SmallVector<const char *, 0> Actual;
  186. BumpPtrAllocator A;
  187. StringSaver Saver(A);
  188. parse(Input, Saver, Actual, /*MarkEOLs=*/false);
  189. EXPECT_EQ(OutputSize, Actual.size());
  190. for (unsigned I = 0, E = Actual.size(); I != E; ++I) {
  191. if (I < OutputSize) {
  192. EXPECT_STREQ(Output[I], Actual[I]);
  193. }
  194. }
  195. }
  196. TEST(CommandLineTest, TokenizeGNUCommandLine) {
  197. const char Input[] =
  198. "foo\\ bar \"foo bar\" \'foo bar\' 'foo\\\\bar' -DFOO=bar\\(\\) "
  199. "foo\"bar\"baz C:\\\\src\\\\foo.cpp \"C:\\src\\foo.cpp\"";
  200. const char *const Output[] = {
  201. "foo bar", "foo bar", "foo bar", "foo\\bar",
  202. "-DFOO=bar()", "foobarbaz", "C:\\src\\foo.cpp", "C:srcfoo.cpp"};
  203. testCommandLineTokenizer(cl::TokenizeGNUCommandLine, Input, Output,
  204. array_lengthof(Output));
  205. }
  206. TEST(CommandLineTest, TokenizeWindowsCommandLine1) {
  207. const char Input[] = "a\\b c\\\\d e\\\\\"f g\" h\\\"i j\\\\\\\"k \"lmn\" o pqr "
  208. "\"st \\\"u\" \\v";
  209. const char *const Output[] = { "a\\b", "c\\\\d", "e\\f g", "h\"i", "j\\\"k",
  210. "lmn", "o", "pqr", "st \"u", "\\v" };
  211. testCommandLineTokenizer(cl::TokenizeWindowsCommandLine, Input, Output,
  212. array_lengthof(Output));
  213. }
  214. TEST(CommandLineTest, TokenizeWindowsCommandLine2) {
  215. const char Input[] = "clang -c -DFOO=\"\"\"ABC\"\"\" x.cpp";
  216. const char *const Output[] = { "clang", "-c", "-DFOO=\"ABC\"", "x.cpp"};
  217. testCommandLineTokenizer(cl::TokenizeWindowsCommandLine, Input, Output,
  218. array_lengthof(Output));
  219. }
  220. TEST(CommandLineTest, TokenizeConfigFile1) {
  221. const char *Input = "\\";
  222. const char *const Output[] = { "\\" };
  223. testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output,
  224. array_lengthof(Output));
  225. }
  226. TEST(CommandLineTest, TokenizeConfigFile2) {
  227. const char *Input = "\\abc";
  228. const char *const Output[] = { "abc" };
  229. testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output,
  230. array_lengthof(Output));
  231. }
  232. TEST(CommandLineTest, TokenizeConfigFile3) {
  233. const char *Input = "abc\\";
  234. const char *const Output[] = { "abc\\" };
  235. testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output,
  236. array_lengthof(Output));
  237. }
  238. TEST(CommandLineTest, TokenizeConfigFile4) {
  239. const char *Input = "abc\\\n123";
  240. const char *const Output[] = { "abc123" };
  241. testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output,
  242. array_lengthof(Output));
  243. }
  244. TEST(CommandLineTest, TokenizeConfigFile5) {
  245. const char *Input = "abc\\\r\n123";
  246. const char *const Output[] = { "abc123" };
  247. testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output,
  248. array_lengthof(Output));
  249. }
  250. TEST(CommandLineTest, TokenizeConfigFile6) {
  251. const char *Input = "abc\\\n";
  252. const char *const Output[] = { "abc" };
  253. testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output,
  254. array_lengthof(Output));
  255. }
  256. TEST(CommandLineTest, TokenizeConfigFile7) {
  257. const char *Input = "abc\\\r\n";
  258. const char *const Output[] = { "abc" };
  259. testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output,
  260. array_lengthof(Output));
  261. }
  262. TEST(CommandLineTest, TokenizeConfigFile8) {
  263. SmallVector<const char *, 0> Actual;
  264. BumpPtrAllocator A;
  265. StringSaver Saver(A);
  266. cl::tokenizeConfigFile("\\\n", Saver, Actual, /*MarkEOLs=*/false);
  267. EXPECT_TRUE(Actual.empty());
  268. }
  269. TEST(CommandLineTest, TokenizeConfigFile9) {
  270. SmallVector<const char *, 0> Actual;
  271. BumpPtrAllocator A;
  272. StringSaver Saver(A);
  273. cl::tokenizeConfigFile("\\\r\n", Saver, Actual, /*MarkEOLs=*/false);
  274. EXPECT_TRUE(Actual.empty());
  275. }
  276. TEST(CommandLineTest, TokenizeConfigFile10) {
  277. const char *Input = "\\\nabc";
  278. const char *const Output[] = { "abc" };
  279. testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output,
  280. array_lengthof(Output));
  281. }
  282. TEST(CommandLineTest, TokenizeConfigFile11) {
  283. const char *Input = "\\\r\nabc";
  284. const char *const Output[] = { "abc" };
  285. testCommandLineTokenizer(cl::tokenizeConfigFile, Input, Output,
  286. array_lengthof(Output));
  287. }
  288. TEST(CommandLineTest, AliasesWithArguments) {
  289. static const size_t ARGC = 3;
  290. const char *const Inputs[][ARGC] = {
  291. { "-tool", "-actual=x", "-extra" },
  292. { "-tool", "-actual", "x" },
  293. { "-tool", "-alias=x", "-extra" },
  294. { "-tool", "-alias", "x" }
  295. };
  296. for (size_t i = 0, e = array_lengthof(Inputs); i < e; ++i) {
  297. StackOption<std::string> Actual("actual");
  298. StackOption<bool> Extra("extra");
  299. StackOption<std::string> Input(cl::Positional);
  300. cl::alias Alias("alias", llvm::cl::aliasopt(Actual));
  301. cl::ParseCommandLineOptions(ARGC, Inputs[i]);
  302. EXPECT_EQ("x", Actual);
  303. EXPECT_EQ(0, Input.getNumOccurrences());
  304. Alias.removeArgument();
  305. }
  306. }
  307. void testAliasRequired(int argc, const char *const *argv) {
  308. StackOption<std::string> Option("option", cl::Required);
  309. cl::alias Alias("o", llvm::cl::aliasopt(Option));
  310. cl::ParseCommandLineOptions(argc, argv);
  311. EXPECT_EQ("x", Option);
  312. EXPECT_EQ(1, Option.getNumOccurrences());
  313. Alias.removeArgument();
  314. }
  315. TEST(CommandLineTest, AliasRequired) {
  316. const char *opts1[] = { "-tool", "-option=x" };
  317. const char *opts2[] = { "-tool", "-o", "x" };
  318. testAliasRequired(array_lengthof(opts1), opts1);
  319. testAliasRequired(array_lengthof(opts2), opts2);
  320. }
  321. TEST(CommandLineTest, HideUnrelatedOptions) {
  322. StackOption<int> TestOption1("hide-option-1");
  323. StackOption<int> TestOption2("hide-option-2", cl::cat(TestCategory));
  324. cl::HideUnrelatedOptions(TestCategory);
  325. ASSERT_EQ(cl::ReallyHidden, TestOption1.getOptionHiddenFlag())
  326. << "Failed to hide extra option.";
  327. ASSERT_EQ(cl::NotHidden, TestOption2.getOptionHiddenFlag())
  328. << "Hid extra option that should be visable.";
  329. StringMap<cl::Option *> &Map =
  330. cl::getRegisteredOptions(*cl::TopLevelSubCommand);
  331. ASSERT_EQ(cl::NotHidden, Map["help"]->getOptionHiddenFlag())
  332. << "Hid default option that should be visable.";
  333. }
  334. cl::OptionCategory TestCategory2("Test Options set 2", "Description");
  335. TEST(CommandLineTest, HideUnrelatedOptionsMulti) {
  336. StackOption<int> TestOption1("multi-hide-option-1");
  337. StackOption<int> TestOption2("multi-hide-option-2", cl::cat(TestCategory));
  338. StackOption<int> TestOption3("multi-hide-option-3", cl::cat(TestCategory2));
  339. const cl::OptionCategory *VisibleCategories[] = {&TestCategory,
  340. &TestCategory2};
  341. cl::HideUnrelatedOptions(makeArrayRef(VisibleCategories));
  342. ASSERT_EQ(cl::ReallyHidden, TestOption1.getOptionHiddenFlag())
  343. << "Failed to hide extra option.";
  344. ASSERT_EQ(cl::NotHidden, TestOption2.getOptionHiddenFlag())
  345. << "Hid extra option that should be visable.";
  346. ASSERT_EQ(cl::NotHidden, TestOption3.getOptionHiddenFlag())
  347. << "Hid extra option that should be visable.";
  348. StringMap<cl::Option *> &Map =
  349. cl::getRegisteredOptions(*cl::TopLevelSubCommand);
  350. ASSERT_EQ(cl::NotHidden, Map["help"]->getOptionHiddenFlag())
  351. << "Hid default option that should be visable.";
  352. }
  353. TEST(CommandLineTest, SetValueInSubcategories) {
  354. cl::ResetCommandLineParser();
  355. StackSubCommand SC1("sc1", "First subcommand");
  356. StackSubCommand SC2("sc2", "Second subcommand");
  357. StackOption<bool> TopLevelOpt("top-level", cl::init(false));
  358. StackOption<bool> SC1Opt("sc1", cl::sub(SC1), cl::init(false));
  359. StackOption<bool> SC2Opt("sc2", cl::sub(SC2), cl::init(false));
  360. EXPECT_FALSE(TopLevelOpt);
  361. EXPECT_FALSE(SC1Opt);
  362. EXPECT_FALSE(SC2Opt);
  363. const char *args[] = {"prog", "-top-level"};
  364. EXPECT_TRUE(
  365. cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
  366. EXPECT_TRUE(TopLevelOpt);
  367. EXPECT_FALSE(SC1Opt);
  368. EXPECT_FALSE(SC2Opt);
  369. TopLevelOpt = false;
  370. cl::ResetAllOptionOccurrences();
  371. EXPECT_FALSE(TopLevelOpt);
  372. EXPECT_FALSE(SC1Opt);
  373. EXPECT_FALSE(SC2Opt);
  374. const char *args2[] = {"prog", "sc1", "-sc1"};
  375. EXPECT_TRUE(
  376. cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
  377. EXPECT_FALSE(TopLevelOpt);
  378. EXPECT_TRUE(SC1Opt);
  379. EXPECT_FALSE(SC2Opt);
  380. SC1Opt = false;
  381. cl::ResetAllOptionOccurrences();
  382. EXPECT_FALSE(TopLevelOpt);
  383. EXPECT_FALSE(SC1Opt);
  384. EXPECT_FALSE(SC2Opt);
  385. const char *args3[] = {"prog", "sc2", "-sc2"};
  386. EXPECT_TRUE(
  387. cl::ParseCommandLineOptions(3, args3, StringRef(), &llvm::nulls()));
  388. EXPECT_FALSE(TopLevelOpt);
  389. EXPECT_FALSE(SC1Opt);
  390. EXPECT_TRUE(SC2Opt);
  391. }
  392. TEST(CommandLineTest, LookupFailsInWrongSubCommand) {
  393. cl::ResetCommandLineParser();
  394. StackSubCommand SC1("sc1", "First subcommand");
  395. StackSubCommand SC2("sc2", "Second subcommand");
  396. StackOption<bool> SC1Opt("sc1", cl::sub(SC1), cl::init(false));
  397. StackOption<bool> SC2Opt("sc2", cl::sub(SC2), cl::init(false));
  398. std::string Errs;
  399. raw_string_ostream OS(Errs);
  400. const char *args[] = {"prog", "sc1", "-sc2"};
  401. EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, StringRef(), &OS));
  402. OS.flush();
  403. EXPECT_FALSE(Errs.empty());
  404. }
  405. TEST(CommandLineTest, AddToAllSubCommands) {
  406. cl::ResetCommandLineParser();
  407. StackSubCommand SC1("sc1", "First subcommand");
  408. StackOption<bool> AllOpt("everywhere", cl::sub(*cl::AllSubCommands),
  409. cl::init(false));
  410. StackSubCommand SC2("sc2", "Second subcommand");
  411. const char *args[] = {"prog", "-everywhere"};
  412. const char *args2[] = {"prog", "sc1", "-everywhere"};
  413. const char *args3[] = {"prog", "sc2", "-everywhere"};
  414. std::string Errs;
  415. raw_string_ostream OS(Errs);
  416. EXPECT_FALSE(AllOpt);
  417. EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, StringRef(), &OS));
  418. EXPECT_TRUE(AllOpt);
  419. AllOpt = false;
  420. cl::ResetAllOptionOccurrences();
  421. EXPECT_FALSE(AllOpt);
  422. EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, StringRef(), &OS));
  423. EXPECT_TRUE(AllOpt);
  424. AllOpt = false;
  425. cl::ResetAllOptionOccurrences();
  426. EXPECT_FALSE(AllOpt);
  427. EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, StringRef(), &OS));
  428. EXPECT_TRUE(AllOpt);
  429. // Since all parsing succeeded, the error message should be empty.
  430. OS.flush();
  431. EXPECT_TRUE(Errs.empty());
  432. }
  433. TEST(CommandLineTest, ReparseCommandLineOptions) {
  434. cl::ResetCommandLineParser();
  435. StackOption<bool> TopLevelOpt("top-level", cl::sub(*cl::TopLevelSubCommand),
  436. cl::init(false));
  437. const char *args[] = {"prog", "-top-level"};
  438. EXPECT_FALSE(TopLevelOpt);
  439. EXPECT_TRUE(
  440. cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
  441. EXPECT_TRUE(TopLevelOpt);
  442. TopLevelOpt = false;
  443. cl::ResetAllOptionOccurrences();
  444. EXPECT_FALSE(TopLevelOpt);
  445. EXPECT_TRUE(
  446. cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
  447. EXPECT_TRUE(TopLevelOpt);
  448. }
  449. TEST(CommandLineTest, RemoveFromRegularSubCommand) {
  450. cl::ResetCommandLineParser();
  451. StackSubCommand SC("sc", "Subcommand");
  452. StackOption<bool> RemoveOption("remove-option", cl::sub(SC), cl::init(false));
  453. StackOption<bool> KeepOption("keep-option", cl::sub(SC), cl::init(false));
  454. const char *args[] = {"prog", "sc", "-remove-option"};
  455. std::string Errs;
  456. raw_string_ostream OS(Errs);
  457. EXPECT_FALSE(RemoveOption);
  458. EXPECT_TRUE(cl::ParseCommandLineOptions(3, args, StringRef(), &OS));
  459. EXPECT_TRUE(RemoveOption);
  460. OS.flush();
  461. EXPECT_TRUE(Errs.empty());
  462. RemoveOption.removeArgument();
  463. cl::ResetAllOptionOccurrences();
  464. EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, StringRef(), &OS));
  465. OS.flush();
  466. EXPECT_FALSE(Errs.empty());
  467. }
  468. TEST(CommandLineTest, RemoveFromTopLevelSubCommand) {
  469. cl::ResetCommandLineParser();
  470. StackOption<bool> TopLevelRemove(
  471. "top-level-remove", cl::sub(*cl::TopLevelSubCommand), cl::init(false));
  472. StackOption<bool> TopLevelKeep(
  473. "top-level-keep", cl::sub(*cl::TopLevelSubCommand), cl::init(false));
  474. const char *args[] = {"prog", "-top-level-remove"};
  475. EXPECT_FALSE(TopLevelRemove);
  476. EXPECT_TRUE(
  477. cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
  478. EXPECT_TRUE(TopLevelRemove);
  479. TopLevelRemove.removeArgument();
  480. cl::ResetAllOptionOccurrences();
  481. EXPECT_FALSE(
  482. cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
  483. }
  484. TEST(CommandLineTest, RemoveFromAllSubCommands) {
  485. cl::ResetCommandLineParser();
  486. StackSubCommand SC1("sc1", "First Subcommand");
  487. StackSubCommand SC2("sc2", "Second Subcommand");
  488. StackOption<bool> RemoveOption("remove-option", cl::sub(*cl::AllSubCommands),
  489. cl::init(false));
  490. StackOption<bool> KeepOption("keep-option", cl::sub(*cl::AllSubCommands),
  491. cl::init(false));
  492. const char *args0[] = {"prog", "-remove-option"};
  493. const char *args1[] = {"prog", "sc1", "-remove-option"};
  494. const char *args2[] = {"prog", "sc2", "-remove-option"};
  495. // It should work for all subcommands including the top-level.
  496. EXPECT_FALSE(RemoveOption);
  497. EXPECT_TRUE(
  498. cl::ParseCommandLineOptions(2, args0, StringRef(), &llvm::nulls()));
  499. EXPECT_TRUE(RemoveOption);
  500. RemoveOption = false;
  501. cl::ResetAllOptionOccurrences();
  502. EXPECT_FALSE(RemoveOption);
  503. EXPECT_TRUE(
  504. cl::ParseCommandLineOptions(3, args1, StringRef(), &llvm::nulls()));
  505. EXPECT_TRUE(RemoveOption);
  506. RemoveOption = false;
  507. cl::ResetAllOptionOccurrences();
  508. EXPECT_FALSE(RemoveOption);
  509. EXPECT_TRUE(
  510. cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
  511. EXPECT_TRUE(RemoveOption);
  512. RemoveOption.removeArgument();
  513. // It should not work for any subcommands including the top-level.
  514. cl::ResetAllOptionOccurrences();
  515. EXPECT_FALSE(
  516. cl::ParseCommandLineOptions(2, args0, StringRef(), &llvm::nulls()));
  517. cl::ResetAllOptionOccurrences();
  518. EXPECT_FALSE(
  519. cl::ParseCommandLineOptions(3, args1, StringRef(), &llvm::nulls()));
  520. cl::ResetAllOptionOccurrences();
  521. EXPECT_FALSE(
  522. cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
  523. }
  524. TEST(CommandLineTest, GetRegisteredSubcommands) {
  525. cl::ResetCommandLineParser();
  526. StackSubCommand SC1("sc1", "First Subcommand");
  527. StackOption<bool> Opt1("opt1", cl::sub(SC1), cl::init(false));
  528. StackSubCommand SC2("sc2", "Second subcommand");
  529. StackOption<bool> Opt2("opt2", cl::sub(SC2), cl::init(false));
  530. const char *args0[] = {"prog", "sc1"};
  531. const char *args1[] = {"prog", "sc2"};
  532. EXPECT_TRUE(
  533. cl::ParseCommandLineOptions(2, args0, StringRef(), &llvm::nulls()));
  534. EXPECT_FALSE(Opt1);
  535. EXPECT_FALSE(Opt2);
  536. for (auto *S : cl::getRegisteredSubcommands()) {
  537. if (*S) {
  538. EXPECT_EQ("sc1", S->getName());
  539. }
  540. }
  541. cl::ResetAllOptionOccurrences();
  542. EXPECT_TRUE(
  543. cl::ParseCommandLineOptions(2, args1, StringRef(), &llvm::nulls()));
  544. EXPECT_FALSE(Opt1);
  545. EXPECT_FALSE(Opt2);
  546. for (auto *S : cl::getRegisteredSubcommands()) {
  547. if (*S) {
  548. EXPECT_EQ("sc2", S->getName());
  549. }
  550. }
  551. }
  552. TEST(CommandLineTest, DefaultOptions) {
  553. cl::ResetCommandLineParser();
  554. StackOption<std::string> Bar("bar", cl::sub(*cl::AllSubCommands),
  555. cl::DefaultOption);
  556. StackOption<std::string, cl::alias> Bar_Alias(
  557. "b", cl::desc("Alias for -bar"), cl::aliasopt(Bar), cl::DefaultOption);
  558. StackOption<bool> Foo("foo", cl::init(false), cl::sub(*cl::AllSubCommands),
  559. cl::DefaultOption);
  560. StackOption<bool, cl::alias> Foo_Alias("f", cl::desc("Alias for -foo"),
  561. cl::aliasopt(Foo), cl::DefaultOption);
  562. StackSubCommand SC1("sc1", "First Subcommand");
  563. // Override "-b" and change type in sc1 SubCommand.
  564. StackOption<bool> SC1_B("b", cl::sub(SC1), cl::init(false));
  565. StackSubCommand SC2("sc2", "Second subcommand");
  566. // Override "-foo" and change type in sc2 SubCommand. Note that this does not
  567. // affect "-f" alias, which continues to work correctly.
  568. StackOption<std::string> SC2_Foo("foo", cl::sub(SC2));
  569. const char *args0[] = {"prog", "-b", "args0 bar string", "-f"};
  570. EXPECT_TRUE(cl::ParseCommandLineOptions(sizeof(args0) / sizeof(char *), args0,
  571. StringRef(), &llvm::nulls()));
  572. EXPECT_TRUE(Bar == "args0 bar string");
  573. EXPECT_TRUE(Foo);
  574. EXPECT_FALSE(SC1_B);
  575. EXPECT_TRUE(SC2_Foo.empty());
  576. cl::ResetAllOptionOccurrences();
  577. const char *args1[] = {"prog", "sc1", "-b", "-bar", "args1 bar string", "-f"};
  578. EXPECT_TRUE(cl::ParseCommandLineOptions(sizeof(args1) / sizeof(char *), args1,
  579. StringRef(), &llvm::nulls()));
  580. EXPECT_TRUE(Bar == "args1 bar string");
  581. EXPECT_TRUE(Foo);
  582. EXPECT_TRUE(SC1_B);
  583. EXPECT_TRUE(SC2_Foo.empty());
  584. for (auto *S : cl::getRegisteredSubcommands()) {
  585. if (*S) {
  586. EXPECT_EQ("sc1", S->getName());
  587. }
  588. }
  589. cl::ResetAllOptionOccurrences();
  590. const char *args2[] = {"prog", "sc2", "-b", "args2 bar string",
  591. "-f", "-foo", "foo string"};
  592. EXPECT_TRUE(cl::ParseCommandLineOptions(sizeof(args2) / sizeof(char *), args2,
  593. StringRef(), &llvm::nulls()));
  594. EXPECT_TRUE(Bar == "args2 bar string");
  595. EXPECT_TRUE(Foo);
  596. EXPECT_FALSE(SC1_B);
  597. EXPECT_TRUE(SC2_Foo == "foo string");
  598. for (auto *S : cl::getRegisteredSubcommands()) {
  599. if (*S) {
  600. EXPECT_EQ("sc2", S->getName());
  601. }
  602. }
  603. cl::ResetCommandLineParser();
  604. }
  605. TEST(CommandLineTest, ArgumentLimit) {
  606. std::string args(32 * 4096, 'a');
  607. EXPECT_FALSE(llvm::sys::commandLineFitsWithinSystemLimits("cl", args.data()));
  608. }
  609. TEST(CommandLineTest, ResponseFileWindows) {
  610. if (!Triple(sys::getProcessTriple()).isOSWindows())
  611. return;
  612. StackOption<std::string, cl::list<std::string>> InputFilenames(
  613. cl::Positional, cl::desc("<input files>"), cl::ZeroOrMore);
  614. StackOption<bool> TopLevelOpt("top-level", cl::init(false));
  615. // Create response file.
  616. int FileDescriptor;
  617. SmallString<64> TempPath;
  618. std::error_code EC =
  619. llvm::sys::fs::createTemporaryFile("resp-", ".txt", FileDescriptor, TempPath);
  620. EXPECT_TRUE(!EC);
  621. std::ofstream RspFile(TempPath.c_str());
  622. EXPECT_TRUE(RspFile.is_open());
  623. RspFile << "-top-level\npath\\dir\\file1\npath/dir/file2";
  624. RspFile.close();
  625. llvm::SmallString<128> RspOpt;
  626. RspOpt.append(1, '@');
  627. RspOpt.append(TempPath.c_str());
  628. const char *args[] = {"prog", RspOpt.c_str()};
  629. EXPECT_FALSE(TopLevelOpt);
  630. EXPECT_TRUE(
  631. cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
  632. EXPECT_TRUE(TopLevelOpt);
  633. EXPECT_TRUE(InputFilenames[0] == "path\\dir\\file1");
  634. EXPECT_TRUE(InputFilenames[1] == "path/dir/file2");
  635. llvm::sys::fs::remove(TempPath.c_str());
  636. }
  637. TEST(CommandLineTest, ResponseFiles) {
  638. llvm::SmallString<128> TestDir;
  639. std::error_code EC =
  640. llvm::sys::fs::createUniqueDirectory("unittest", TestDir);
  641. EXPECT_TRUE(!EC);
  642. // Create included response file of first level.
  643. llvm::SmallString<128> IncludedFileName;
  644. llvm::sys::path::append(IncludedFileName, TestDir, "resp1");
  645. std::ofstream IncludedFile(IncludedFileName.c_str());
  646. EXPECT_TRUE(IncludedFile.is_open());
  647. IncludedFile << "-option_1 -option_2\n"
  648. "@incdir/resp2\n"
  649. "-option_3=abcd\n"
  650. "@incdir/resp3\n"
  651. "-option_4=efjk\n";
  652. IncludedFile.close();
  653. // Directory for included file.
  654. llvm::SmallString<128> IncDir;
  655. llvm::sys::path::append(IncDir, TestDir, "incdir");
  656. EC = llvm::sys::fs::create_directory(IncDir);
  657. EXPECT_TRUE(!EC);
  658. // Create included response file of second level.
  659. llvm::SmallString<128> IncludedFileName2;
  660. llvm::sys::path::append(IncludedFileName2, IncDir, "resp2");
  661. std::ofstream IncludedFile2(IncludedFileName2.c_str());
  662. EXPECT_TRUE(IncludedFile2.is_open());
  663. IncludedFile2 << "-option_21 -option_22\n";
  664. IncludedFile2 << "-option_23=abcd\n";
  665. IncludedFile2.close();
  666. // Create second included response file of second level.
  667. llvm::SmallString<128> IncludedFileName3;
  668. llvm::sys::path::append(IncludedFileName3, IncDir, "resp3");
  669. std::ofstream IncludedFile3(IncludedFileName3.c_str());
  670. EXPECT_TRUE(IncludedFile3.is_open());
  671. IncludedFile3 << "-option_31 -option_32\n";
  672. IncludedFile3 << "-option_33=abcd\n";
  673. IncludedFile3.close();
  674. // Prepare 'file' with reference to response file.
  675. SmallString<128> IncRef;
  676. IncRef.append(1, '@');
  677. IncRef.append(IncludedFileName.c_str());
  678. llvm::SmallVector<const char *, 4> Argv =
  679. { "test/test", "-flag_1", IncRef.c_str(), "-flag_2" };
  680. // Expand response files.
  681. llvm::BumpPtrAllocator A;
  682. llvm::StringSaver Saver(A);
  683. bool Res = llvm::cl::ExpandResponseFiles(
  684. Saver, llvm::cl::TokenizeGNUCommandLine, Argv, false, true);
  685. EXPECT_TRUE(Res);
  686. EXPECT_EQ(Argv.size(), 13U);
  687. EXPECT_STREQ(Argv[0], "test/test");
  688. EXPECT_STREQ(Argv[1], "-flag_1");
  689. EXPECT_STREQ(Argv[2], "-option_1");
  690. EXPECT_STREQ(Argv[3], "-option_2");
  691. EXPECT_STREQ(Argv[4], "-option_21");
  692. EXPECT_STREQ(Argv[5], "-option_22");
  693. EXPECT_STREQ(Argv[6], "-option_23=abcd");
  694. EXPECT_STREQ(Argv[7], "-option_3=abcd");
  695. EXPECT_STREQ(Argv[8], "-option_31");
  696. EXPECT_STREQ(Argv[9], "-option_32");
  697. EXPECT_STREQ(Argv[10], "-option_33=abcd");
  698. EXPECT_STREQ(Argv[11], "-option_4=efjk");
  699. EXPECT_STREQ(Argv[12], "-flag_2");
  700. llvm::sys::fs::remove(IncludedFileName3);
  701. llvm::sys::fs::remove(IncludedFileName2);
  702. llvm::sys::fs::remove(IncDir);
  703. llvm::sys::fs::remove(IncludedFileName);
  704. llvm::sys::fs::remove(TestDir);
  705. }
  706. TEST(CommandLineTest, RecursiveResponseFiles) {
  707. SmallString<128> TestDir;
  708. std::error_code EC = sys::fs::createUniqueDirectory("unittest", TestDir);
  709. EXPECT_TRUE(!EC);
  710. SmallString<128> SelfFilePath;
  711. sys::path::append(SelfFilePath, TestDir, "self.rsp");
  712. std::string SelfFileRef = std::string("@") + SelfFilePath.c_str();
  713. SmallString<128> NestedFilePath;
  714. sys::path::append(NestedFilePath, TestDir, "nested.rsp");
  715. std::string NestedFileRef = std::string("@") + NestedFilePath.c_str();
  716. SmallString<128> FlagFilePath;
  717. sys::path::append(FlagFilePath, TestDir, "flag.rsp");
  718. std::string FlagFileRef = std::string("@") + FlagFilePath.c_str();
  719. std::ofstream SelfFile(SelfFilePath.str());
  720. EXPECT_TRUE(SelfFile.is_open());
  721. SelfFile << "-option_1\n";
  722. SelfFile << FlagFileRef << "\n";
  723. SelfFile << NestedFileRef << "\n";
  724. SelfFile << SelfFileRef << "\n";
  725. SelfFile.close();
  726. std::ofstream NestedFile(NestedFilePath.str());
  727. EXPECT_TRUE(NestedFile.is_open());
  728. NestedFile << "-option_2\n";
  729. NestedFile << FlagFileRef << "\n";
  730. NestedFile << SelfFileRef << "\n";
  731. NestedFile << NestedFileRef << "\n";
  732. NestedFile.close();
  733. std::ofstream FlagFile(FlagFilePath.str());
  734. EXPECT_TRUE(FlagFile.is_open());
  735. FlagFile << "-option_x\n";
  736. FlagFile.close();
  737. // Ensure:
  738. // Recursive expansion terminates
  739. // Recursive files never expand
  740. // Non-recursive repeats are allowed
  741. SmallVector<const char *, 4> Argv = {"test/test", SelfFileRef.c_str(),
  742. "-option_3"};
  743. BumpPtrAllocator A;
  744. StringSaver Saver(A);
  745. #ifdef _WIN32
  746. cl::TokenizerCallback Tokenizer = cl::TokenizeWindowsCommandLine;
  747. #else
  748. cl::TokenizerCallback Tokenizer = cl::TokenizeGNUCommandLine;
  749. #endif
  750. bool Res = cl::ExpandResponseFiles(Saver, Tokenizer, Argv, false, false);
  751. EXPECT_FALSE(Res);
  752. EXPECT_EQ(Argv.size(), 9U);
  753. EXPECT_STREQ(Argv[0], "test/test");
  754. EXPECT_STREQ(Argv[1], "-option_1");
  755. EXPECT_STREQ(Argv[2], "-option_x");
  756. EXPECT_STREQ(Argv[3], "-option_2");
  757. EXPECT_STREQ(Argv[4], "-option_x");
  758. EXPECT_STREQ(Argv[5], SelfFileRef.c_str());
  759. EXPECT_STREQ(Argv[6], NestedFileRef.c_str());
  760. EXPECT_STREQ(Argv[7], SelfFileRef.c_str());
  761. EXPECT_STREQ(Argv[8], "-option_3");
  762. }
  763. TEST(CommandLineTest, ResponseFilesAtArguments) {
  764. SmallString<128> TestDir;
  765. std::error_code EC = sys::fs::createUniqueDirectory("unittest", TestDir);
  766. EXPECT_TRUE(!EC);
  767. SmallString<128> ResponseFilePath;
  768. sys::path::append(ResponseFilePath, TestDir, "test.rsp");
  769. std::ofstream ResponseFile(ResponseFilePath.c_str());
  770. EXPECT_TRUE(ResponseFile.is_open());
  771. ResponseFile << "-foo" << "\n";
  772. ResponseFile << "-bar" << "\n";
  773. ResponseFile.close();
  774. // Ensure we expand rsp files after lots of non-rsp arguments starting with @.
  775. constexpr size_t NON_RSP_AT_ARGS = 64;
  776. SmallVector<const char *, 4> Argv = {"test/test"};
  777. Argv.append(NON_RSP_AT_ARGS, "@non_rsp_at_arg");
  778. std::string ResponseFileRef = std::string("@") + ResponseFilePath.c_str();
  779. Argv.push_back(ResponseFileRef.c_str());
  780. BumpPtrAllocator A;
  781. StringSaver Saver(A);
  782. bool Res = cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Argv,
  783. false, false);
  784. EXPECT_FALSE(Res);
  785. // ASSERT instead of EXPECT to prevent potential out-of-bounds access.
  786. ASSERT_EQ(Argv.size(), 1 + NON_RSP_AT_ARGS + 2);
  787. size_t i = 0;
  788. EXPECT_STREQ(Argv[i++], "test/test");
  789. for (; i < 1 + NON_RSP_AT_ARGS; ++i)
  790. EXPECT_STREQ(Argv[i], "@non_rsp_at_arg");
  791. EXPECT_STREQ(Argv[i++], "-foo");
  792. EXPECT_STREQ(Argv[i++], "-bar");
  793. }
  794. TEST(CommandLineTest, SetDefautValue) {
  795. cl::ResetCommandLineParser();
  796. StackOption<std::string> Opt1("opt1", cl::init("true"));
  797. StackOption<bool> Opt2("opt2", cl::init(true));
  798. cl::alias Alias("alias", llvm::cl::aliasopt(Opt2));
  799. StackOption<int> Opt3("opt3", cl::init(3));
  800. const char *args[] = {"prog", "-opt1=false", "-opt2", "-opt3"};
  801. EXPECT_TRUE(
  802. cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
  803. EXPECT_TRUE(Opt1 == "false");
  804. EXPECT_TRUE(Opt2);
  805. EXPECT_TRUE(Opt3 == 3);
  806. Opt2 = false;
  807. Opt3 = 1;
  808. cl::ResetAllOptionOccurrences();
  809. for (auto &OM : cl::getRegisteredOptions(*cl::TopLevelSubCommand)) {
  810. cl::Option *O = OM.second;
  811. if (O->ArgStr == "opt2") {
  812. continue;
  813. }
  814. O->setDefault();
  815. }
  816. EXPECT_TRUE(Opt1 == "true");
  817. EXPECT_TRUE(Opt2);
  818. EXPECT_TRUE(Opt3 == 3);
  819. Alias.removeArgument();
  820. }
  821. TEST(CommandLineTest, ReadConfigFile) {
  822. llvm::SmallVector<const char *, 1> Argv;
  823. llvm::SmallString<128> TestDir;
  824. std::error_code EC =
  825. llvm::sys::fs::createUniqueDirectory("unittest", TestDir);
  826. EXPECT_TRUE(!EC);
  827. llvm::SmallString<128> TestCfg;
  828. llvm::sys::path::append(TestCfg, TestDir, "foo");
  829. std::ofstream ConfigFile(TestCfg.c_str());
  830. EXPECT_TRUE(ConfigFile.is_open());
  831. ConfigFile << "# Comment\n"
  832. "-option_1\n"
  833. "@subconfig\n"
  834. "-option_3=abcd\n"
  835. "-option_4=\\\n"
  836. "cdef\n";
  837. ConfigFile.close();
  838. llvm::SmallString<128> TestCfg2;
  839. llvm::sys::path::append(TestCfg2, TestDir, "subconfig");
  840. std::ofstream ConfigFile2(TestCfg2.c_str());
  841. EXPECT_TRUE(ConfigFile2.is_open());
  842. ConfigFile2 << "-option_2\n"
  843. "\n"
  844. " # comment\n";
  845. ConfigFile2.close();
  846. // Make sure the current directory is not the directory where config files
  847. // resides. In this case the code that expands response files will not find
  848. // 'subconfig' unless it resolves nested inclusions relative to the including
  849. // file.
  850. llvm::SmallString<128> CurrDir;
  851. EC = llvm::sys::fs::current_path(CurrDir);
  852. EXPECT_TRUE(!EC);
  853. EXPECT_TRUE(StringRef(CurrDir) != StringRef(TestDir));
  854. llvm::BumpPtrAllocator A;
  855. llvm::StringSaver Saver(A);
  856. bool Result = llvm::cl::readConfigFile(TestCfg, Saver, Argv);
  857. EXPECT_TRUE(Result);
  858. EXPECT_EQ(Argv.size(), 4U);
  859. EXPECT_STREQ(Argv[0], "-option_1");
  860. EXPECT_STREQ(Argv[1], "-option_2");
  861. EXPECT_STREQ(Argv[2], "-option_3=abcd");
  862. EXPECT_STREQ(Argv[3], "-option_4=cdef");
  863. llvm::sys::fs::remove(TestCfg2);
  864. llvm::sys::fs::remove(TestCfg);
  865. llvm::sys::fs::remove(TestDir);
  866. }
  867. TEST(CommandLineTest, PositionalEatArgsError) {
  868. cl::ResetCommandLineParser();
  869. StackOption<std::string, cl::list<std::string>> PosEatArgs(
  870. "positional-eat-args", cl::Positional, cl::desc("<arguments>..."),
  871. cl::ZeroOrMore, cl::PositionalEatsArgs);
  872. StackOption<std::string, cl::list<std::string>> PosEatArgs2(
  873. "positional-eat-args2", cl::Positional, cl::desc("Some strings"),
  874. cl::ZeroOrMore, cl::PositionalEatsArgs);
  875. const char *args[] = {"prog", "-positional-eat-args=XXXX"};
  876. const char *args2[] = {"prog", "-positional-eat-args=XXXX", "-foo"};
  877. const char *args3[] = {"prog", "-positional-eat-args", "-foo"};
  878. const char *args4[] = {"prog", "-positional-eat-args",
  879. "-foo", "-positional-eat-args2",
  880. "-bar", "foo"};
  881. std::string Errs;
  882. raw_string_ostream OS(Errs);
  883. EXPECT_FALSE(cl::ParseCommandLineOptions(2, args, StringRef(), &OS)); OS.flush();
  884. EXPECT_FALSE(Errs.empty()); Errs.clear();
  885. EXPECT_FALSE(cl::ParseCommandLineOptions(3, args2, StringRef(), &OS)); OS.flush();
  886. EXPECT_FALSE(Errs.empty()); Errs.clear();
  887. EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, StringRef(), &OS)); OS.flush();
  888. EXPECT_TRUE(Errs.empty()); Errs.clear();
  889. cl::ResetAllOptionOccurrences();
  890. EXPECT_TRUE(cl::ParseCommandLineOptions(6, args4, StringRef(), &OS)); OS.flush();
  891. EXPECT_TRUE(PosEatArgs.size() == 1);
  892. EXPECT_TRUE(PosEatArgs2.size() == 2);
  893. EXPECT_TRUE(Errs.empty());
  894. }
  895. #ifdef _WIN32
  896. TEST(CommandLineTest, GetCommandLineArguments) {
  897. int argc = __argc;
  898. char **argv = __argv;
  899. // GetCommandLineArguments is called in InitLLVM.
  900. llvm::InitLLVM X(argc, argv);
  901. EXPECT_EQ(llvm::sys::path::is_absolute(argv[0]),
  902. llvm::sys::path::is_absolute(__argv[0]));
  903. EXPECT_TRUE(llvm::sys::path::filename(argv[0])
  904. .equals_lower("supporttests.exe"))
  905. << "Filename of test executable is "
  906. << llvm::sys::path::filename(argv[0]);
  907. }
  908. #endif
  909. class OutputRedirector {
  910. public:
  911. OutputRedirector(int RedirectFD)
  912. : RedirectFD(RedirectFD), OldFD(dup(RedirectFD)) {
  913. if (OldFD == -1 ||
  914. sys::fs::createTemporaryFile("unittest-redirect", "", NewFD,
  915. FilePath) ||
  916. dup2(NewFD, RedirectFD) == -1)
  917. Valid = false;
  918. }
  919. ~OutputRedirector() {
  920. dup2(OldFD, RedirectFD);
  921. close(OldFD);
  922. close(NewFD);
  923. }
  924. SmallVector<char, 128> FilePath;
  925. bool Valid = true;
  926. private:
  927. int RedirectFD;
  928. int OldFD;
  929. int NewFD;
  930. };
  931. struct AutoDeleteFile {
  932. SmallVector<char, 128> FilePath;
  933. ~AutoDeleteFile() {
  934. if (!FilePath.empty())
  935. sys::fs::remove(std::string(FilePath.data(), FilePath.size()));
  936. }
  937. };
  938. class PrintOptionInfoTest : public ::testing::Test {
  939. public:
  940. // Return std::string because the output of a failing EXPECT check is
  941. // unreadable for StringRef. It also avoids any lifetime issues.
  942. template <typename... Ts> std::string runTest(Ts... OptionAttributes) {
  943. outs().flush(); // flush any output from previous tests
  944. AutoDeleteFile File;
  945. {
  946. OutputRedirector Stdout(fileno(stdout));
  947. if (!Stdout.Valid)
  948. return "";
  949. File.FilePath = Stdout.FilePath;
  950. StackOption<OptionValue> TestOption(Opt, cl::desc(HelpText),
  951. OptionAttributes...);
  952. printOptionInfo(TestOption, 26);
  953. outs().flush();
  954. }
  955. auto Buffer = MemoryBuffer::getFile(File.FilePath);
  956. if (!Buffer)
  957. return "";
  958. return Buffer->get()->getBuffer().str();
  959. }
  960. enum class OptionValue { Val };
  961. const StringRef Opt = "some-option";
  962. const StringRef HelpText = "some help";
  963. private:
  964. // This is a workaround for cl::Option sub-classes having their
  965. // printOptionInfo functions private.
  966. void printOptionInfo(const cl::Option &O, size_t Width) {
  967. O.printOptionInfo(Width);
  968. }
  969. };
  970. TEST_F(PrintOptionInfoTest, PrintOptionInfoValueOptionalWithoutSentinel) {
  971. std::string Output =
  972. runTest(cl::ValueOptional,
  973. cl::values(clEnumValN(OptionValue::Val, "v1", "desc1")));
  974. // clang-format off
  975. EXPECT_EQ(Output, (" --" + Opt + "=<value> - " + HelpText + "\n"
  976. " =v1 - desc1\n")
  977. .str());
  978. // clang-format on
  979. }
  980. TEST_F(PrintOptionInfoTest, PrintOptionInfoValueOptionalWithSentinel) {
  981. std::string Output = runTest(
  982. cl::ValueOptional, cl::values(clEnumValN(OptionValue::Val, "v1", "desc1"),
  983. clEnumValN(OptionValue::Val, "", "")));
  984. // clang-format off
  985. EXPECT_EQ(Output,
  986. (" --" + Opt + " - " + HelpText + "\n"
  987. " --" + Opt + "=<value> - " + HelpText + "\n"
  988. " =v1 - desc1\n")
  989. .str());
  990. // clang-format on
  991. }
  992. TEST_F(PrintOptionInfoTest, PrintOptionInfoValueOptionalWithSentinelWithHelp) {
  993. std::string Output = runTest(
  994. cl::ValueOptional, cl::values(clEnumValN(OptionValue::Val, "v1", "desc1"),
  995. clEnumValN(OptionValue::Val, "", "desc2")));
  996. // clang-format off
  997. EXPECT_EQ(Output, (" --" + Opt + " - " + HelpText + "\n"
  998. " --" + Opt + "=<value> - " + HelpText + "\n"
  999. " =v1 - desc1\n"
  1000. " =<empty> - desc2\n")
  1001. .str());
  1002. // clang-format on
  1003. }
  1004. TEST_F(PrintOptionInfoTest, PrintOptionInfoValueRequiredWithEmptyValueName) {
  1005. std::string Output = runTest(
  1006. cl::ValueRequired, cl::values(clEnumValN(OptionValue::Val, "v1", "desc1"),
  1007. clEnumValN(OptionValue::Val, "", "")));
  1008. // clang-format off
  1009. EXPECT_EQ(Output, (" --" + Opt + "=<value> - " + HelpText + "\n"
  1010. " =v1 - desc1\n"
  1011. " =<empty>\n")
  1012. .str());
  1013. // clang-format on
  1014. }
  1015. TEST_F(PrintOptionInfoTest, PrintOptionInfoEmptyValueDescription) {
  1016. std::string Output = runTest(
  1017. cl::ValueRequired, cl::values(clEnumValN(OptionValue::Val, "v1", "")));
  1018. // clang-format off
  1019. EXPECT_EQ(Output,
  1020. (" --" + Opt + "=<value> - " + HelpText + "\n"
  1021. " =v1\n").str());
  1022. // clang-format on
  1023. }
  1024. class GetOptionWidthTest : public ::testing::Test {
  1025. public:
  1026. enum class OptionValue { Val };
  1027. template <typename... Ts>
  1028. size_t runTest(StringRef ArgName, Ts... OptionAttributes) {
  1029. StackOption<OptionValue> TestOption(ArgName, cl::desc("some help"),
  1030. OptionAttributes...);
  1031. return getOptionWidth(TestOption);
  1032. }
  1033. private:
  1034. // This is a workaround for cl::Option sub-classes having their
  1035. // printOptionInfo
  1036. // functions private.
  1037. size_t getOptionWidth(const cl::Option &O) { return O.getOptionWidth(); }
  1038. };
  1039. TEST_F(GetOptionWidthTest, GetOptionWidthArgNameLonger) {
  1040. StringRef ArgName("a-long-argument-name");
  1041. size_t ExpectedStrSize = (" --" + ArgName + "=<value> - ").str().size();
  1042. EXPECT_EQ(
  1043. runTest(ArgName, cl::values(clEnumValN(OptionValue::Val, "v", "help"))),
  1044. ExpectedStrSize);
  1045. }
  1046. TEST_F(GetOptionWidthTest, GetOptionWidthFirstOptionNameLonger) {
  1047. StringRef OptName("a-long-option-name");
  1048. size_t ExpectedStrSize = (" =" + OptName + " - ").str().size();
  1049. EXPECT_EQ(
  1050. runTest("a", cl::values(clEnumValN(OptionValue::Val, OptName, "help"),
  1051. clEnumValN(OptionValue::Val, "b", "help"))),
  1052. ExpectedStrSize);
  1053. }
  1054. TEST_F(GetOptionWidthTest, GetOptionWidthSecondOptionNameLonger) {
  1055. StringRef OptName("a-long-option-name");
  1056. size_t ExpectedStrSize = (" =" + OptName + " - ").str().size();
  1057. EXPECT_EQ(
  1058. runTest("a", cl::values(clEnumValN(OptionValue::Val, "b", "help"),
  1059. clEnumValN(OptionValue::Val, OptName, "help"))),
  1060. ExpectedStrSize);
  1061. }
  1062. TEST_F(GetOptionWidthTest, GetOptionWidthEmptyOptionNameLonger) {
  1063. size_t ExpectedStrSize = StringRef(" =<empty> - ").size();
  1064. // The length of a=<value> (including indentation) is actually the same as the
  1065. // =<empty> string, so it is impossible to distinguish via testing the case
  1066. // where the empty string is picked from where the option name is picked.
  1067. EXPECT_EQ(runTest("a", cl::values(clEnumValN(OptionValue::Val, "b", "help"),
  1068. clEnumValN(OptionValue::Val, "", "help"))),
  1069. ExpectedStrSize);
  1070. }
  1071. TEST_F(GetOptionWidthTest,
  1072. GetOptionWidthValueOptionalEmptyOptionWithNoDescription) {
  1073. StringRef ArgName("a");
  1074. // The length of a=<value> (including indentation) is actually the same as the
  1075. // =<empty> string, so it is impossible to distinguish via testing the case
  1076. // where the empty string is ignored from where it is not ignored.
  1077. // The dash will not actually be printed, but the space it would take up is
  1078. // included to ensure a consistent column width.
  1079. size_t ExpectedStrSize = (" -" + ArgName + "=<value> - ").str().size();
  1080. EXPECT_EQ(runTest(ArgName, cl::ValueOptional,
  1081. cl::values(clEnumValN(OptionValue::Val, "value", "help"),
  1082. clEnumValN(OptionValue::Val, "", ""))),
  1083. ExpectedStrSize);
  1084. }
  1085. TEST_F(GetOptionWidthTest,
  1086. GetOptionWidthValueRequiredEmptyOptionWithNoDescription) {
  1087. // The length of a=<value> (including indentation) is actually the same as the
  1088. // =<empty> string, so it is impossible to distinguish via testing the case
  1089. // where the empty string is picked from where the option name is picked
  1090. size_t ExpectedStrSize = StringRef(" =<empty> - ").size();
  1091. EXPECT_EQ(runTest("a", cl::ValueRequired,
  1092. cl::values(clEnumValN(OptionValue::Val, "value", "help"),
  1093. clEnumValN(OptionValue::Val, "", ""))),
  1094. ExpectedStrSize);
  1095. }
  1096. TEST(CommandLineTest, PrefixOptions) {
  1097. cl::ResetCommandLineParser();
  1098. StackOption<std::string, cl::list<std::string>> IncludeDirs(
  1099. "I", cl::Prefix, cl::desc("Declare an include directory"));
  1100. // Test non-prefixed variant works with cl::Prefix options.
  1101. EXPECT_TRUE(IncludeDirs.empty());
  1102. const char *args[] = {"prog", "-I=/usr/include"};
  1103. EXPECT_TRUE(
  1104. cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
  1105. EXPECT_TRUE(IncludeDirs.size() == 1);
  1106. EXPECT_TRUE(IncludeDirs.front().compare("/usr/include") == 0);
  1107. IncludeDirs.erase(IncludeDirs.begin());
  1108. cl::ResetAllOptionOccurrences();
  1109. // Test non-prefixed variant works with cl::Prefix options when value is
  1110. // passed in following argument.
  1111. EXPECT_TRUE(IncludeDirs.empty());
  1112. const char *args2[] = {"prog", "-I", "/usr/include"};
  1113. EXPECT_TRUE(
  1114. cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
  1115. EXPECT_TRUE(IncludeDirs.size() == 1);
  1116. EXPECT_TRUE(IncludeDirs.front().compare("/usr/include") == 0);
  1117. IncludeDirs.erase(IncludeDirs.begin());
  1118. cl::ResetAllOptionOccurrences();
  1119. // Test prefixed variant works with cl::Prefix options.
  1120. EXPECT_TRUE(IncludeDirs.empty());
  1121. const char *args3[] = {"prog", "-I/usr/include"};
  1122. EXPECT_TRUE(
  1123. cl::ParseCommandLineOptions(2, args3, StringRef(), &llvm::nulls()));
  1124. EXPECT_TRUE(IncludeDirs.size() == 1);
  1125. EXPECT_TRUE(IncludeDirs.front().compare("/usr/include") == 0);
  1126. StackOption<std::string, cl::list<std::string>> MacroDefs(
  1127. "D", cl::AlwaysPrefix, cl::desc("Define a macro"),
  1128. cl::value_desc("MACRO[=VALUE]"));
  1129. cl::ResetAllOptionOccurrences();
  1130. // Test non-prefixed variant does not work with cl::AlwaysPrefix options:
  1131. // equal sign is part of the value.
  1132. EXPECT_TRUE(MacroDefs.empty());
  1133. const char *args4[] = {"prog", "-D=HAVE_FOO"};
  1134. EXPECT_TRUE(
  1135. cl::ParseCommandLineOptions(2, args4, StringRef(), &llvm::nulls()));
  1136. EXPECT_TRUE(MacroDefs.size() == 1);
  1137. EXPECT_TRUE(MacroDefs.front().compare("=HAVE_FOO") == 0);
  1138. MacroDefs.erase(MacroDefs.begin());
  1139. cl::ResetAllOptionOccurrences();
  1140. // Test non-prefixed variant does not allow value to be passed in following
  1141. // argument with cl::AlwaysPrefix options.
  1142. EXPECT_TRUE(MacroDefs.empty());
  1143. const char *args5[] = {"prog", "-D", "HAVE_FOO"};
  1144. EXPECT_FALSE(
  1145. cl::ParseCommandLineOptions(3, args5, StringRef(), &llvm::nulls()));
  1146. EXPECT_TRUE(MacroDefs.empty());
  1147. cl::ResetAllOptionOccurrences();
  1148. // Test prefixed variant works with cl::AlwaysPrefix options.
  1149. EXPECT_TRUE(MacroDefs.empty());
  1150. const char *args6[] = {"prog", "-DHAVE_FOO"};
  1151. EXPECT_TRUE(
  1152. cl::ParseCommandLineOptions(2, args6, StringRef(), &llvm::nulls()));
  1153. EXPECT_TRUE(MacroDefs.size() == 1);
  1154. EXPECT_TRUE(MacroDefs.front().compare("HAVE_FOO") == 0);
  1155. }
  1156. TEST(CommandLineTest, GroupingWithValue) {
  1157. cl::ResetCommandLineParser();
  1158. StackOption<bool> OptF("f", cl::Grouping, cl::desc("Some flag"));
  1159. StackOption<bool> OptB("b", cl::Grouping, cl::desc("Another flag"));
  1160. StackOption<bool> OptD("d", cl::Grouping, cl::ValueDisallowed,
  1161. cl::desc("ValueDisallowed option"));
  1162. StackOption<std::string> OptV("v", cl::Grouping,
  1163. cl::desc("ValueRequired option"));
  1164. StackOption<std::string> OptO("o", cl::Grouping, cl::ValueOptional,
  1165. cl::desc("ValueOptional option"));
  1166. // Should be possible to use an option which requires a value
  1167. // at the end of a group.
  1168. const char *args1[] = {"prog", "-fv", "val1"};
  1169. EXPECT_TRUE(
  1170. cl::ParseCommandLineOptions(3, args1, StringRef(), &llvm::nulls()));
  1171. EXPECT_TRUE(OptF);
  1172. EXPECT_STREQ("val1", OptV.c_str());
  1173. OptV.clear();
  1174. cl::ResetAllOptionOccurrences();
  1175. // Should not crash if it is accidentally used elsewhere in the group.
  1176. const char *args2[] = {"prog", "-vf", "val2"};
  1177. EXPECT_FALSE(
  1178. cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
  1179. OptV.clear();
  1180. cl::ResetAllOptionOccurrences();
  1181. // Should allow the "opt=value" form at the end of the group
  1182. const char *args3[] = {"prog", "-fv=val3"};
  1183. EXPECT_TRUE(
  1184. cl::ParseCommandLineOptions(2, args3, StringRef(), &llvm::nulls()));
  1185. EXPECT_TRUE(OptF);
  1186. EXPECT_STREQ("val3", OptV.c_str());
  1187. OptV.clear();
  1188. cl::ResetAllOptionOccurrences();
  1189. // Should allow assigning a value for a ValueOptional option
  1190. // at the end of the group
  1191. const char *args4[] = {"prog", "-fo=val4"};
  1192. EXPECT_TRUE(
  1193. cl::ParseCommandLineOptions(2, args4, StringRef(), &llvm::nulls()));
  1194. EXPECT_TRUE(OptF);
  1195. EXPECT_STREQ("val4", OptO.c_str());
  1196. OptO.clear();
  1197. cl::ResetAllOptionOccurrences();
  1198. // Should assign an empty value if a ValueOptional option is used elsewhere
  1199. // in the group.
  1200. const char *args5[] = {"prog", "-fob"};
  1201. EXPECT_TRUE(
  1202. cl::ParseCommandLineOptions(2, args5, StringRef(), &llvm::nulls()));
  1203. EXPECT_TRUE(OptF);
  1204. EXPECT_EQ(1, OptO.getNumOccurrences());
  1205. EXPECT_EQ(1, OptB.getNumOccurrences());
  1206. EXPECT_TRUE(OptO.empty());
  1207. cl::ResetAllOptionOccurrences();
  1208. // Should not allow an assignment for a ValueDisallowed option.
  1209. const char *args6[] = {"prog", "-fd=false"};
  1210. EXPECT_FALSE(
  1211. cl::ParseCommandLineOptions(2, args6, StringRef(), &llvm::nulls()));
  1212. }
  1213. TEST(CommandLineTest, GroupingAndPrefix) {
  1214. cl::ResetCommandLineParser();
  1215. StackOption<bool> OptF("f", cl::Grouping, cl::desc("Some flag"));
  1216. StackOption<bool> OptB("b", cl::Grouping, cl::desc("Another flag"));
  1217. StackOption<std::string> OptP("p", cl::Prefix, cl::Grouping,
  1218. cl::desc("Prefix and Grouping"));
  1219. StackOption<std::string> OptA("a", cl::AlwaysPrefix, cl::Grouping,
  1220. cl::desc("AlwaysPrefix and Grouping"));
  1221. // Should be possible to use a cl::Prefix option without grouping.
  1222. const char *args1[] = {"prog", "-pval1"};
  1223. EXPECT_TRUE(
  1224. cl::ParseCommandLineOptions(2, args1, StringRef(), &llvm::nulls()));
  1225. EXPECT_STREQ("val1", OptP.c_str());
  1226. OptP.clear();
  1227. cl::ResetAllOptionOccurrences();
  1228. // Should be possible to pass a value in a separate argument.
  1229. const char *args2[] = {"prog", "-p", "val2"};
  1230. EXPECT_TRUE(
  1231. cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
  1232. EXPECT_STREQ("val2", OptP.c_str());
  1233. OptP.clear();
  1234. cl::ResetAllOptionOccurrences();
  1235. // The "-opt=value" form should work, too.
  1236. const char *args3[] = {"prog", "-p=val3"};
  1237. EXPECT_TRUE(
  1238. cl::ParseCommandLineOptions(2, args3, StringRef(), &llvm::nulls()));
  1239. EXPECT_STREQ("val3", OptP.c_str());
  1240. OptP.clear();
  1241. cl::ResetAllOptionOccurrences();
  1242. // All three previous cases should work the same way if an option with both
  1243. // cl::Prefix and cl::Grouping modifiers is used at the end of a group.
  1244. const char *args4[] = {"prog", "-fpval4"};
  1245. EXPECT_TRUE(
  1246. cl::ParseCommandLineOptions(2, args4, StringRef(), &llvm::nulls()));
  1247. EXPECT_TRUE(OptF);
  1248. EXPECT_STREQ("val4", OptP.c_str());
  1249. OptP.clear();
  1250. cl::ResetAllOptionOccurrences();
  1251. const char *args5[] = {"prog", "-fp", "val5"};
  1252. EXPECT_TRUE(
  1253. cl::ParseCommandLineOptions(3, args5, StringRef(), &llvm::nulls()));
  1254. EXPECT_TRUE(OptF);
  1255. EXPECT_STREQ("val5", OptP.c_str());
  1256. OptP.clear();
  1257. cl::ResetAllOptionOccurrences();
  1258. const char *args6[] = {"prog", "-fp=val6"};
  1259. EXPECT_TRUE(
  1260. cl::ParseCommandLineOptions(2, args6, StringRef(), &llvm::nulls()));
  1261. EXPECT_TRUE(OptF);
  1262. EXPECT_STREQ("val6", OptP.c_str());
  1263. OptP.clear();
  1264. cl::ResetAllOptionOccurrences();
  1265. // Should assign a value even if the part after a cl::Prefix option is equal
  1266. // to the name of another option.
  1267. const char *args7[] = {"prog", "-fpb"};
  1268. EXPECT_TRUE(
  1269. cl::ParseCommandLineOptions(2, args7, StringRef(), &llvm::nulls()));
  1270. EXPECT_TRUE(OptF);
  1271. EXPECT_STREQ("b", OptP.c_str());
  1272. EXPECT_FALSE(OptB);
  1273. OptP.clear();
  1274. cl::ResetAllOptionOccurrences();
  1275. // Should be possible to use a cl::AlwaysPrefix option without grouping.
  1276. const char *args8[] = {"prog", "-aval8"};
  1277. EXPECT_TRUE(
  1278. cl::ParseCommandLineOptions(2, args8, StringRef(), &llvm::nulls()));
  1279. EXPECT_STREQ("val8", OptA.c_str());
  1280. OptA.clear();
  1281. cl::ResetAllOptionOccurrences();
  1282. // Should not be possible to pass a value in a separate argument.
  1283. const char *args9[] = {"prog", "-a", "val9"};
  1284. EXPECT_FALSE(
  1285. cl::ParseCommandLineOptions(3, args9, StringRef(), &llvm::nulls()));
  1286. cl::ResetAllOptionOccurrences();
  1287. // With the "-opt=value" form, the "=" symbol should be preserved.
  1288. const char *args10[] = {"prog", "-a=val10"};
  1289. EXPECT_TRUE(
  1290. cl::ParseCommandLineOptions(2, args10, StringRef(), &llvm::nulls()));
  1291. EXPECT_STREQ("=val10", OptA.c_str());
  1292. OptA.clear();
  1293. cl::ResetAllOptionOccurrences();
  1294. // All three previous cases should work the same way if an option with both
  1295. // cl::AlwaysPrefix and cl::Grouping modifiers is used at the end of a group.
  1296. const char *args11[] = {"prog", "-faval11"};
  1297. EXPECT_TRUE(
  1298. cl::ParseCommandLineOptions(2, args11, StringRef(), &llvm::nulls()));
  1299. EXPECT_TRUE(OptF);
  1300. EXPECT_STREQ("val11", OptA.c_str());
  1301. OptA.clear();
  1302. cl::ResetAllOptionOccurrences();
  1303. const char *args12[] = {"prog", "-fa", "val12"};
  1304. EXPECT_FALSE(
  1305. cl::ParseCommandLineOptions(3, args12, StringRef(), &llvm::nulls()));
  1306. cl::ResetAllOptionOccurrences();
  1307. const char *args13[] = {"prog", "-fa=val13"};
  1308. EXPECT_TRUE(
  1309. cl::ParseCommandLineOptions(2, args13, StringRef(), &llvm::nulls()));
  1310. EXPECT_TRUE(OptF);
  1311. EXPECT_STREQ("=val13", OptA.c_str());
  1312. OptA.clear();
  1313. cl::ResetAllOptionOccurrences();
  1314. // Should assign a value even if the part after a cl::AlwaysPrefix option
  1315. // is equal to the name of another option.
  1316. const char *args14[] = {"prog", "-fab"};
  1317. EXPECT_TRUE(
  1318. cl::ParseCommandLineOptions(2, args14, StringRef(), &llvm::nulls()));
  1319. EXPECT_TRUE(OptF);
  1320. EXPECT_STREQ("b", OptA.c_str());
  1321. EXPECT_FALSE(OptB);
  1322. OptA.clear();
  1323. cl::ResetAllOptionOccurrences();
  1324. }
  1325. TEST(CommandLineTest, LongOptions) {
  1326. cl::ResetCommandLineParser();
  1327. StackOption<bool> OptA("a", cl::desc("Some flag"));
  1328. StackOption<bool> OptBLong("long-flag", cl::desc("Some long flag"));
  1329. StackOption<bool, cl::alias> OptB("b", cl::desc("Alias to --long-flag"),
  1330. cl::aliasopt(OptBLong));
  1331. StackOption<std::string> OptAB("ab", cl::desc("Another long option"));
  1332. std::string Errs;
  1333. raw_string_ostream OS(Errs);
  1334. const char *args1[] = {"prog", "-a", "-ab", "val1"};
  1335. const char *args2[] = {"prog", "-a", "--ab", "val1"};
  1336. const char *args3[] = {"prog", "-ab", "--ab", "val1"};
  1337. //
  1338. // The following tests treat `-` and `--` the same, and always match the
  1339. // longest string.
  1340. //
  1341. EXPECT_TRUE(
  1342. cl::ParseCommandLineOptions(4, args1, StringRef(), &OS)); OS.flush();
  1343. EXPECT_TRUE(OptA);
  1344. EXPECT_FALSE(OptBLong);
  1345. EXPECT_STREQ("val1", OptAB.c_str());
  1346. EXPECT_TRUE(Errs.empty()); Errs.clear();
  1347. cl::ResetAllOptionOccurrences();
  1348. EXPECT_TRUE(
  1349. cl::ParseCommandLineOptions(4, args2, StringRef(), &OS)); OS.flush();
  1350. EXPECT_TRUE(OptA);
  1351. EXPECT_FALSE(OptBLong);
  1352. EXPECT_STREQ("val1", OptAB.c_str());
  1353. EXPECT_TRUE(Errs.empty()); Errs.clear();
  1354. cl::ResetAllOptionOccurrences();
  1355. // Fails because `-ab` and `--ab` are treated the same and appear more than
  1356. // once. Also, `val1` is unexpected.
  1357. EXPECT_FALSE(
  1358. cl::ParseCommandLineOptions(4, args3, StringRef(), &OS)); OS.flush();
  1359. outs()<< Errs << "\n";
  1360. EXPECT_FALSE(Errs.empty()); Errs.clear();
  1361. cl::ResetAllOptionOccurrences();
  1362. //
  1363. // The following tests treat `-` and `--` differently, with `-` for short, and
  1364. // `--` for long options.
  1365. //
  1366. // Fails because `-ab` is treated as `-a -b`, so `-a` is seen twice, and
  1367. // `val1` is unexpected.
  1368. EXPECT_FALSE(cl::ParseCommandLineOptions(4, args1, StringRef(),
  1369. &OS, nullptr, true)); OS.flush();
  1370. EXPECT_FALSE(Errs.empty()); Errs.clear();
  1371. cl::ResetAllOptionOccurrences();
  1372. // Works because `-a` is treated differently than `--ab`.
  1373. EXPECT_TRUE(cl::ParseCommandLineOptions(4, args2, StringRef(),
  1374. &OS, nullptr, true)); OS.flush();
  1375. EXPECT_TRUE(Errs.empty()); Errs.clear();
  1376. cl::ResetAllOptionOccurrences();
  1377. // Works because `-ab` is treated as `-a -b`, and `--ab` is a long option.
  1378. EXPECT_TRUE(cl::ParseCommandLineOptions(4, args3, StringRef(),
  1379. &OS, nullptr, true));
  1380. EXPECT_TRUE(OptA);
  1381. EXPECT_TRUE(OptBLong);
  1382. EXPECT_STREQ("val1", OptAB.c_str());
  1383. OS.flush();
  1384. EXPECT_TRUE(Errs.empty()); Errs.clear();
  1385. cl::ResetAllOptionOccurrences();
  1386. }
  1387. } // anonymous namespace