mirror of
https://github.com/RPCS3/llvm.git
synced 2025-03-03 16:18:37 +00:00
Revert Recommit "[CommandLine] Remove OptionCategory and SubCommand caches from the Option class."
This reverts r365675 (git commit 43d75f977853c3ec891a440c362b2df183a211b5) The patch causes a crash in SupportTests (CommandLineTest.AliasesWithArguments). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@365742 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
146fca2f16
commit
2c80014379
@ -187,27 +187,24 @@ enum MiscFlags { // Miscellaneous flags to adjust argument
|
||||
//
|
||||
class OptionCategory {
|
||||
private:
|
||||
StringRef Name = "General Category";
|
||||
StringRef Description;
|
||||
StringRef const Name;
|
||||
StringRef const Description;
|
||||
|
||||
void registerCategory();
|
||||
|
||||
public:
|
||||
OptionCategory(StringRef Name,
|
||||
StringRef Description = "")
|
||||
OptionCategory(StringRef const Name,
|
||||
StringRef const Description = "")
|
||||
: Name(Name), Description(Description) {
|
||||
registerCategory();
|
||||
}
|
||||
OptionCategory() = default;
|
||||
|
||||
StringRef getName() const { return Name; }
|
||||
StringRef getDescription() const { return Description; }
|
||||
|
||||
SmallPtrSet<Option *, 16> MemberOptions;
|
||||
};
|
||||
|
||||
// The general Option Category (used as default category).
|
||||
extern ManagedStatic<OptionCategory> GeneralCategory;
|
||||
extern OptionCategory GeneralCategory;
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// SubCommand class
|
||||
@ -286,12 +283,9 @@ public:
|
||||
StringRef ArgStr; // The argument string itself (ex: "help", "o")
|
||||
StringRef HelpStr; // The descriptive text message for -help
|
||||
StringRef ValueStr; // String describing what the value of this option is
|
||||
|
||||
// Return the set of OptionCategories that this Option belongs to.
|
||||
SmallPtrSet<OptionCategory *, 1> getCategories() const;
|
||||
|
||||
// Return the set of SubCommands that this Option belongs to.
|
||||
SmallPtrSet<SubCommand *, 1> getSubCommands() const;
|
||||
SmallVector<OptionCategory *, 1>
|
||||
Categories; // The Categories this option belongs to
|
||||
SmallPtrSet<SubCommand *, 1> Subs; // The subcommands this option belongs to.
|
||||
|
||||
inline enum NumOccurrencesFlag getNumOccurrencesFlag() const {
|
||||
return (enum NumOccurrencesFlag)Occurrences;
|
||||
@ -323,6 +317,12 @@ public:
|
||||
return getNumOccurrencesFlag() == cl::ConsumeAfter;
|
||||
}
|
||||
|
||||
bool isInAllSubCommands() const {
|
||||
return any_of(Subs, [](const SubCommand *SC) {
|
||||
return SC == &*AllSubCommands;
|
||||
});
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------------------===
|
||||
// Accessor functions set by OptionModifiers
|
||||
//
|
||||
@ -336,13 +336,16 @@ public:
|
||||
void setMiscFlag(enum MiscFlags M) { Misc |= M; }
|
||||
void setPosition(unsigned pos) { Position = pos; }
|
||||
void addCategory(OptionCategory &C);
|
||||
void addSubCommand(SubCommand &S) { Subs.insert(&S); }
|
||||
|
||||
protected:
|
||||
explicit Option(enum NumOccurrencesFlag OccurrencesFlag,
|
||||
enum OptionHidden Hidden)
|
||||
: NumOccurrences(0), Occurrences(OccurrencesFlag), Value(0),
|
||||
HiddenFlag(Hidden), Formatting(NormalFormatting), Misc(0),
|
||||
FullyInitialized(false), Position(0), AdditionalVals(0) {}
|
||||
FullyInitialized(false), Position(0), AdditionalVals(0) {
|
||||
Categories.push_back(&GeneralCategory);
|
||||
}
|
||||
|
||||
inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; }
|
||||
|
||||
@ -351,14 +354,7 @@ public:
|
||||
|
||||
// addArgument - Register this argument with the commandline system.
|
||||
//
|
||||
virtual void addArgument(SubCommand &SC);
|
||||
|
||||
// addArgument - Only called in done() method to add default
|
||||
// TopLevelSubCommand.
|
||||
void addArgument() {
|
||||
if (!FullyInitialized)
|
||||
addArgument(*TopLevelSubCommand);
|
||||
}
|
||||
void addArgument();
|
||||
|
||||
/// Unregisters this option from the CommandLine system.
|
||||
///
|
||||
@ -469,7 +465,7 @@ struct sub {
|
||||
|
||||
sub(SubCommand &S) : Sub(S) {}
|
||||
|
||||
template <class Opt> void apply(Opt &O) const { O.addArgument(Sub); }
|
||||
template <class Opt> void apply(Opt &O) const { O.addSubCommand(Sub); }
|
||||
};
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
@ -1776,10 +1772,11 @@ class alias : public Option {
|
||||
error("cl::alias must have argument name specified!");
|
||||
if (!AliasFor)
|
||||
error("cl::alias must have an cl::aliasopt(option) specified!");
|
||||
for(OptionCategory *Cat: AliasFor->getCategories())
|
||||
addCategory(*Cat);
|
||||
for(SubCommand *SC: AliasFor->getSubCommands())
|
||||
Option::addArgument(*SC);
|
||||
if (!Subs.empty())
|
||||
error("cl::alias must not have cl::sub(), aliased option's cl::sub() will be used!");
|
||||
Subs = AliasFor->Subs;
|
||||
Categories = AliasFor->Categories;
|
||||
addArgument();
|
||||
}
|
||||
|
||||
public:
|
||||
@ -1793,10 +1790,6 @@ public:
|
||||
AliasFor = &O;
|
||||
}
|
||||
|
||||
// Does nothing when called via apply. Aliases call Option::addArgument
|
||||
// directly in the done() method to actually add the option..
|
||||
void addArgument(SubCommand &SC) override {}
|
||||
|
||||
template <class... Mods>
|
||||
explicit alias(const Mods &... Ms)
|
||||
: Option(Optional, Hidden), AliasFor(nullptr) {
|
||||
|
@ -142,7 +142,7 @@ public:
|
||||
// This collects Options added with the cl::DefaultOption flag. Since they can
|
||||
// be overridden, they are not added to the appropriate SubCommands until
|
||||
// ParseCommandLineOptions actually runs.
|
||||
SmallVector<std::pair<Option*, SubCommand*>, 4> DefaultOptions;
|
||||
SmallVector<Option*, 4> DefaultOptions;
|
||||
|
||||
// This collects the different option categories that have been registered.
|
||||
SmallPtrSet<OptionCategory *, 16> RegisteredOptionCategories;
|
||||
@ -151,7 +151,6 @@ public:
|
||||
SmallPtrSet<SubCommand *, 4> RegisteredSubCommands;
|
||||
|
||||
CommandLineParser() : ActiveSubCommand(nullptr) {
|
||||
RegisteredOptionCategories.insert(&*GeneralCategory);
|
||||
registerSubCommand(&*TopLevelSubCommand);
|
||||
registerSubCommand(&*AllSubCommands);
|
||||
}
|
||||
@ -183,16 +182,15 @@ public:
|
||||
}
|
||||
|
||||
void addLiteralOption(Option &Opt, StringRef Name) {
|
||||
for(SubCommand *SC: Opt.getSubCommands())
|
||||
addLiteralOption(Opt, SC, Name);
|
||||
if (Opt.Subs.empty())
|
||||
addLiteralOption(Opt, &*TopLevelSubCommand, Name);
|
||||
else {
|
||||
for (auto SC : Opt.Subs)
|
||||
addLiteralOption(Opt, SC, Name);
|
||||
}
|
||||
}
|
||||
|
||||
void addOption(Option *O, SubCommand *SC, bool ProcessDefaultOptions = false) {
|
||||
if (!ProcessDefaultOptions && O->isDefaultOption()) {
|
||||
DefaultOptions.push_back(std::make_pair(O, SC));
|
||||
return;
|
||||
}
|
||||
|
||||
void addOption(Option *O, SubCommand *SC) {
|
||||
bool HadErrors = false;
|
||||
if (O->hasArgStr()) {
|
||||
// If it's a DefaultOption, check to make sure it isn't already there.
|
||||
@ -234,14 +232,22 @@ public:
|
||||
for (const auto &Sub : RegisteredSubCommands) {
|
||||
if (SC == Sub)
|
||||
continue;
|
||||
addOption(O, Sub, ProcessDefaultOptions);
|
||||
addOption(O, Sub);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void addDefaultOptions() {
|
||||
for (std::pair<Option *, SubCommand *> &DO : DefaultOptions) {
|
||||
addOption(DO.first, DO.second, true);
|
||||
void addOption(Option *O, bool ProcessDefaultOption = false) {
|
||||
if (!ProcessDefaultOption && O->isDefaultOption()) {
|
||||
DefaultOptions.push_back(O);
|
||||
return;
|
||||
}
|
||||
|
||||
if (O->Subs.empty()) {
|
||||
addOption(O, &*TopLevelSubCommand);
|
||||
} else {
|
||||
for (auto SC : O->Subs)
|
||||
addOption(O, SC);
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,8 +285,17 @@ public:
|
||||
}
|
||||
|
||||
void removeOption(Option *O) {
|
||||
for (auto SC : RegisteredSubCommands)
|
||||
removeOption(O, SC);
|
||||
if (O->Subs.empty())
|
||||
removeOption(O, &*TopLevelSubCommand);
|
||||
else {
|
||||
if (O->isInAllSubCommands()) {
|
||||
for (auto SC : RegisteredSubCommands)
|
||||
removeOption(O, SC);
|
||||
} else {
|
||||
for (auto SC : O->Subs)
|
||||
removeOption(O, SC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool hasOptions(const SubCommand &Sub) const {
|
||||
@ -309,8 +324,17 @@ public:
|
||||
}
|
||||
|
||||
void updateArgStr(Option *O, StringRef NewName) {
|
||||
for (auto SC : RegisteredSubCommands)
|
||||
updateArgStr(O, NewName, SC);
|
||||
if (O->Subs.empty())
|
||||
updateArgStr(O, NewName, &*TopLevelSubCommand);
|
||||
else {
|
||||
if (O->isInAllSubCommands()) {
|
||||
for (auto SC : RegisteredSubCommands)
|
||||
updateArgStr(O, NewName, SC);
|
||||
} else {
|
||||
for (auto SC : O->Subs)
|
||||
updateArgStr(O, NewName, SC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void printOptionValues();
|
||||
@ -365,7 +389,6 @@ public:
|
||||
|
||||
MoreHelp.clear();
|
||||
RegisteredOptionCategories.clear();
|
||||
RegisteredOptionCategories.insert(&*GeneralCategory);
|
||||
|
||||
ResetAllOptionOccurrences();
|
||||
RegisteredSubCommands.clear();
|
||||
@ -404,38 +427,13 @@ extrahelp::extrahelp(StringRef Help) : morehelp(Help) {
|
||||
GlobalParser->MoreHelp.push_back(Help);
|
||||
}
|
||||
|
||||
void Option::addArgument(SubCommand &SC) {
|
||||
GlobalParser->addOption(this, &SC);
|
||||
void Option::addArgument() {
|
||||
GlobalParser->addOption(this);
|
||||
FullyInitialized = true;
|
||||
}
|
||||
|
||||
void Option::removeArgument() { GlobalParser->removeOption(this); }
|
||||
|
||||
SmallPtrSet<OptionCategory *, 1> Option::getCategories() const {
|
||||
SmallPtrSet<OptionCategory *, 1> Cats;
|
||||
for (OptionCategory *C: GlobalParser->RegisteredOptionCategories) {
|
||||
if (C->MemberOptions.find(this) != C->MemberOptions.end())
|
||||
Cats.insert(C);
|
||||
}
|
||||
if (Cats.empty())
|
||||
Cats.insert(&*GeneralCategory);
|
||||
return Cats;
|
||||
}
|
||||
|
||||
SmallPtrSet<SubCommand *, 1> Option::getSubCommands() const {
|
||||
// This can happen for enums and literal options.
|
||||
if (ArgStr.empty())
|
||||
return SmallPtrSet<SubCommand *, 1>{&*TopLevelSubCommand};
|
||||
|
||||
SmallPtrSet<SubCommand *, 1> Subs;
|
||||
for (SubCommand *SC : GlobalParser->getRegisteredSubcommands()) {
|
||||
auto I = SC->OptionsMap.find(ArgStr);
|
||||
if (I != SC->OptionsMap.end() && I->getValue() == this)
|
||||
Subs.insert(SC);
|
||||
}
|
||||
return Subs;
|
||||
}
|
||||
|
||||
void Option::setArgStr(StringRef S) {
|
||||
if (FullyInitialized)
|
||||
GlobalParser->updateArgStr(this, S);
|
||||
@ -446,7 +444,14 @@ void Option::setArgStr(StringRef S) {
|
||||
}
|
||||
|
||||
void Option::addCategory(OptionCategory &C) {
|
||||
C.MemberOptions.insert(this);
|
||||
assert(!Categories.empty() && "Categories cannot be empty.");
|
||||
// Maintain backward compatibility by replacing the default GeneralCategory
|
||||
// if it's still set. Otherwise, just add the new one. The GeneralCategory
|
||||
// must be explicitly added if you want multiple categories that include it.
|
||||
if (&C != &GeneralCategory && Categories[0] == &GeneralCategory)
|
||||
Categories[0] = &C;
|
||||
else if (find(Categories, &C) == Categories.end())
|
||||
Categories.push_back(&C);
|
||||
}
|
||||
|
||||
void Option::reset() {
|
||||
@ -457,8 +462,7 @@ void Option::reset() {
|
||||
}
|
||||
|
||||
// Initialise the general option category.
|
||||
LLVM_REQUIRE_CONSTANT_INITIALIZATION
|
||||
ManagedStatic<OptionCategory> llvm::cl::GeneralCategory;
|
||||
OptionCategory llvm::cl::GeneralCategory("General options");
|
||||
|
||||
void OptionCategory::registerCategory() {
|
||||
GlobalParser->registerCategory(this);
|
||||
@ -1298,7 +1302,9 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
|
||||
auto &SinkOpts = ChosenSubCommand->SinkOpts;
|
||||
auto &OptionsMap = ChosenSubCommand->OptionsMap;
|
||||
|
||||
addDefaultOptions();
|
||||
for (auto O: DefaultOptions) {
|
||||
addOption(O, true);
|
||||
}
|
||||
|
||||
if (ConsumeAfterOpt) {
|
||||
assert(PositionalOpts.size() > 0 &&
|
||||
@ -2198,7 +2204,7 @@ protected:
|
||||
// options within categories will also be alphabetically sorted.
|
||||
for (size_t I = 0, E = Opts.size(); I != E; ++I) {
|
||||
Option *Opt = Opts[I].second;
|
||||
for (auto *Cat : Opt->getCategories()) {
|
||||
for (auto &Cat : Opt->Categories) {
|
||||
assert(CategorizedOptions.count(Cat) > 0 &&
|
||||
"Option has an unregistered category");
|
||||
CategorizedOptions[Cat].push_back(Opt);
|
||||
@ -2459,7 +2465,7 @@ cl::getRegisteredSubcommands() {
|
||||
|
||||
void cl::HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub) {
|
||||
for (auto &I : Sub.OptionsMap) {
|
||||
for (OptionCategory *Cat : I.second->getCategories()) {
|
||||
for (auto &Cat : I.second->Categories) {
|
||||
if (Cat != &Category &&
|
||||
Cat != &GenericCategory)
|
||||
I.second->setHiddenFlag(cl::ReallyHidden);
|
||||
@ -2470,7 +2476,7 @@ void cl::HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub) {
|
||||
void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories,
|
||||
SubCommand &Sub) {
|
||||
for (auto &I : Sub.OptionsMap) {
|
||||
for (OptionCategory *Cat : I.second->getCategories()) {
|
||||
for (auto &Cat : I.second->Categories) {
|
||||
if (find(Categories, Cat) == Categories.end() && Cat != &GenericCategory)
|
||||
I.second->setHiddenFlag(cl::ReallyHidden);
|
||||
}
|
||||
|
@ -95,16 +95,16 @@ TEST(CommandLineTest, ModifyExisitingOption) {
|
||||
cl::Option *Retrieved = Map["test-option"];
|
||||
ASSERT_EQ(&TestOption, Retrieved) << "Retrieved wrong option.";
|
||||
|
||||
ASSERT_NE(Retrieved->getCategories().end(),
|
||||
find_if(Retrieved->getCategories(),
|
||||
ASSERT_NE(Retrieved->Categories.end(),
|
||||
find_if(Retrieved->Categories,
|
||||
[&](const llvm::cl::OptionCategory *Cat) {
|
||||
return Cat == &*cl::GeneralCategory;
|
||||
return Cat == &cl::GeneralCategory;
|
||||
}))
|
||||
<< "Incorrect default option category.";
|
||||
|
||||
Retrieved->addCategory(TestCategory);
|
||||
ASSERT_NE(Retrieved->getCategories().end(),
|
||||
find_if(Retrieved->getCategories(),
|
||||
ASSERT_NE(Retrieved->Categories.end(),
|
||||
find_if(Retrieved->Categories,
|
||||
[&](const llvm::cl::OptionCategory *Cat) {
|
||||
return Cat == &TestCategory;
|
||||
}))
|
||||
@ -160,8 +160,8 @@ TEST(CommandLineTest, ParseEnvironmentToLocalVar) {
|
||||
TEST(CommandLineTest, UseOptionCategory) {
|
||||
StackOption<int> TestOption2("test-option", cl::cat(TestCategory));
|
||||
|
||||
ASSERT_NE(TestOption2.getCategories().end(),
|
||||
find_if(TestOption2.getCategories(),
|
||||
ASSERT_NE(TestOption2.Categories.end(),
|
||||
find_if(TestOption2.Categories,
|
||||
[&](const llvm::cl::OptionCategory *Cat) {
|
||||
return Cat == &TestCategory;
|
||||
}))
|
||||
@ -170,44 +170,42 @@ TEST(CommandLineTest, UseOptionCategory) {
|
||||
|
||||
TEST(CommandLineTest, UseMultipleCategories) {
|
||||
StackOption<int> TestOption2("test-option2", cl::cat(TestCategory),
|
||||
cl::cat(*cl::GeneralCategory),
|
||||
cl::cat(*cl::GeneralCategory));
|
||||
auto TestOption2Categories = TestOption2.getCategories();
|
||||
cl::cat(cl::GeneralCategory),
|
||||
cl::cat(cl::GeneralCategory));
|
||||
|
||||
// Make sure cl::GeneralCategory wasn't added twice.
|
||||
ASSERT_EQ(TestOption2Categories.size(), 2U);
|
||||
ASSERT_EQ(TestOption2.Categories.size(), 2U);
|
||||
|
||||
ASSERT_NE(TestOption2Categories.end(),
|
||||
find_if(TestOption2Categories,
|
||||
ASSERT_NE(TestOption2.Categories.end(),
|
||||
find_if(TestOption2.Categories,
|
||||
[&](const llvm::cl::OptionCategory *Cat) {
|
||||
return Cat == &TestCategory;
|
||||
}))
|
||||
<< "Failed to assign Option Category.";
|
||||
ASSERT_NE(TestOption2Categories.end(),
|
||||
find_if(TestOption2Categories,
|
||||
ASSERT_NE(TestOption2.Categories.end(),
|
||||
find_if(TestOption2.Categories,
|
||||
[&](const llvm::cl::OptionCategory *Cat) {
|
||||
return Cat == &*cl::GeneralCategory;
|
||||
return Cat == &cl::GeneralCategory;
|
||||
}))
|
||||
<< "Failed to assign General Category.";
|
||||
|
||||
cl::OptionCategory AnotherCategory("Additional test Options", "Description");
|
||||
StackOption<int> TestOption("test-option", cl::cat(TestCategory),
|
||||
cl::cat(AnotherCategory));
|
||||
auto TestOptionCategories = TestOption.getCategories();
|
||||
ASSERT_EQ(TestOptionCategories.end(),
|
||||
find_if(TestOptionCategories,
|
||||
ASSERT_EQ(TestOption.Categories.end(),
|
||||
find_if(TestOption.Categories,
|
||||
[&](const llvm::cl::OptionCategory *Cat) {
|
||||
return Cat == &*cl::GeneralCategory;
|
||||
return Cat == &cl::GeneralCategory;
|
||||
}))
|
||||
<< "Failed to remove General Category.";
|
||||
ASSERT_NE(TestOptionCategories.end(),
|
||||
find_if(TestOptionCategories,
|
||||
ASSERT_NE(TestOption.Categories.end(),
|
||||
find_if(TestOption.Categories,
|
||||
[&](const llvm::cl::OptionCategory *Cat) {
|
||||
return Cat == &TestCategory;
|
||||
}))
|
||||
<< "Failed to assign Option Category.";
|
||||
ASSERT_NE(TestOptionCategories.end(),
|
||||
find_if(TestOptionCategories,
|
||||
ASSERT_NE(TestOption.Categories.end(),
|
||||
find_if(TestOption.Categories,
|
||||
[&](const llvm::cl::OptionCategory *Cat) {
|
||||
return Cat == &AnotherCategory;
|
||||
}))
|
||||
@ -380,30 +378,6 @@ TEST(CommandLineTest, AliasRequired) {
|
||||
testAliasRequired(array_lengthof(opts2), opts2);
|
||||
}
|
||||
|
||||
TEST(CommandLineTest, AliasWithSubCommand) {
|
||||
StackSubCommand SC1("sc1", "Subcommand 1");
|
||||
StackOption<std::string> Option1("option", cl::value_desc("output file"),
|
||||
cl::init("-"), cl::desc("Option"),
|
||||
cl::sub(SC1));
|
||||
StackOption<std::string, cl::alias> Alias1("o", llvm::cl::aliasopt(Option1),
|
||||
cl::desc("Alias for --option"),
|
||||
cl::sub(SC1));
|
||||
}
|
||||
|
||||
TEST(CommandLineTest, AliasWithMultipleSubCommandsWithSameOption) {
|
||||
StackSubCommand SC1("sc1", "Subcommand 1");
|
||||
StackOption<std::string> Option1("option", cl::value_desc("output file"),
|
||||
cl::init("-"), cl::desc("Option"),
|
||||
cl::sub(SC1));
|
||||
StackSubCommand SC2("sc2", "Subcommand 2");
|
||||
StackOption<std::string> Option2("option", cl::value_desc("output file"),
|
||||
cl::init("-"), cl::desc("Option"),
|
||||
cl::sub(SC2));
|
||||
|
||||
StackOption<std::string, cl::alias> Alias1("o", llvm::cl::aliasopt(Option1),
|
||||
cl::desc("Alias for --option"));
|
||||
}
|
||||
|
||||
TEST(CommandLineTest, HideUnrelatedOptions) {
|
||||
StackOption<int> TestOption1("hide-option-1");
|
||||
StackOption<int> TestOption2("hide-option-2", cl::cat(TestCategory));
|
||||
|
Loading…
x
Reference in New Issue
Block a user