llvm.org GIT mirror llvm / f944830
[CommandLineParser] Add DefaultOption flag Summary: Add DefaultOption flag to CommandLineParser which provides a default option or alias, but allows users to override it for some other purpose as needed. Also, add `-h` as a default alias to `-help`, which can be seamlessly overridden by applications like llvm-objdump and llvm-readobj which use `-h` as an alias for other options. (relanding after revert, r358414) Added DefaultOptions.clear() to reset(). Reviewers: alexfh, klimek Reviewed By: klimek Subscribers: kristina, MaskRay, mehdi_amini, inglorion, dexonsmith, hiraditya, llvm-commits, jhenderson, arphaman, cfe-commits Tags: #clang, #llvm Differential Revision: https://reviews.llvm.org/D59746 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@358428 91177308-0d34-0410-b5e6-96231b3b80d8 Don Hinton 4 months ago
6 changed file(s) with 145 addition(s) and 15 deletion(s). Raw diff Collapse all Expand all
127127 USAGE: compiler [options]
128128
129129 OPTIONS:
130 -h - Alias for -help
130131 -help - display available options (-help-hidden for more)
131132 -o - Specify output filename
132133
193194 USAGE: compiler [options]
194195
195196 OPTIONS:
197 -h - Alias for -help
196198 -help - display available options (-help-hidden for more)
197199 -o - Specify output filename
198200
12501252 with ``cl::CommaSeparated``, this modifier only makes sense with a `cl::list`_
12511253 option.
12521254
1255 .. _cl::DefaultOption:
1256
1257 * The **cl::DefaultOption** modifier is used to specify that the option is a
1258 default that can be overridden by application specific parsers. For example,
1259 the ``-help`` alias, ``-h``, is registered this way, so it can be overridden
1260 by applications that need to use the ``-h`` option for another purpose,
1261 either as a regular option or an alias for another option.
1262
12531263 .. _response files:
12541264
12551265 Response files
174174 // If this is enabled, multiple letter options are allowed to bunch together
175175 // with only a single hyphen for the whole group. This allows emulation
176176 // of the behavior that ls uses for example: ls -la === ls -l -a
177 Grouping = 0x08
177 Grouping = 0x08,
178
179 // Default option
180 DefaultOption = 0x10
178181 };
179182
180183 //===----------------------------------------------------------------------===//
269272 unsigned Value : 2;
270273 unsigned HiddenFlag : 2; // enum OptionHidden
271274 unsigned Formatting : 2; // enum FormattingFlags
272 unsigned Misc : 4;
275 unsigned Misc : 5;
273276 unsigned Position = 0; // Position of last occurrence of the option
274277 unsigned AdditionalVals = 0; // Greater than 0 for multi-valued option.
275278
305308 bool hasArgStr() const { return !ArgStr.empty(); }
306309 bool isPositional() const { return getFormattingFlag() == cl::Positional; }
307310 bool isSink() const { return getMiscFlags() & cl::Sink; }
311 bool isDefaultOption() const { return getMiscFlags() & cl::DefaultOption; }
308312
309313 bool isConsumeAfter() const {
310314 return getNumOccurrencesFlag() == cl::ConsumeAfter;
381385 }
382386
383387 inline int getNumOccurrences() const { return NumOccurrences; }
384 inline void reset() { NumOccurrences = 0; }
388 void reset();
385389 };
386390
387391 //===----------------------------------------------------------------------===//
17311735 error("cl::alias must have argument name specified!");
17321736 if (!AliasFor)
17331737 error("cl::alias must have an cl::aliasopt(option) specified!");
1738 if (!Subs.empty())
1739 error("cl::alias must not have cl::sub(), aliased option's cl::sub() will be used!");
17341740 Subs = AliasFor->Subs;
1741 Category = AliasFor->Category;
17351742 addArgument();
17361743 }
17371744
9797 // This collects additional help to be printed.
9898 std::vector MoreHelp;
9999
100 // This collects Options added with the cl::DefaultOption flag. Since they can
101 // be overridden, they are not added to the appropriate SubCommands until
102 // ParseCommandLineOptions actually runs.
103 SmallVector DefaultOptions;
104
100105 // This collects the different option categories that have been registered.
101106 SmallPtrSet RegisteredOptionCategories;
102107
145150 void addOption(Option *O, SubCommand *SC) {
146151 bool HadErrors = false;
147152 if (O->hasArgStr()) {
153 // If it's a DefaultOption, check to make sure it isn't already there.
154 if (O->isDefaultOption() &&
155 SC->OptionsMap.find(O->ArgStr) != SC->OptionsMap.end())
156 return;
157
148158 // Add argument to the argument map!
149159 if (!SC->OptionsMap.insert(std::make_pair(O->ArgStr, O)).second) {
150160 errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr
184194 }
185195 }
186196
187 void addOption(Option *O) {
197 void addOption(Option *O, bool ProcessDefaultOption = false) {
198 if (!ProcessDefaultOption && O->isDefaultOption()) {
199 DefaultOptions.push_back(O);
200 return;
201 }
202
188203 if (O->Subs.empty()) {
189204 addOption(O, &*TopLevelSubCommand);
190205 } else {
200215 OptionNames.push_back(O->ArgStr);
201216
202217 SubCommand &Sub = *SC;
203 for (auto Name : OptionNames)
204 Sub.OptionsMap.erase(Name);
218 auto End = Sub.OptionsMap.end();
219 for (auto Name : OptionNames) {
220 auto I = Sub.OptionsMap.find(Name);
221 if (I != End && I->getValue() == O)
222 Sub.OptionsMap.erase(I);
223 }
205224
206225 if (O->getFormattingFlag() == cl::Positional)
207226 for (auto Opt = Sub.PositionalOpts.begin();
265284 if (O->Subs.empty())
266285 updateArgStr(O, NewName, &*TopLevelSubCommand);
267286 else {
268 for (auto SC : O->Subs)
269 updateArgStr(O, NewName, SC);
287 if (O->isInAllSubCommands()) {
288 for (auto SC : RegisteredSubCommands)
289 updateArgStr(O, NewName, SC);
290 } else {
291 for (auto SC : O->Subs)
292 updateArgStr(O, NewName, SC);
293 }
270294 }
271295 }
272296
330354 AllSubCommands->reset();
331355 registerSubCommand(&*TopLevelSubCommand);
332356 registerSubCommand(&*AllSubCommands);
357
358 DefaultOptions.clear();
333359 }
334360
335361 private:
363389 GlobalParser->updateArgStr(this, S);
364390 assert((S.empty() || S[0] != '-') && "Option can't start with '-");
365391 ArgStr = S;
392 }
393
394 void Option::reset() {
395 NumOccurrences = 0;
396 setDefault();
397 if (isDefaultOption())
398 removeArgument();
366399 }
367400
368401 // Initialise the general option category.
11651198 auto &PositionalOpts = ChosenSubCommand->PositionalOpts;
11661199 auto &SinkOpts = ChosenSubCommand->SinkOpts;
11671200 auto &OptionsMap = ChosenSubCommand->OptionsMap;
1201
1202 for (auto O: DefaultOptions) {
1203 addOption(O, true);
1204 }
11681205
11691206 if (ConsumeAfterOpt) {
11701207 assert(PositionalOpts.size() > 0 &&
21442181 HOp("help", cl::desc("Display available options (-help-hidden for more)"),
21452182 cl::location(WrappedNormalPrinter), cl::ValueDisallowed,
21462183 cl::cat(GenericCategory), cl::sub(*AllSubCommands));
2184
2185 static cl::alias HOpA("h", cl::desc("Alias for -help"), cl::aliasopt(HOp),
2186 cl::DefaultOption);
21472187
21482188 static cl::opt>
21492189 HHOp("help-hidden", cl::desc("Display all available options"),
0 # RUN: llvm-objdump -help-hidden %t | FileCheck --check-prefix=CHECK-OBJDUMP %s
1 # RUN: llvm-readobj -help-hidden %t | FileCheck --check-prefix=CHECK-READOBJ %s
2 # RUN: llvm-tblgen -help-hidden %t | FileCheck --check-prefix=CHECK-TBLGEN %s
3 # RUN: llvm-opt-report -help-hidden %t | FileCheck --check-prefix=CHECK-OPT-RPT %s
4 # RUN: llvm-dwarfdump -help-hidden %t | FileCheck --check-prefix=CHECK-DWARF %s
5 # RUN: llvm-dwarfdump -h %t | FileCheck --check-prefix=CHECK-DWARF-H %s
6
7
8 # CHECK-OBJDUMP: -h - Alias for --section-headers
9 # CHECK-READOBJ: -h - Alias for --file-headers
10 # CHECK-TBLGEN: -h - Alias for -help
11 # CHECK-OPT-RPT: -h - Alias for -help
12 # CHECK-DWARF: -h - Alias for -help
13
14 # llvm-dwarfdump declares `-h` option and prints special help in that case,
15 # which is weird, but makes for a good test, i.e., shows the default `-h`
16 # wasn't used.
17 # CHECK-DWARF-H-NOT: -help-list - Display list of available options (-help-list-hidden for more)
3535 using namespace llvm;
3636 using namespace llvm::yaml;
3737
38 static cl::opt Help("h", cl::desc("Alias for -help"), cl::Hidden);
39
4038 // Mark all our options with this category, everything else (except for -version
4139 // and -help) will be hidden.
4240 static cl::OptionCategory
439437 "A tool to generate an optimization report from YAML optimization"
440438 " record files.\n");
441439
442 if (Help) {
443 cl::PrintHelpMessage();
444 return 0;
445 }
446
447440 LocationInfoTy LocationInfo;
448441 if (!readLocationInfo(LocationInfo))
449442 return 1;
617617 EXPECT_EQ("sc2", S->getName());
618618 }
619619 }
620 }
621
622 TEST(CommandLineTest, DefaultOptions) {
623 cl::ResetCommandLineParser();
624
625 StackOption Bar("bar", cl::sub(*cl::AllSubCommands),
626 cl::DefaultOption);
627 StackOption Bar_Alias(
628 "b", cl::desc("Alias for -bar"), cl::aliasopt(Bar), cl::DefaultOption);
629
630 StackOption Foo("foo", cl::init(false), cl::sub(*cl::AllSubCommands),
631 cl::DefaultOption);
632 StackOption Foo_Alias("f", cl::desc("Alias for -foo"),
633 cl::aliasopt(Foo), cl::DefaultOption);
634
635 StackSubCommand SC1("sc1", "First Subcommand");
636 // Override "-b" and change type in sc1 SubCommand.
637 StackOption SC1_B("b", cl::sub(SC1), cl::init(false));
638 StackSubCommand SC2("sc2", "Second subcommand");
639 // Override "-foo" and change type in sc2 SubCommand. Note that this does not
640 // affect "-f" alias, which continues to work correctly.
641 StackOption SC2_Foo("foo", cl::sub(SC2));
642
643 const char *args0[] = {"prog", "-b", "args0 bar string", "-f"};
644 EXPECT_TRUE(cl::ParseCommandLineOptions(sizeof(args0) / sizeof(char *), args0,
645 StringRef(), &llvm::nulls()));
646 EXPECT_TRUE(Bar == "args0 bar string");
647 EXPECT_TRUE(Foo);
648 EXPECT_FALSE(SC1_B);
649 EXPECT_TRUE(SC2_Foo.empty());
650
651 cl::ResetAllOptionOccurrences();
652
653 const char *args1[] = {"prog", "sc1", "-b", "-bar", "args1 bar string", "-f"};
654 EXPECT_TRUE(cl::ParseCommandLineOptions(sizeof(args1) / sizeof(char *), args1,
655 StringRef(), &llvm::nulls()));
656 EXPECT_TRUE(Bar == "args1 bar string");
657 EXPECT_TRUE(Foo);
658 EXPECT_TRUE(SC1_B);
659 EXPECT_TRUE(SC2_Foo.empty());
660 for (auto *S : cl::getRegisteredSubcommands()) {
661 if (*S) {
662 EXPECT_EQ("sc1", S->getName());
663 }
664 }
665
666 cl::ResetAllOptionOccurrences();
667
668 const char *args2[] = {"prog", "sc2", "-b", "args2 bar string",
669 "-f", "-foo", "foo string"};
670 EXPECT_TRUE(cl::ParseCommandLineOptions(sizeof(args2) / sizeof(char *), args2,
671 StringRef(), &llvm::nulls()));
672 EXPECT_TRUE(Bar == "args2 bar string");
673 EXPECT_TRUE(Foo);
674 EXPECT_FALSE(SC1_B);
675 EXPECT_TRUE(SC2_Foo == "foo string");
676 for (auto *S : cl::getRegisteredSubcommands()) {
677 if (*S) {
678 EXPECT_EQ("sc2", S->getName());
679 }
680 }
681 cl::ResetCommandLineParser();
620682 }
621683
622684 TEST(CommandLineTest, ArgumentLimit) {