llvm.org GIT mirror llvm / c19a1fb
[Support][CommandLine] Make it possible to get error messages from ParseCommandLineOptions when ignoring errors. Summary: Previously, ParseCommandLineOptions returns false and ignores error messages when IgnoreErrors. It would be useful to also return error messages if users decide to check parsing result instead of having the program exit on error. Reviewers: chandlerc, mehdi_amini, rnk Reviewed By: rnk Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D30893 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@297810 91177308-0d34-0410-b5e6-96231b3b80d8 Eric Liu 3 years ago
3 changed file(s) with 86 addition(s) and 52 deletion(s). Raw diff Collapse all Expand all
4949 //===----------------------------------------------------------------------===//
5050 // ParseCommandLineOptions - Command line option processing entry point.
5151 //
52 // Returns true on success. Otherwise, this will print the error message to
53 // stderr and exit if \p Errs is not set (nullptr by default), or print the
54 // error message to \p Errs and return false if \p Errs is provided.
5255 bool ParseCommandLineOptions(int argc, const char *const *argv,
5356 StringRef Overview = "",
54 bool IgnoreErrors = false);
57 raw_ostream *Errs = nullptr);
5558
5659 //===----------------------------------------------------------------------===//
5760 // ParseEnvironmentOptions - Environment variable option processing alternate
122122 void ResetAllOptionOccurrences();
123123
124124 bool ParseCommandLineOptions(int argc, const char *const *argv,
125 StringRef Overview, bool IgnoreErrors);
125 StringRef Overview, raw_ostream *Errs = nullptr);
126126
127127 void addLiteralOption(Option &Opt, SubCommand *SC, StringRef Name) {
128128 if (Opt.hasArgStr())
10121012 }
10131013
10141014 bool cl::ParseCommandLineOptions(int argc, const char *const *argv,
1015 StringRef Overview, bool IgnoreErrors) {
1015 StringRef Overview, raw_ostream *Errs) {
10161016 return GlobalParser->ParseCommandLineOptions(argc, argv, Overview,
1017 IgnoreErrors);
1017 Errs);
10181018 }
10191019
10201020 void CommandLineParser::ResetAllOptionOccurrences() {
10291029 bool CommandLineParser::ParseCommandLineOptions(int argc,
10301030 const char *const *argv,
10311031 StringRef Overview,
1032 bool IgnoreErrors) {
1032 raw_ostream *Errs) {
10331033 assert(hasOptions() && "No options specified!");
10341034
10351035 // Expand response files.
10441044 ProgramName = sys::path::filename(StringRef(argv[0]));
10451045
10461046 ProgramOverview = Overview;
1047 bool IgnoreErrors = Errs;
1048 if (!Errs)
1049 Errs = &errs();
10471050 bool ErrorParsing = false;
10481051
10491052 // Check out the positional arguments to collect information about them.
10961099 // not specified after an option that eats all extra arguments, or this
10971100 // one will never get any!
10981101 //
1099 if (!IgnoreErrors) {
1102 if (!IgnoreErrors)
11001103 Opt->error("error - option can never match, because "
11011104 "another positional argument will match an "
11021105 "unbounded number of values, and this option"
11031106 " does not require a value!");
1104 errs() << ProgramName << ": CommandLine Error: Option '"
1105 << Opt->ArgStr << "' is all messed up!\n";
1106 errs() << PositionalOpts.size();
1107 }
1107 *Errs << ProgramName << ": CommandLine Error: Option '" << Opt->ArgStr
1108 << "' is all messed up!\n";
1109 *Errs << PositionalOpts.size();
11081110 ErrorParsing = true;
11091111 }
11101112 UnboundedFound |= EatsUnboundedNumberOfValues(Opt);
11991201
12001202 if (!Handler) {
12011203 if (SinkOpts.empty()) {
1202 if (!IgnoreErrors) {
1203 errs() << ProgramName << ": Unknown command line argument '"
1204 << argv[i] << "'. Try: '" << argv[0] << " -help'\n";
1205
1206 if (NearestHandler) {
1207 // If we know a near match, report it as well.
1208 errs() << ProgramName << ": Did you mean '-" << NearestHandlerString
1209 << "'?\n";
1210 }
1204 *Errs << ProgramName << ": Unknown command line argument '" << argv[i]
1205 << "'. Try: '" << argv[0] << " -help'\n";
1206
1207 if (NearestHandler) {
1208 // If we know a near match, report it as well.
1209 *Errs << ProgramName << ": Did you mean '-" << NearestHandlerString
1210 << "'?\n";
12111211 }
12121212
12131213 ErrorParsing = true;
12301230
12311231 // Check and handle positional arguments now...
12321232 if (NumPositionalRequired > PositionalVals.size()) {
1233 if (!IgnoreErrors) {
1234 errs() << ProgramName
1233 *Errs << ProgramName
12351234 << ": Not enough positional command line arguments specified!\n"
12361235 << "Must specify at least " << NumPositionalRequired
12371236 << " positional argument" << (NumPositionalRequired > 1 ? "s" : "")
12381237 << ": See: " << argv[0] << " - help\n";
1239 }
12401238
12411239 ErrorParsing = true;
12421240 } else if (!HasUnlimitedPositionals &&
12431241 PositionalVals.size() > PositionalOpts.size()) {
1244 if (!IgnoreErrors) {
1245 errs() << ProgramName << ": Too many positional arguments specified!\n"
1246 << "Can specify at most " << PositionalOpts.size()
1247 << " positional arguments: See: " << argv[0] << " -help\n";
1248 }
1242 *Errs << ProgramName << ": Too many positional arguments specified!\n"
1243 << "Can specify at most " << PositionalOpts.size()
1244 << " positional arguments: See: " << argv[0] << " -help\n";
12491245 ErrorParsing = true;
12501246
12511247 } else if (!ConsumeAfterOpt) {
21812177
21822178 void LLVMParseCommandLineOptions(int argc, const char *const *argv,
21832179 const char *Overview) {
2184 llvm::cl::ParseCommandLineOptions(argc, argv, StringRef(Overview), true);
2185 }
2180 llvm::cl::ParseCommandLineOptions(argc, argv, StringRef(Overview),
2181 &llvm::nulls());
2182 }
302302 EXPECT_FALSE(SC1Opt);
303303 EXPECT_FALSE(SC2Opt);
304304 const char *args[] = {"prog", "-top-level"};
305 EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, StringRef(), true));
305 EXPECT_TRUE(
306 cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
306307 EXPECT_TRUE(TopLevelOpt);
307308 EXPECT_FALSE(SC1Opt);
308309 EXPECT_FALSE(SC2Opt);
314315 EXPECT_FALSE(SC1Opt);
315316 EXPECT_FALSE(SC2Opt);
316317 const char *args2[] = {"prog", "sc1", "-sc1"};
317 EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, StringRef(), true));
318 EXPECT_TRUE(
319 cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
318320 EXPECT_FALSE(TopLevelOpt);
319321 EXPECT_TRUE(SC1Opt);
320322 EXPECT_FALSE(SC2Opt);
326328 EXPECT_FALSE(SC1Opt);
327329 EXPECT_FALSE(SC2Opt);
328330 const char *args3[] = {"prog", "sc2", "-sc2"};
329 EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, StringRef(), true));
331 EXPECT_TRUE(
332 cl::ParseCommandLineOptions(3, args3, StringRef(), &llvm::nulls()));
330333 EXPECT_FALSE(TopLevelOpt);
331334 EXPECT_FALSE(SC1Opt);
332335 EXPECT_TRUE(SC2Opt);
341344 StackOption SC1Opt("sc1", cl::sub(SC1), cl::init(false));
342345 StackOption SC2Opt("sc2", cl::sub(SC2), cl::init(false));
343346
347 std::string Errs;
348 raw_string_ostream OS(Errs);
349
344350 const char *args[] = {"prog", "sc1", "-sc2"};
345 EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, StringRef(), true));
351 EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, StringRef(), &OS));
352 OS.flush();
353 EXPECT_FALSE(Errs.empty());
346354 }
347355
348356 TEST(CommandLineTest, AddToAllSubCommands) {
357365 const char *args2[] = {"prog", "sc1", "-everywhere"};
358366 const char *args3[] = {"prog", "sc2", "-everywhere"};
359367
368 std::string Errs;
369 raw_string_ostream OS(Errs);
370
360371 EXPECT_FALSE(AllOpt);
361 EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, StringRef(), true));
372 EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, StringRef(), &OS));
362373 EXPECT_TRUE(AllOpt);
363374
364375 AllOpt = false;
365376
366377 cl::ResetAllOptionOccurrences();
367378 EXPECT_FALSE(AllOpt);
368 EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, StringRef(), true));
379 EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, StringRef(), &OS));
369380 EXPECT_TRUE(AllOpt);
370381
371382 AllOpt = false;
372383
373384 cl::ResetAllOptionOccurrences();
374385 EXPECT_FALSE(AllOpt);
375 EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, StringRef(), true));
386 EXPECT_TRUE(cl::ParseCommandLineOptions(3, args3, StringRef(), &OS));
376387 EXPECT_TRUE(AllOpt);
388
389 // Since all parsing succeeded, the error message should be empty.
390 OS.flush();
391 EXPECT_TRUE(Errs.empty());
377392 }
378393
379394 TEST(CommandLineTest, ReparseCommandLineOptions) {
385400 const char *args[] = {"prog", "-top-level"};
386401
387402 EXPECT_FALSE(TopLevelOpt);
388 EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, StringRef(), true));
403 EXPECT_TRUE(
404 cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
389405 EXPECT_TRUE(TopLevelOpt);
390406
391407 TopLevelOpt = false;
392408
393409 cl::ResetAllOptionOccurrences();
394410 EXPECT_FALSE(TopLevelOpt);
395 EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, StringRef(), true));
411 EXPECT_TRUE(
412 cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
396413 EXPECT_TRUE(TopLevelOpt);
397414 }
398415
405422
406423 const char *args[] = {"prog", "sc", "-remove-option"};
407424
425 std::string Errs;
426 raw_string_ostream OS(Errs);
427
408428 EXPECT_FALSE(RemoveOption);
409 EXPECT_TRUE(cl::ParseCommandLineOptions(3, args, StringRef(), true));
429 EXPECT_TRUE(cl::ParseCommandLineOptions(3, args, StringRef(), &OS));
410430 EXPECT_TRUE(RemoveOption);
431 OS.flush();
432 EXPECT_TRUE(Errs.empty());
411433
412434 RemoveOption.removeArgument();
413435
414436 cl::ResetAllOptionOccurrences();
415 EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, StringRef(), true));
437 EXPECT_FALSE(cl::ParseCommandLineOptions(3, args, StringRef(), &OS));
438 OS.flush();
439 EXPECT_FALSE(Errs.empty());
416440 }
417441
418442 TEST(CommandLineTest, RemoveFromTopLevelSubCommand) {
426450 const char *args[] = {"prog", "-top-level-remove"};
427451
428452 EXPECT_FALSE(TopLevelRemove);
429 EXPECT_TRUE(cl::ParseCommandLineOptions(2, args, StringRef(), true));
453 EXPECT_TRUE(
454 cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
430455 EXPECT_TRUE(TopLevelRemove);
431456
432457 TopLevelRemove.removeArgument();
433458
434459 cl::ResetAllOptionOccurrences();
435 EXPECT_FALSE(cl::ParseCommandLineOptions(2, args, StringRef(), true));
460 EXPECT_FALSE(
461 cl::ParseCommandLineOptions(2, args, StringRef(), &llvm::nulls()));
436462 }
437463
438464 TEST(CommandLineTest, RemoveFromAllSubCommands) {
451477
452478 // It should work for all subcommands including the top-level.
453479 EXPECT_FALSE(RemoveOption);
454 EXPECT_TRUE(cl::ParseCommandLineOptions(2, args0, StringRef(), true));
480 EXPECT_TRUE(
481 cl::ParseCommandLineOptions(2, args0, StringRef(), &llvm::nulls()));
455482 EXPECT_TRUE(RemoveOption);
456483
457484 RemoveOption = false;
458485
459486 cl::ResetAllOptionOccurrences();
460487 EXPECT_FALSE(RemoveOption);
461 EXPECT_TRUE(cl::ParseCommandLineOptions(3, args1, StringRef(), true));
488 EXPECT_TRUE(
489 cl::ParseCommandLineOptions(3, args1, StringRef(), &llvm::nulls()));
462490 EXPECT_TRUE(RemoveOption);
463491
464492 RemoveOption = false;
465493
466494 cl::ResetAllOptionOccurrences();
467495 EXPECT_FALSE(RemoveOption);
468 EXPECT_TRUE(cl::ParseCommandLineOptions(3, args2, StringRef(), true));
496 EXPECT_TRUE(
497 cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
469498 EXPECT_TRUE(RemoveOption);
470499
471500 RemoveOption.removeArgument();
472501
473502 // It should not work for any subcommands including the top-level.
474503 cl::ResetAllOptionOccurrences();
475 EXPECT_FALSE(cl::ParseCommandLineOptions(2, args0, StringRef(), true));
476 cl::ResetAllOptionOccurrences();
477 EXPECT_FALSE(cl::ParseCommandLineOptions(3, args1, StringRef(), true));
478 cl::ResetAllOptionOccurrences();
479 EXPECT_FALSE(cl::ParseCommandLineOptions(3, args2, StringRef(), true));
504 EXPECT_FALSE(
505 cl::ParseCommandLineOptions(2, args0, StringRef(), &llvm::nulls()));
506 cl::ResetAllOptionOccurrences();
507 EXPECT_FALSE(
508 cl::ParseCommandLineOptions(3, args1, StringRef(), &llvm::nulls()));
509 cl::ResetAllOptionOccurrences();
510 EXPECT_FALSE(
511 cl::ParseCommandLineOptions(3, args2, StringRef(), &llvm::nulls()));
480512 }
481513
482514 TEST(CommandLineTest, GetRegisteredSubcommands) {
490522 const char *args0[] = {"prog", "sc1"};
491523 const char *args1[] = {"prog", "sc2"};
492524
493 EXPECT_TRUE(cl::ParseCommandLineOptions(2, args0, StringRef(), true));
525 EXPECT_TRUE(
526 cl::ParseCommandLineOptions(2, args0, StringRef(), &llvm::nulls()));
494527 EXPECT_FALSE(Opt1);
495528 EXPECT_FALSE(Opt2);
496529 for (auto *S : cl::getRegisteredSubcommands()) {
499532 }
500533
501534 cl::ResetAllOptionOccurrences();
502 EXPECT_TRUE(cl::ParseCommandLineOptions(2, args1, StringRef(), true));
535 EXPECT_TRUE(
536 cl::ParseCommandLineOptions(2, args1, StringRef(), &llvm::nulls()));
503537 EXPECT_FALSE(Opt1);
504538 EXPECT_FALSE(Opt2);
505539 for (auto *S : cl::getRegisteredSubcommands()) {