llvm.org GIT mirror llvm / 9475039
Revert [CommandLine] Remove OptionCategory and SubCommand caches from the Option class. This reverts r364134 (git commit a5b83bc9e3b8e8945b55068c762bd6c73621a4b0) Caused errors in the asan bot, so the GeneralCategory global needs to be changed to ManagedStatic. Differential Revision: https://reviews.llvm.org/D62105 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@364141 91177308-0d34-0410-b5e6-96231b3b80d8 Don Hinton 4 months ago
3 changed file(s) with 102 addition(s) and 125 deletion(s). Raw diff Collapse all Expand all
200200
201201 StringRef getName() const { return Name; }
202202 StringRef getDescription() const { return Description; }
203
204 SmallPtrSet
205203 };
206204
207205 // The general Option Category (used as default category).
284282 StringRef ArgStr; // The argument string itself (ex: "help", "o")
285283 StringRef HelpStr; // The descriptive text message for -help
286284 StringRef ValueStr; // String describing what the value of this option is
287
288 // Return the set of OptionCategories that this Option belongs to.
289 SmallPtrSet getCategories() const;
290
291 // Return the set of SubCommands that this Option belongs to.
292 SmallPtrSet getSubCommands() const;
285 SmallVector
286 Categories; // The Categories this option belongs to
287 SmallPtrSet Subs; // The subcommands this option belongs to.
293288
294289 inline enum NumOccurrencesFlag getNumOccurrencesFlag() const {
295290 return (enum NumOccurrencesFlag)Occurrences;
319314
320315 bool isConsumeAfter() const {
321316 return getNumOccurrencesFlag() == cl::ConsumeAfter;
317 }
318
319 bool isInAllSubCommands() const {
320 return any_of(Subs, [](const SubCommand *SC) {
321 return SC == &*AllSubCommands;
322 });
322323 }
323324
324325 //-------------------------------------------------------------------------===
334335 void setMiscFlag(enum MiscFlags M) { Misc |= M; }
335336 void setPosition(unsigned pos) { Position = pos; }
336337 void addCategory(OptionCategory &C);
338 void addSubCommand(SubCommand &S) { Subs.insert(&S); }
337339
338340 protected:
339341 explicit Option(enum NumOccurrencesFlag OccurrencesFlag,
340342 enum OptionHidden Hidden)
341343 : NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0),
342344 HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0),
343 FullyInitialized(false), Position(0), AdditionalVals(0) {}
345 FullyInitialized(false), Position(0), AdditionalVals(0) {
346 Categories.push_back(&GeneralCategory);
347 }
344348
345349 inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; }
346350
349353
350354 // addArgument - Register this argument with the commandline system.
351355 //
352 virtual void addArgument(SubCommand &SC);
353
354 // addArgument - Only called in done() method to add default
355 // TopLevelSubCommand.
356 void addArgument() {
357 if (!FullyInitialized)
358 addArgument(*TopLevelSubCommand);
359 }
356 void addArgument();
360357
361358 /// Unregisters this option from the CommandLine system.
362359 ///
467464
468465 sub(SubCommand &S) : Sub(S) {}
469466
470 template void apply(Opt &O) const { O.addArgument(Sub); }
467 template void apply(Opt &O) const { O.addSubCommand(Sub); }
471468 };
472469
473470 //===----------------------------------------------------------------------===//
17741771 error("cl::alias must have argument name specified!");
17751772 if (!AliasFor)
17761773 error("cl::alias must have an cl::aliasopt(option) specified!");
1777 for(OptionCategory *Cat: AliasFor->getCategories())
1778 addCategory(*Cat);
1779 for(SubCommand *SC: AliasFor->getSubCommands())
1780 Option::addArgument(*SC);
1774 if (!Subs.empty())
1775 error("cl::alias must not have cl::sub(), aliased option's cl::sub() will be used!");
1776 Subs = AliasFor->Subs;
1777 Categories = AliasFor->Categories;
1778 addArgument();
17811779 }
17821780
17831781 public:
17901788 error("cl::alias must only have one cl::aliasopt(...) specified!");
17911789 AliasFor = &O;
17921790 }
1793
1794 // Does nothing when called via apply. Aliases call Option::addArgument
1795 // directly in the done() method to actually add the option..
1796 void addArgument(SubCommand &SC) override {}
17971791
17981792 template
17991793 explicit alias(const Mods &... Ms)
141141 // This collects Options added with the cl::DefaultOption flag. Since they can
142142 // be overridden, they are not added to the appropriate SubCommands until
143143 // ParseCommandLineOptions actually runs.
144 SmallVector<std::pair, 4> DefaultOptions;
144 SmallVector<Option*, 4> DefaultOptions;
145145
146146 // This collects the different option categories that have been registered.
147147 SmallPtrSet RegisteredOptionCategories;
181181 }
182182
183183 void addLiteralOption(Option &Opt, StringRef Name) {
184 for(SubCommand *SC: Opt.getSubCommands())
185 addLiteralOption(Opt, SC, Name);
186 }
187
188 void addOption(Option *O, SubCommand *SC, bool ProcessDefaultOptions = false) {
189 if (!ProcessDefaultOptions && O->isDefaultOption()) {
190 DefaultOptions.push_back(std::make_pair(O, SC));
191 return;
192 }
193
184 if (Opt.Subs.empty())
185 addLiteralOption(Opt, &*TopLevelSubCommand, Name);
186 else {
187 for (auto SC : Opt.Subs)
188 addLiteralOption(Opt, SC, Name);
189 }
190 }
191
192 void addOption(Option *O, SubCommand *SC) {
194193 bool HadErrors = false;
195194 if (O->hasArgStr()) {
196195 // If it's a DefaultOption, check to make sure it isn't already there.
232231 for (const auto &Sub : RegisteredSubCommands) {
233232 if (SC == Sub)
234233 continue;
235 addOption(O, Sub, ProcessDefaultOptions);
236 }
237 }
238 }
239
240 void addDefaultOptions() {
241 for (std::pair
242 addOption(DO.first, DO.second, true);
234 addOption(O, Sub);
235 }
236 }
237 }
238
239 void addOption(Option *O, bool ProcessDefaultOption = false) {
240 if (!ProcessDefaultOption && O->isDefaultOption()) {
241 DefaultOptions.push_back(O);
242 return;
243 }
244
245 if (O->Subs.empty()) {
246 addOption(O, &*TopLevelSubCommand);
247 } else {
248 for (auto SC : O->Subs)
249 addOption(O, SC);
243250 }
244251 }
245252
277284 }
278285
279286 void removeOption(Option *O) {
280 for (auto SC : RegisteredSubCommands)
281 removeOption(O, SC);
287 if (O->Subs.empty())
288 removeOption(O, &*TopLevelSubCommand);
289 else {
290 if (O->isInAllSubCommands()) {
291 for (auto SC : RegisteredSubCommands)
292 removeOption(O, SC);
293 } else {
294 for (auto SC : O->Subs)
295 removeOption(O, SC);
296 }
297 }
282298 }
283299
284300 bool hasOptions(const SubCommand &Sub) const {
307323 }
308324
309325 void updateArgStr(Option *O, StringRef NewName) {
310 for (auto SC : RegisteredSubCommands)
311 updateArgStr(O, NewName, SC);
326 if (O->Subs.empty())
327 updateArgStr(O, NewName, &*TopLevelSubCommand);
328 else {
329 if (O->isInAllSubCommands()) {
330 for (auto SC : RegisteredSubCommands)
331 updateArgStr(O, NewName, SC);
332 } else {
333 for (auto SC : O->Subs)
334 updateArgStr(O, NewName, SC);
335 }
336 }
312337 }
313338
314339 void printOptionValues();
401426 GlobalParser->MoreHelp.push_back(Help);
402427 }
403428
404 void Option::addArgument(SubCommand &SC) {
405 GlobalParser->addOption(this, &SC);
429 void Option::addArgument() {
430 GlobalParser->addOption(this);
406431 FullyInitialized = true;
407432 }
408433
409434 void Option::removeArgument() { GlobalParser->removeOption(this); }
410
411 SmallPtrSet Option::getCategories() const {
412 SmallPtrSet Cats;
413 for (OptionCategory *C: GlobalParser->RegisteredOptionCategories) {
414 if (C->MemberOptions.find(this) != C->MemberOptions.end())
415 Cats.insert(C);
416 }
417 if (Cats.empty())
418 Cats.insert(&GeneralCategory);
419 return Cats;
420 }
421
422 SmallPtrSet Option::getSubCommands() const {
423 // This can happen for enums and literal options.
424 if (ArgStr.empty())
425 return SmallPtrSet{&*TopLevelSubCommand};
426
427 SmallPtrSet Subs;
428 for (SubCommand *SC : GlobalParser->getRegisteredSubcommands()) {
429 auto I = SC->OptionsMap.find(ArgStr);
430 if (I != SC->OptionsMap.end() && I->getValue() == this)
431 Subs.insert(SC);
432 }
433 return Subs;
434 }
435435
436436 void Option::setArgStr(StringRef S) {
437437 if (FullyInitialized)
443443 }
444444
445445 void Option::addCategory(OptionCategory &C) {
446 C.MemberOptions.insert(this);
446 assert(!Categories.empty() && "Categories cannot be empty.");
447 // Maintain backward compatibility by replacing the default GeneralCategory
448 // if it's still set. Otherwise, just add the new one. The GeneralCategory
449 // must be explicitly added if you want multiple categories that include it.
450 if (&C != &GeneralCategory && Categories[0] == &GeneralCategory)
451 Categories[0] = &C;
452 else if (find(Categories, &C) == Categories.end())
453 Categories.push_back(&C);
447454 }
448455
449456 void Option::reset() {
12941301 auto &SinkOpts = ChosenSubCommand->SinkOpts;
12951302 auto &OptionsMap = ChosenSubCommand->OptionsMap;
12961303
1297 addDefaultOptions();
1304 for (auto O: DefaultOptions) {
1305 addOption(O, true);
1306 }
12981307
12991308 if (ConsumeAfterOpt) {
13001309 assert(PositionalOpts.size() > 0 &&
21942203 // options within categories will also be alphabetically sorted.
21952204 for (size_t I = 0, E = Opts.size(); I != E; ++I) {
21962205 Option *Opt = Opts[I].second;
2197 for (auto *Cat : Opt->getCategories()) {
2206 for (auto &Cat : Opt->Categories) {
21982207 assert(CategorizedOptions.count(Cat) > 0 &&
21992208 "Option has an unregistered category");
22002209 CategorizedOptions[Cat].push_back(Opt);
24552464
24562465 void cl::HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub) {
24572466 for (auto &I : Sub.OptionsMap) {
2458 for (OptionCategory *Cat : I.second->getCategories()) {
2467 for (auto &Cat : I.second->Categories) {
24592468 if (Cat != &Category &&
24602469 Cat != &GenericCategory)
24612470 I.second->setHiddenFlag(cl::ReallyHidden);
24662475 void cl::HideUnrelatedOptions(ArrayRef Categories,
24672476 SubCommand &Sub) {
24682477 for (auto &I : Sub.OptionsMap) {
2469 for (OptionCategory *Cat : I.second->getCategories()) {
2478 for (auto &Cat : I.second->Categories) {
24702479 if (find(Categories, Cat) == Categories.end() && Cat != &GenericCategory)
24712480 I.second->setHiddenFlag(cl::ReallyHidden);
24722481 }
9494 cl::Option *Retrieved = Map["test-option"];
9595 ASSERT_EQ(&TestOption, Retrieved) << "Retrieved wrong option.";
9696
97 ASSERT_NE(Retrieved->getCategories().end(),
98 find_if(Retrieved->getCategories(),
97 ASSERT_NE(Retrieved->Categories.end(),
98 find_if(Retrieved->Categories,
9999 [&](const llvm::cl::OptionCategory *Cat) {
100100 return Cat == &cl::GeneralCategory;
101101 }))
102102 << "Incorrect default option category.";
103103
104104 Retrieved->addCategory(TestCategory);
105 ASSERT_NE(Retrieved->getCategories().end(),
106 find_if(Retrieved->getCategories(),
105 ASSERT_NE(Retrieved->Categories.end(),
106 find_if(Retrieved->Categories,
107107 [&](const llvm::cl::OptionCategory *Cat) {
108108 return Cat == &TestCategory;
109109 }))
159159 TEST(CommandLineTest, UseOptionCategory) {
160160 StackOption TestOption2("test-option", cl::cat(TestCategory));
161161
162 ASSERT_NE(TestOption2.getCategories().end(),
163 find_if(TestOption2.getCategories(),
162 ASSERT_NE(TestOption2.Categories.end(),
163 find_if(TestOption2.Categories,
164164 [&](const llvm::cl::OptionCategory *Cat) {
165165 return Cat == &TestCategory;
166166 }))
171171 StackOption TestOption2("test-option2", cl::cat(TestCategory),
172172 cl::cat(cl::GeneralCategory),
173173 cl::cat(cl::GeneralCategory));
174 auto TestOption2Categories = TestOption2.getCategories();
175174
176175 // Make sure cl::GeneralCategory wasn't added twice.
177 ASSERT_EQ(TestOption2Categories.size(), 2U);
178
179 ASSERT_NE(TestOption2Categories.end(),
180 find_if(TestOption2Categories,
176 ASSERT_EQ(TestOption2.Categories.size(), 2U);
177
178 ASSERT_NE(TestOption2.Categories.end(),
179 find_if(TestOption2.Categories,
181180 [&](const llvm::cl::OptionCategory *Cat) {
182181 return Cat == &TestCategory;
183182 }))
184183 << "Failed to assign Option Category.";
185 ASSERT_NE(TestOption2Categories.end(),
186 find_if(TestOption2Categories,
184 ASSERT_NE(TestOption2.Categories.end(),
185 find_if(TestOption2.Categories,
187186 [&](const llvm::cl::OptionCategory *Cat) {
188187 return Cat == &cl::GeneralCategory;
189188 }))
192191 cl::OptionCategory AnotherCategory("Additional test Options", "Description");
193192 StackOption TestOption("test-option", cl::cat(TestCategory),
194193 cl::cat(AnotherCategory));
195 auto TestOptionCategories = TestOption.getCategories();
196 ASSERT_EQ(TestOptionCategories.end(),
197 find_if(TestOptionCategories,
194 ASSERT_EQ(TestOption.Categories.end(),
195 find_if(TestOption.Categories,
198196 [&](const llvm::cl::OptionCategory *Cat) {
199197 return Cat == &cl::GeneralCategory;
200198 }))
201199 << "Failed to remove General Category.";
202 ASSERT_NE(TestOptionCategories.end(),
203 find_if(TestOptionCategories,
200 ASSERT_NE(TestOption.Categories.end(),
201 find_if(TestOption.Categories,
204202 [&](const llvm::cl::OptionCategory *Cat) {
205203 return Cat == &TestCategory;
206204 }))
207205 << "Failed to assign Option Category.";
208 ASSERT_NE(TestOptionCategories.end(),
209 find_if(TestOptionCategories,
206 ASSERT_NE(TestOption.Categories.end(),
207 find_if(TestOption.Categories,
210208 [&](const llvm::cl::OptionCategory *Cat) {
211209 return Cat == &AnotherCategory;
212210 }))
377375 const char *opts2[] = { "-tool", "-o", "x" };
378376 testAliasRequired(array_lengthof(opts1), opts1);
379377 testAliasRequired(array_lengthof(opts2), opts2);
380 }
381
382 TEST(CommandLineTest, AliasWithSubCommand) {
383 StackSubCommand SC1("sc1", "Subcommand 1");
384 StackOption Option1("option", cl::value_desc("output file"),
385 cl::init("-"), cl::desc("Option"),
386 cl::sub(SC1));
387 StackOption Alias1("o", llvm::cl::aliasopt(Option1),
388 cl::desc("Alias for --option"),
389 cl::sub(SC1));
390 }
391
392 TEST(CommandLineTest, AliasWithMultipleSubCommandsWithSameOption) {
393 StackSubCommand SC1("sc1", "Subcommand 1");
394 StackOption Option1("option", cl::value_desc("output file"),
395 cl::init("-"), cl::desc("Option"),
396 cl::sub(SC1));
397 StackSubCommand SC2("sc2", "Subcommand 2");
398 StackOption Option2("option", cl::value_desc("output file"),
399 cl::init("-"), cl::desc("Option"),
400 cl::sub(SC2));
401
402 StackOption Alias1("o", llvm::cl::aliasopt(Option1),
403 cl::desc("Alias for --option"));
404378 }
405379
406380 TEST(CommandLineTest, HideUnrelatedOptions) {