diff --git a/llvm/include/llvm/Support/CommandLine.h b/llvm/include/llvm/Support/CommandLine.h --- a/llvm/include/llvm/Support/CommandLine.h +++ b/llvm/include/llvm/Support/CommandLine.h @@ -30,7 +30,6 @@ #include "llvm/ADT/Twine.h" #include "llvm/ADT/iterator_range.h" #include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -238,12 +237,6 @@ Option *ConsumeAfterOpt = nullptr; // The ConsumeAfter option if it exists. }; -// A special subcommand representing no subcommand -extern ManagedStatic TopLevelSubCommand; - -// A special subcommand that can be used to put an option into all subcommands. -extern ManagedStatic AllSubCommands; - //===----------------------------------------------------------------------===// // class Option { @@ -346,7 +339,10 @@ inline void setNumAdditionalVals(unsigned n) { AdditionalVals = n; } public: - virtual ~Option() = default; + virtual ~Option() { + if (FullyInitialized) + removeArgument(); + } // Register this argument with the commandline system. // diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp --- a/llvm/lib/Support/CommandLine.cpp +++ b/llvm/lib/Support/CommandLine.cpp @@ -37,7 +37,6 @@ #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Host.h" -#include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/Path.h" #include "llvm/Support/Process.h" @@ -433,26 +432,29 @@ } // namespace -static ManagedStatic GlobalParser; +static CommandLineParser &getGlobalParser() { + static CommandLineParser GlobalParser; + return GlobalParser; +} void cl::AddLiteralOption(Option &O, StringRef Name) { - GlobalParser->addLiteralOption(O, Name); + getGlobalParser().addLiteralOption(O, Name); } extrahelp::extrahelp(StringRef Help) : morehelp(Help) { - GlobalParser->MoreHelp.push_back(Help); + getGlobalParser().MoreHelp.push_back(Help); } void Option::addArgument() { - GlobalParser->addOption(this); + getGlobalParser().addOption(this); FullyInitialized = true; } -void Option::removeArgument() { GlobalParser->removeOption(this); } +void Option::removeArgument() { getGlobalParser().removeOption(this); } void Option::setArgStr(StringRef S) { if (FullyInitialized) - GlobalParser->updateArgStr(this, S); + getGlobalParser().updateArgStr(this, S); assert((S.empty() || S[0] != '-') && "Option can't start with '-"); ArgStr = S; if (ArgStr.size() == 1) @@ -478,29 +480,25 @@ } void OptionCategory::registerCategory() { - GlobalParser->registerCategory(this); + getGlobalParser().registerCategory(this); } -// A special subcommand representing no subcommand. It is particularly important -// that this ManagedStatic uses constant initailization and not dynamic -// initialization because it is referenced from cl::opt constructors, which run -// dynamically in an arbitrary order. -LLVM_REQUIRE_CONSTANT_INITIALIZATION -ManagedStatic llvm::cl::TopLevelSubCommand; - -// A special subcommand that can be used to put an option into all subcommands. -ManagedStatic llvm::cl::AllSubCommands; - -SubCommand &SubCommand::getTopLevel() { return *TopLevelSubCommand; } +SubCommand &SubCommand::getTopLevel() { + static SubCommand TopLevelSubCommand; + return TopLevelSubCommand; +} -SubCommand &SubCommand::getAll() { return *AllSubCommands; } +SubCommand &SubCommand::getAll() { + static SubCommand AllSubCommands; + return AllSubCommands; +} void SubCommand::registerSubCommand() { - GlobalParser->registerSubCommand(this); + getGlobalParser().registerSubCommand(this); } void SubCommand::unregisterSubCommand() { - GlobalParser->unregisterSubCommand(this); + getGlobalParser().unregisterSubCommand(this); } void SubCommand::reset() { @@ -512,7 +510,7 @@ } SubCommand::operator bool() const { - return (GlobalParser->getActiveSubCommand() == this); + return (getGlobalParser().getActiveSubCommand() == this); } //===----------------------------------------------------------------------===// @@ -1401,8 +1399,8 @@ int NewArgc = static_cast(NewArgv.size()); // Parse all options. - return GlobalParser->ParseCommandLineOptions(NewArgc, &NewArgv[0], Overview, - Errs, LongOptionsUseDoubleDash); + return getGlobalParser().ParseCommandLineOptions( + NewArgc, &NewArgv[0], Overview, Errs, LongOptionsUseDoubleDash); } /// Reset all options at least once, so that we can parse different options. @@ -1464,7 +1462,7 @@ if (ChosenSubCommand != &SubCommand::getTopLevel()) FirstArg = 2; } - GlobalParser->ActiveSubCommand = ChosenSubCommand; + getGlobalParser().ActiveSubCommand = ChosenSubCommand; assert(ChosenSubCommand); auto &ConsumeAfterOpt = ChosenSubCommand->ConsumeAfterOpt; @@ -1769,7 +1767,8 @@ if (ArgName.empty()) Errs << HelpStr; // Be nice for positional arguments else - Errs << GlobalParser->ProgramName << ": for the " << PrintArg(ArgName, 0); + Errs << getGlobalParser().ProgramName << ": for the " + << PrintArg(ArgName, 0); Errs << " option: " << Message << "\n"; return true; @@ -2277,7 +2276,7 @@ } void printHelp() { - SubCommand *Sub = GlobalParser->getActiveSubCommand(); + SubCommand *Sub = getGlobalParser().getActiveSubCommand(); auto &OptionsMap = Sub->OptionsMap; auto &PositionalOpts = Sub->PositionalOpts; auto &ConsumeAfterOpt = Sub->ConsumeAfterOpt; @@ -2286,24 +2285,24 @@ sortOpts(OptionsMap, Opts, ShowHidden); StrSubCommandPairVector Subs; - sortSubCommands(GlobalParser->RegisteredSubCommands, Subs); + sortSubCommands(getGlobalParser().RegisteredSubCommands, Subs); - if (!GlobalParser->ProgramOverview.empty()) - outs() << "OVERVIEW: " << GlobalParser->ProgramOverview << "\n"; + if (!getGlobalParser().ProgramOverview.empty()) + outs() << "OVERVIEW: " << getGlobalParser().ProgramOverview << "\n"; - outs() << "USAGE: " << GlobalParser->ProgramName; - if (Sub == &SubCommand::getTopLevel()) { - if (Subs.size() > 2) - outs() << " [subcommand]"; - outs() << " [options]"; - } else { - if (!Sub->getDescription().empty()) { - outs() << "SUBCOMMAND '" << Sub->getName() - << "': " << Sub->getDescription() << "\n\n"; - } - outs() << "USAGE: " << GlobalParser->ProgramName << " " - << Sub->getName() << " [options]"; + if (Sub == &SubCommand::getTopLevel()) { + outs() << "USAGE: " << getGlobalParser().ProgramName; + if (Subs.size() > 2) + outs() << " [subcommand]"; + outs() << " [options]"; + } else { + if (!Sub->getDescription().empty()) { + outs() << "SUBCOMMAND '" << Sub->getName() + << "': " << Sub->getDescription() << "\n\n"; } + outs() << "USAGE: " << getGlobalParser().ProgramName << " " + << Sub->getName() << " [options]"; + } for (auto *Opt : PositionalOpts) { if (Opt->hasArgStr()) @@ -2325,7 +2324,7 @@ outs() << "SUBCOMMANDS:\n\n"; printSubCommands(Subs, MaxSubLen); outs() << "\n"; - outs() << " Type \"" << GlobalParser->ProgramName + outs() << " Type \"" << getGlobalParser().ProgramName << " --help\" to get more help on a specific " "subcommand"; } @@ -2341,9 +2340,9 @@ printOptions(Opts, MaxArgLen); // Print any extra help the user has declared. - for (const auto &I : GlobalParser->MoreHelp) + for (const auto &I : getGlobalParser().MoreHelp) outs() << I; - GlobalParser->MoreHelp.clear(); + getGlobalParser().MoreHelp.clear(); } }; @@ -2370,7 +2369,8 @@ // Collect registered option categories into vector in preparation for // sorting. - for (OptionCategory *Category : GlobalParser->RegisteredOptionCategories) + for (OptionCategory *Category : + getGlobalParser().RegisteredOptionCategories) SortedCategories.push_back(Category); // Sort the different option categories alphabetically. @@ -2583,14 +2583,17 @@ cl::location(VersionPrinterInstance), cl::ValueDisallowed, cl::cat(GenericCategory)}; }; + +static CommandLineCommonOptions &getCommonOptions() { + static CommandLineCommonOptions CommonOptions; + return CommonOptions; +} + } // End anonymous namespace -// Lazy-initialized global instance of options controlling the command-line -// parser and general handling. -static ManagedStatic CommonOptions; static void initCommonOptions() { - *CommonOptions; + getCommonOptions(); initDebugCounterOptions(); initGraphWriterOptions(); initSignalsOptions(); @@ -2612,17 +2615,17 @@ if (!OptionWasSpecified) return; - if (CommonOptions->OverrideVersionPrinter != nullptr) { - CommonOptions->OverrideVersionPrinter(outs()); + if (getCommonOptions().OverrideVersionPrinter != nullptr) { + getCommonOptions().OverrideVersionPrinter(outs()); exit(0); } print(); // Iterate over any registered extra printers and call them to add further // information. - if (!CommonOptions->ExtraVersionPrinters.empty()) { + if (!getCommonOptions().ExtraVersionPrinters.empty()) { outs() << '\n'; - for (const auto &I : CommonOptions->ExtraVersionPrinters) + for (const auto &I : getCommonOptions().ExtraVersionPrinters) I(outs()); } @@ -2636,10 +2639,10 @@ // Decide which printer to invoke. If more than one option category is // registered then it is useful to show the categorized help instead of // uncategorized help. - if (GlobalParser->RegisteredOptionCategories.size() > 1) { + if (getGlobalParser().RegisteredOptionCategories.size() > 1) { // unhide --help-list option so user can have uncategorized output if they // want it. - CommonOptions->HLOp.setHiddenFlag(NotHidden); + getCommonOptions().HLOp.setHiddenFlag(NotHidden); CategorizedPrinter = true; // Invoke categorized printer } else @@ -2647,10 +2650,10 @@ } // Print the value of each option. -void cl::PrintOptionValues() { GlobalParser->printOptionValues(); } +void cl::PrintOptionValues() { getGlobalParser().printOptionValues(); } void CommandLineParser::printOptionValues() { - if (!CommonOptions->PrintOptions && !CommonOptions->PrintAllOptions) + if (!getCommonOptions().PrintOptions && !getCommonOptions().PrintAllOptions) return; SmallVector, 128> Opts; @@ -2662,37 +2665,38 @@ MaxArgLen = std::max(MaxArgLen, Opts[i].second->getOptionWidth()); for (size_t i = 0, e = Opts.size(); i != e; ++i) - Opts[i].second->printOptionValue(MaxArgLen, CommonOptions->PrintAllOptions); + Opts[i].second->printOptionValue(MaxArgLen, + getCommonOptions().PrintAllOptions); } // Utility function for printing the help message. void cl::PrintHelpMessage(bool Hidden, bool Categorized) { if (!Hidden && !Categorized) - CommonOptions->UncategorizedNormalPrinter.printHelp(); + getCommonOptions().UncategorizedNormalPrinter.printHelp(); else if (!Hidden && Categorized) - CommonOptions->CategorizedNormalPrinter.printHelp(); + getCommonOptions().CategorizedNormalPrinter.printHelp(); else if (Hidden && !Categorized) - CommonOptions->UncategorizedHiddenPrinter.printHelp(); + getCommonOptions().UncategorizedHiddenPrinter.printHelp(); else - CommonOptions->CategorizedHiddenPrinter.printHelp(); + getCommonOptions().CategorizedHiddenPrinter.printHelp(); } /// Utility function for printing version number. void cl::PrintVersionMessage() { - CommonOptions->VersionPrinterInstance.print(); + getCommonOptions().VersionPrinterInstance.print(); } void cl::SetVersionPrinter(VersionPrinterTy func) { - CommonOptions->OverrideVersionPrinter = func; + getCommonOptions().OverrideVersionPrinter = func; } void cl::AddExtraVersionPrinter(VersionPrinterTy func) { - CommonOptions->ExtraVersionPrinters.push_back(func); + getCommonOptions().ExtraVersionPrinters.push_back(func); } StringMap