2873 lines · cpp
1//===-- CommandLine.cpp - Command line parser implementation --------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This class implements a command line argument processor that is useful when10// creating a tool. It provides a simple, minimalistic interface that is easily11// extensible and supports nonlocal (library) command line options.12//13// Note that rather than trying to figure out what this code does, you could try14// reading the library documentation located in docs/CommandLine.html15//16//===----------------------------------------------------------------------===//17 18#include "llvm/Support/CommandLine.h"19 20#include "DebugOptions.h"21 22#include "llvm-c/Support.h"23#include "llvm/ADT/ArrayRef.h"24#include "llvm/ADT/STLFunctionalExtras.h"25#include "llvm/ADT/SmallPtrSet.h"26#include "llvm/ADT/SmallString.h"27#include "llvm/ADT/StringExtras.h"28#include "llvm/ADT/StringMap.h"29#include "llvm/ADT/StringRef.h"30#include "llvm/ADT/Twine.h"31#include "llvm/Config/config.h"32#include "llvm/Support/Compiler.h"33#include "llvm/Support/ConvertUTF.h"34#include "llvm/Support/Debug.h"35#include "llvm/Support/Error.h"36#include "llvm/Support/ErrorHandling.h"37#include "llvm/Support/FileSystem.h"38#include "llvm/Support/ManagedStatic.h"39#include "llvm/Support/MemoryBuffer.h"40#include "llvm/Support/Path.h"41#include "llvm/Support/Process.h"42#include "llvm/Support/StringSaver.h"43#include "llvm/Support/VirtualFileSystem.h"44#include "llvm/Support/raw_ostream.h"45#include <cstdlib>46#include <optional>47#include <string>48using namespace llvm;49using namespace cl;50 51#define DEBUG_TYPE "commandline"52 53//===----------------------------------------------------------------------===//54// Template instantiations and anchors.55//56namespace llvm {57namespace cl {58template class LLVM_EXPORT_TEMPLATE basic_parser<bool>;59template class LLVM_EXPORT_TEMPLATE basic_parser<boolOrDefault>;60template class LLVM_EXPORT_TEMPLATE basic_parser<int>;61template class LLVM_EXPORT_TEMPLATE basic_parser<long>;62template class LLVM_EXPORT_TEMPLATE basic_parser<long long>;63template class LLVM_EXPORT_TEMPLATE basic_parser<unsigned>;64template class LLVM_EXPORT_TEMPLATE basic_parser<unsigned long>;65template class LLVM_EXPORT_TEMPLATE basic_parser<unsigned long long>;66template class LLVM_EXPORT_TEMPLATE basic_parser<double>;67template class LLVM_EXPORT_TEMPLATE basic_parser<float>;68template class LLVM_EXPORT_TEMPLATE basic_parser<std::string>;69template class LLVM_EXPORT_TEMPLATE basic_parser<char>;70 71#if !(defined(LLVM_ENABLE_LLVM_EXPORT_ANNOTATIONS) && defined(_MSC_VER))72// Only instantiate opt<std::string> when not building a Windows DLL. When73// exporting opt<std::string>, MSVC implicitly exports symbols for74// std::basic_string through transitive inheritance via std::string. These75// symbols may appear in clients, leading to duplicate symbol conflicts.76template class LLVM_EXPORT_TEMPLATE opt<std::string>;77#endif78 79template class LLVM_EXPORT_TEMPLATE opt<bool>;80template class LLVM_EXPORT_TEMPLATE opt<char>;81template class LLVM_EXPORT_TEMPLATE opt<int>;82template class LLVM_EXPORT_TEMPLATE opt<unsigned>;83 84} // namespace cl85} // namespace llvm86 87// Pin the vtables to this file.88void GenericOptionValue::anchor() {}89void OptionValue<boolOrDefault>::anchor() {}90void OptionValue<std::string>::anchor() {}91void Option::anchor() {}92void basic_parser_impl::anchor() {}93void parser<bool>::anchor() {}94void parser<boolOrDefault>::anchor() {}95void parser<int>::anchor() {}96void parser<long>::anchor() {}97void parser<long long>::anchor() {}98void parser<unsigned>::anchor() {}99void parser<unsigned long>::anchor() {}100void parser<unsigned long long>::anchor() {}101void parser<double>::anchor() {}102void parser<float>::anchor() {}103void parser<std::string>::anchor() {}104void parser<std::optional<std::string>>::anchor() {}105void parser<char>::anchor() {}106 107// These anchor functions instantiate opt<T> and reference its virtual108// destructor to ensure MSVC exports the corresponding vtable and typeinfo when109// building a Windows DLL. Without an explicit reference, MSVC may omit the110// instantiation at link time even if it is marked DLL-export.111void opt_bool_anchor() { opt<bool> anchor{""}; }112void opt_char_anchor() { opt<char> anchor{""}; }113void opt_int_anchor() { opt<int> anchor{""}; }114void opt_unsigned_anchor() { opt<unsigned> anchor{""}; }115 116//===----------------------------------------------------------------------===//117 118const static size_t DefaultPad = 2;119 120static StringRef ArgPrefix = "-";121static StringRef ArgPrefixLong = "--";122static StringRef ArgHelpPrefix = " - ";123 124static size_t argPlusPrefixesSize(StringRef ArgName, size_t Pad = DefaultPad) {125 size_t Len = ArgName.size();126 if (Len == 1)127 return Len + Pad + ArgPrefix.size() + ArgHelpPrefix.size();128 return Len + Pad + ArgPrefixLong.size() + ArgHelpPrefix.size();129}130 131static SmallString<8> argPrefix(StringRef ArgName, size_t Pad = DefaultPad) {132 SmallString<8> Prefix;133 for (size_t I = 0; I < Pad; ++I) {134 Prefix.push_back(' ');135 }136 Prefix.append(ArgName.size() > 1 ? ArgPrefixLong : ArgPrefix);137 return Prefix;138}139 140// Option predicates...141static inline bool isGrouping(const Option *O) {142 return O->getMiscFlags() & cl::Grouping;143}144static inline bool isPrefixedOrGrouping(const Option *O) {145 return isGrouping(O) || O->getFormattingFlag() == cl::Prefix ||146 O->getFormattingFlag() == cl::AlwaysPrefix;147}148 149 150namespace {151 152class PrintArg {153 StringRef ArgName;154 size_t Pad;155public:156 PrintArg(StringRef ArgName, size_t Pad = DefaultPad) : ArgName(ArgName), Pad(Pad) {}157 friend raw_ostream &operator<<(raw_ostream &OS, const PrintArg &);158};159 160raw_ostream &operator<<(raw_ostream &OS, const PrintArg& Arg) {161 OS << argPrefix(Arg.ArgName, Arg.Pad) << Arg.ArgName;162 return OS;163}164 165class CommandLineParser {166public:167 // Globals for name and overview of program. Program name is not a string to168 // avoid static ctor/dtor issues.169 std::string ProgramName;170 StringRef ProgramOverview;171 172 // This collects additional help to be printed.173 std::vector<StringRef> MoreHelp;174 175 // This collects Options added with the cl::DefaultOption flag. Since they can176 // be overridden, they are not added to the appropriate SubCommands until177 // ParseCommandLineOptions actually runs.178 SmallVector<Option*, 4> DefaultOptions;179 180 // This collects the different option categories that have been registered.181 SmallPtrSet<OptionCategory *, 16> RegisteredOptionCategories;182 183 // This collects the different subcommands that have been registered.184 SmallPtrSet<SubCommand *, 4> RegisteredSubCommands;185 186 CommandLineParser() { registerSubCommand(&SubCommand::getTopLevel()); }187 188 void ResetAllOptionOccurrences();189 190 bool ParseCommandLineOptions(int argc, const char *const *argv,191 StringRef Overview, raw_ostream *Errs = nullptr,192 vfs::FileSystem *VFS = nullptr,193 bool LongOptionsUseDoubleDash = false);194 195 void forEachSubCommand(Option &Opt, function_ref<void(SubCommand &)> Action) {196 if (Opt.Subs.empty()) {197 Action(SubCommand::getTopLevel());198 return;199 }200 if (Opt.Subs.size() == 1 && *Opt.Subs.begin() == &SubCommand::getAll()) {201 for (auto *SC : RegisteredSubCommands)202 Action(*SC);203 Action(SubCommand::getAll());204 return;205 }206 for (auto *SC : Opt.Subs) {207 assert(SC != &SubCommand::getAll() &&208 "SubCommand::getAll() should not be used with other subcommands");209 Action(*SC);210 }211 }212 213 void addLiteralOption(Option &Opt, SubCommand *SC, StringRef Name) {214 if (Opt.hasArgStr())215 return;216 if (!SC->OptionsMap.insert(std::make_pair(Name, &Opt)).second) {217 errs() << ProgramName << ": CommandLine Error: Option '" << Name218 << "' registered more than once!\n";219 report_fatal_error("inconsistency in registered CommandLine options");220 }221 }222 223 void addLiteralOption(Option &Opt, StringRef Name) {224 forEachSubCommand(225 Opt, [&](SubCommand &SC) { addLiteralOption(Opt, &SC, Name); });226 }227 228 void addOption(Option *O, SubCommand *SC) {229 bool HadErrors = false;230 if (O->hasArgStr()) {231 // If it's a DefaultOption, check to make sure it isn't already there.232 if (O->isDefaultOption() && SC->OptionsMap.contains(O->ArgStr))233 return;234 235 // Add argument to the argument map!236 if (!SC->OptionsMap.insert(std::make_pair(O->ArgStr, O)).second) {237 errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr238 << "' registered more than once!\n";239 HadErrors = true;240 }241 }242 243 // Remember information about positional options.244 if (O->getFormattingFlag() == cl::Positional)245 SC->PositionalOpts.push_back(O);246 else if (O->getMiscFlags() & cl::Sink) // Remember sink options247 SC->SinkOpts.push_back(O);248 else if (O->getNumOccurrencesFlag() == cl::ConsumeAfter) {249 if (SC->ConsumeAfterOpt) {250 O->error("Cannot specify more than one option with cl::ConsumeAfter!");251 HadErrors = true;252 }253 SC->ConsumeAfterOpt = O;254 }255 256 // Fail hard if there were errors. These are strictly unrecoverable and257 // indicate serious issues such as conflicting option names or an258 // incorrectly259 // linked LLVM distribution.260 if (HadErrors)261 report_fatal_error("inconsistency in registered CommandLine options");262 }263 264 void addOption(Option *O, bool ProcessDefaultOption = false) {265 if (!ProcessDefaultOption && O->isDefaultOption()) {266 DefaultOptions.push_back(O);267 return;268 }269 forEachSubCommand(*O, [&](SubCommand &SC) { addOption(O, &SC); });270 }271 272 void removeOption(Option *O, SubCommand *SC) {273 SmallVector<StringRef, 16> OptionNames;274 O->getExtraOptionNames(OptionNames);275 if (O->hasArgStr())276 OptionNames.push_back(O->ArgStr);277 278 SubCommand &Sub = *SC;279 auto End = Sub.OptionsMap.end();280 for (auto Name : OptionNames) {281 auto I = Sub.OptionsMap.find(Name);282 if (I != End && I->getValue() == O)283 Sub.OptionsMap.erase(I);284 }285 286 if (O->getFormattingFlag() == cl::Positional)287 for (auto *Opt = Sub.PositionalOpts.begin();288 Opt != Sub.PositionalOpts.end(); ++Opt) {289 if (*Opt == O) {290 Sub.PositionalOpts.erase(Opt);291 break;292 }293 }294 else if (O->getMiscFlags() & cl::Sink)295 for (auto *Opt = Sub.SinkOpts.begin(); Opt != Sub.SinkOpts.end(); ++Opt) {296 if (*Opt == O) {297 Sub.SinkOpts.erase(Opt);298 break;299 }300 }301 else if (O == Sub.ConsumeAfterOpt)302 Sub.ConsumeAfterOpt = nullptr;303 }304 305 void removeOption(Option *O) {306 forEachSubCommand(*O, [&](SubCommand &SC) { removeOption(O, &SC); });307 }308 309 bool hasOptions(const SubCommand &Sub) const {310 return (!Sub.OptionsMap.empty() || !Sub.PositionalOpts.empty() ||311 nullptr != Sub.ConsumeAfterOpt);312 }313 314 bool hasOptions() const {315 for (const auto *S : RegisteredSubCommands) {316 if (hasOptions(*S))317 return true;318 }319 return false;320 }321 322 bool hasNamedSubCommands() const {323 for (const auto *S : RegisteredSubCommands)324 if (!S->getName().empty())325 return true;326 return false;327 }328 329 SubCommand *getActiveSubCommand() { return ActiveSubCommand; }330 331 void updateArgStr(Option *O, StringRef NewName, SubCommand *SC) {332 SubCommand &Sub = *SC;333 if (!Sub.OptionsMap.insert(std::make_pair(NewName, O)).second) {334 errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr335 << "' registered more than once!\n";336 report_fatal_error("inconsistency in registered CommandLine options");337 }338 Sub.OptionsMap.erase(O->ArgStr);339 }340 341 void updateArgStr(Option *O, StringRef NewName) {342 forEachSubCommand(*O,343 [&](SubCommand &SC) { updateArgStr(O, NewName, &SC); });344 }345 346 void printOptionValues();347 348 void registerCategory(OptionCategory *cat) {349 assert(count_if(RegisteredOptionCategories,350 [cat](const OptionCategory *Category) {351 return cat->getName() == Category->getName();352 }) == 0 &&353 "Duplicate option categories");354 355 RegisteredOptionCategories.insert(cat);356 }357 358 void registerSubCommand(SubCommand *sub) {359 assert(count_if(RegisteredSubCommands,360 [sub](const SubCommand *Sub) {361 return (!sub->getName().empty()) &&362 (Sub->getName() == sub->getName());363 }) == 0 &&364 "Duplicate subcommands");365 RegisteredSubCommands.insert(sub);366 367 // For all options that have been registered for all subcommands, add the368 // option to this subcommand now.369 assert(sub != &SubCommand::getAll() &&370 "SubCommand::getAll() should not be registered");371 for (auto &E : SubCommand::getAll().OptionsMap) {372 Option *O = E.second;373 if ((O->isPositional() || O->isSink() || O->isConsumeAfter()) ||374 O->hasArgStr())375 addOption(O, sub);376 else377 addLiteralOption(*O, sub, E.first());378 }379 }380 381 void unregisterSubCommand(SubCommand *sub) {382 RegisteredSubCommands.erase(sub);383 }384 385 iterator_range<SmallPtrSet<SubCommand *, 4>::iterator>386 getRegisteredSubcommands() {387 return make_range(RegisteredSubCommands.begin(),388 RegisteredSubCommands.end());389 }390 391 void reset() {392 ActiveSubCommand = nullptr;393 ProgramName.clear();394 ProgramOverview = StringRef();395 396 MoreHelp.clear();397 RegisteredOptionCategories.clear();398 399 ResetAllOptionOccurrences();400 RegisteredSubCommands.clear();401 402 SubCommand::getTopLevel().reset();403 SubCommand::getAll().reset();404 registerSubCommand(&SubCommand::getTopLevel());405 406 DefaultOptions.clear();407 }408 409private:410 SubCommand *ActiveSubCommand = nullptr;411 412 Option *LookupOption(SubCommand &Sub, StringRef &Arg, StringRef &Value);413 Option *LookupLongOption(SubCommand &Sub, StringRef &Arg, StringRef &Value,414 bool LongOptionsUseDoubleDash, bool HaveDoubleDash) {415 Option *Opt = LookupOption(Sub, Arg, Value);416 if (Opt && LongOptionsUseDoubleDash && !HaveDoubleDash && !isGrouping(Opt))417 return nullptr;418 return Opt;419 }420 SubCommand *LookupSubCommand(StringRef Name, std::string &NearestString);421};422 423} // namespace424 425static ManagedStatic<CommandLineParser> GlobalParser;426 427template <typename T, T TrueVal, T FalseVal>428static bool parseBool(Option &O, StringRef ArgName, StringRef Arg, T &Value) {429 if (Arg == "" || Arg == "true" || Arg == "TRUE" || Arg == "True" ||430 Arg == "1") {431 Value = TrueVal;432 return false;433 }434 435 if (Arg == "false" || Arg == "FALSE" || Arg == "False" || Arg == "0") {436 Value = FalseVal;437 return false;438 }439 return O.error("'" + Arg +440 "' is invalid value for boolean argument! Try 0 or 1");441}442 443void cl::AddLiteralOption(Option &O, StringRef Name) {444 GlobalParser->addLiteralOption(O, Name);445}446 447extrahelp::extrahelp(StringRef Help) : morehelp(Help) {448 GlobalParser->MoreHelp.push_back(Help);449}450 451void Option::addArgument() {452 GlobalParser->addOption(this);453 FullyInitialized = true;454}455 456void Option::removeArgument() { GlobalParser->removeOption(this); }457 458void Option::setArgStr(StringRef S) {459 if (FullyInitialized)460 GlobalParser->updateArgStr(this, S);461 assert(!S.starts_with("-") && "Option can't start with '-");462 ArgStr = S;463 if (ArgStr.size() == 1)464 setMiscFlag(Grouping);465}466 467void Option::addCategory(OptionCategory &C) {468 assert(!Categories.empty() && "Categories cannot be empty.");469 // Maintain backward compatibility by replacing the default GeneralCategory470 // if it's still set. Otherwise, just add the new one. The GeneralCategory471 // must be explicitly added if you want multiple categories that include it.472 if (&C != &getGeneralCategory() && Categories[0] == &getGeneralCategory())473 Categories[0] = &C;474 else if (!is_contained(Categories, &C))475 Categories.push_back(&C);476}477 478void Option::reset() {479 NumOccurrences = 0;480 setDefault();481 if (isDefaultOption())482 removeArgument();483}484 485void OptionCategory::registerCategory() {486 GlobalParser->registerCategory(this);487}488 489// A special subcommand representing no subcommand. It is particularly important490// that this ManagedStatic uses constant initailization and not dynamic491// initialization because it is referenced from cl::opt constructors, which run492// dynamically in an arbitrary order.493LLVM_REQUIRE_CONSTANT_INITIALIZATION494static ManagedStatic<SubCommand> TopLevelSubCommand;495 496// A special subcommand that can be used to put an option into all subcommands.497static ManagedStatic<SubCommand> AllSubCommands;498 499SubCommand &SubCommand::getTopLevel() { return *TopLevelSubCommand; }500 501SubCommand &SubCommand::getAll() { return *AllSubCommands; }502 503void SubCommand::registerSubCommand() {504 GlobalParser->registerSubCommand(this);505}506 507void SubCommand::unregisterSubCommand() {508 GlobalParser->unregisterSubCommand(this);509}510 511void SubCommand::reset() {512 PositionalOpts.clear();513 SinkOpts.clear();514 OptionsMap.clear();515 516 ConsumeAfterOpt = nullptr;517}518 519SubCommand::operator bool() const {520 return (GlobalParser->getActiveSubCommand() == this);521}522 523//===----------------------------------------------------------------------===//524// Basic, shared command line option processing machinery.525//526 527/// LookupOption - Lookup the option specified by the specified option on the528/// command line. If there is a value specified (after an equal sign) return529/// that as well. This assumes that leading dashes have already been stripped.530Option *CommandLineParser::LookupOption(SubCommand &Sub, StringRef &Arg,531 StringRef &Value) {532 // Reject all dashes.533 if (Arg.empty())534 return nullptr;535 assert(&Sub != &SubCommand::getAll());536 537 size_t EqualPos = Arg.find('=');538 539 // If we have an equals sign, remember the value.540 if (EqualPos == StringRef::npos) {541 // Look up the option.542 return Sub.OptionsMap.lookup(Arg);543 }544 545 // If the argument before the = is a valid option name and the option allows546 // non-prefix form (ie is not AlwaysPrefix), we match. If not, signal match547 // failure by returning nullptr.548 auto I = Sub.OptionsMap.find(Arg.substr(0, EqualPos));549 if (I == Sub.OptionsMap.end())550 return nullptr;551 552 auto *O = I->second;553 if (O->getFormattingFlag() == cl::AlwaysPrefix)554 return nullptr;555 556 Value = Arg.substr(EqualPos + 1);557 Arg = Arg.substr(0, EqualPos);558 return I->second;559}560 561SubCommand *CommandLineParser::LookupSubCommand(StringRef Name,562 std::string &NearestString) {563 if (Name.empty())564 return &SubCommand::getTopLevel();565 // Find a subcommand with the edit distance == 1.566 SubCommand *NearestMatch = nullptr;567 for (auto *S : RegisteredSubCommands) {568 assert(S != &SubCommand::getAll() &&569 "SubCommand::getAll() is not expected in RegisteredSubCommands");570 if (S->getName().empty())571 continue;572 573 if (S->getName() == Name)574 return S;575 576 if (!NearestMatch && S->getName().edit_distance(Name) < 2)577 NearestMatch = S;578 }579 580 if (NearestMatch)581 NearestString = NearestMatch->getName();582 583 return &SubCommand::getTopLevel();584}585 586/// LookupNearestOption - Lookup the closest match to the option specified by587/// the specified option on the command line. If there is a value specified588/// (after an equal sign) return that as well. This assumes that leading dashes589/// have already been stripped.590static Option *LookupNearestOption(StringRef Arg,591 const StringMap<Option *> &OptionsMap,592 std::string &NearestString) {593 // Reject all dashes.594 if (Arg.empty())595 return nullptr;596 597 // Split on any equal sign.598 std::pair<StringRef, StringRef> SplitArg = Arg.split('=');599 StringRef &LHS = SplitArg.first; // LHS == Arg when no '=' is present.600 StringRef &RHS = SplitArg.second;601 602 // Find the closest match.603 Option *Best = nullptr;604 unsigned BestDistance = 0;605 for (const auto &[_, O] : OptionsMap) {606 // Do not suggest really hidden options (not shown in any help).607 if (O->getOptionHiddenFlag() == ReallyHidden)608 continue;609 610 SmallVector<StringRef, 16> OptionNames;611 O->getExtraOptionNames(OptionNames);612 if (O->hasArgStr())613 OptionNames.push_back(O->ArgStr);614 615 bool PermitValue = O->getValueExpectedFlag() != cl::ValueDisallowed;616 StringRef Flag = PermitValue ? LHS : Arg;617 for (const auto &Name : OptionNames) {618 unsigned Distance = StringRef(Name).edit_distance(619 Flag, /*AllowReplacements=*/true, /*MaxEditDistance=*/BestDistance);620 if (!Best || Distance < BestDistance) {621 Best = O;622 BestDistance = Distance;623 if (RHS.empty() || !PermitValue)624 NearestString = std::string(Name);625 else626 NearestString = (Twine(Name) + "=" + RHS).str();627 }628 }629 }630 631 return Best;632}633 634/// CommaSeparateAndAddOccurrence - A wrapper around Handler->addOccurrence()635/// that does special handling of cl::CommaSeparated options.636static bool CommaSeparateAndAddOccurrence(Option *Handler, unsigned pos,637 StringRef ArgName, StringRef Value,638 bool MultiArg = false) {639 // Check to see if this option accepts a comma separated list of values. If640 // it does, we have to split up the value into multiple values.641 if (Handler->getMiscFlags() & CommaSeparated) {642 StringRef Val(Value);643 StringRef::size_type Pos = Val.find(',');644 645 while (Pos != StringRef::npos) {646 // Process the portion before the comma.647 if (Handler->addOccurrence(pos, ArgName, Val.substr(0, Pos), MultiArg))648 return true;649 // Erase the portion before the comma, AND the comma.650 Val = Val.substr(Pos + 1);651 // Check for another comma.652 Pos = Val.find(',');653 }654 655 Value = Val;656 }657 658 return Handler->addOccurrence(pos, ArgName, Value, MultiArg);659}660 661/// ProvideOption - For Value, this differentiates between an empty value ("")662/// and a null value (StringRef()). The later is accepted for arguments that663/// don't allow a value (-foo) the former is rejected (-foo=).664static inline bool ProvideOption(Option *Handler, StringRef ArgName,665 StringRef Value, int argc,666 const char *const *argv, int &i) {667 // Is this a multi-argument option?668 unsigned NumAdditionalVals = Handler->getNumAdditionalVals();669 670 // Enforce value requirements671 switch (Handler->getValueExpectedFlag()) {672 case ValueRequired:673 if (!Value.data()) { // No value specified?674 // If no other argument or the option only supports prefix form, we675 // cannot look at the next argument.676 if (i + 1 >= argc || Handler->getFormattingFlag() == cl::AlwaysPrefix)677 return Handler->error("requires a value!");678 // Steal the next argument, like for '-o filename'679 assert(argv && "null check");680 Value = StringRef(argv[++i]);681 }682 break;683 case ValueDisallowed:684 if (NumAdditionalVals > 0)685 return Handler->error("multi-valued option specified"686 " with ValueDisallowed modifier!");687 688 if (Value.data())689 return Handler->error("does not allow a value! '" + Twine(Value) +690 "' specified.");691 break;692 case ValueOptional:693 break;694 }695 696 // If this isn't a multi-arg option, just run the handler.697 if (NumAdditionalVals == 0)698 return CommaSeparateAndAddOccurrence(Handler, i, ArgName, Value);699 700 // If it is, run the handle several times.701 bool MultiArg = false;702 703 if (Value.data()) {704 if (CommaSeparateAndAddOccurrence(Handler, i, ArgName, Value, MultiArg))705 return true;706 --NumAdditionalVals;707 MultiArg = true;708 }709 710 while (NumAdditionalVals > 0) {711 if (i + 1 >= argc)712 return Handler->error("not enough values!");713 assert(argv && "null check");714 Value = StringRef(argv[++i]);715 716 if (CommaSeparateAndAddOccurrence(Handler, i, ArgName, Value, MultiArg))717 return true;718 MultiArg = true;719 --NumAdditionalVals;720 }721 return false;722}723 724bool llvm::cl::ProvidePositionalOption(Option *Handler, StringRef Arg, int i) {725 int Dummy = i;726 return ProvideOption(Handler, Handler->ArgStr, Arg, 0, nullptr, Dummy);727}728 729// getOptionPred - Check to see if there are any options that satisfy the730// specified predicate with names that are the prefixes in Name. This is731// checked by progressively stripping characters off of the name, checking to732// see if there options that satisfy the predicate. If we find one, return it,733// otherwise return null.734//735static Option *getOptionPred(StringRef Name, size_t &Length,736 bool (*Pred)(const Option *),737 const StringMap<Option *> &OptionsMap) {738 StringMap<Option *>::const_iterator OMI = OptionsMap.find(Name);739 if (OMI != OptionsMap.end() && !Pred(OMI->getValue()))740 OMI = OptionsMap.end();741 742 // Loop while we haven't found an option and Name still has at least two743 // characters in it (so that the next iteration will not be the empty744 // string.745 while (OMI == OptionsMap.end() && Name.size() > 1) {746 Name = Name.drop_back();747 OMI = OptionsMap.find(Name);748 if (OMI != OptionsMap.end() && !Pred(OMI->getValue()))749 OMI = OptionsMap.end();750 }751 752 if (OMI != OptionsMap.end() && Pred(OMI->second)) {753 Length = Name.size();754 return OMI->second; // Found one!755 }756 return nullptr; // No option found!757}758 759/// HandlePrefixedOrGroupedOption - The specified argument string (which started760/// with at least one '-') does not fully match an available option. Check to761/// see if this is a prefix or grouped option. If so, split arg into output an762/// Arg/Value pair and return the Option to parse it with.763static Option *764HandlePrefixedOrGroupedOption(StringRef &Arg, StringRef &Value,765 bool &ErrorParsing,766 const StringMap<Option *> &OptionsMap) {767 if (Arg.size() == 1)768 return nullptr;769 770 // Do the lookup!771 size_t Length = 0;772 Option *PGOpt = getOptionPred(Arg, Length, isPrefixedOrGrouping, OptionsMap);773 if (!PGOpt)774 return nullptr;775 776 do {777 StringRef MaybeValue =778 (Length < Arg.size()) ? Arg.substr(Length) : StringRef();779 Arg = Arg.substr(0, Length);780 assert(OptionsMap.count(Arg) && OptionsMap.find(Arg)->second == PGOpt);781 782 // cl::Prefix options do not preserve '=' when used separately.783 // The behavior for them with grouped options should be the same.784 if (MaybeValue.empty() || PGOpt->getFormattingFlag() == cl::AlwaysPrefix ||785 (PGOpt->getFormattingFlag() == cl::Prefix && MaybeValue[0] != '=')) {786 Value = MaybeValue;787 return PGOpt;788 }789 790 if (MaybeValue[0] == '=') {791 Value = MaybeValue.substr(1);792 return PGOpt;793 }794 795 // This must be a grouped option.796 assert(isGrouping(PGOpt) && "Broken getOptionPred!");797 798 // Grouping options inside a group can't have values.799 if (PGOpt->getValueExpectedFlag() == cl::ValueRequired) {800 ErrorParsing |= PGOpt->error("may not occur within a group!");801 return nullptr;802 }803 804 // Because the value for the option is not required, we don't need to pass805 // argc/argv in.806 int Dummy = 0;807 ErrorParsing |= ProvideOption(PGOpt, Arg, StringRef(), 0, nullptr, Dummy);808 809 // Get the next grouping option.810 Arg = MaybeValue;811 PGOpt = getOptionPred(Arg, Length, isGrouping, OptionsMap);812 } while (PGOpt);813 814 // We could not find a grouping option in the remainder of Arg.815 return nullptr;816}817 818static bool RequiresValue(const Option *O) {819 return O->getNumOccurrencesFlag() == cl::Required ||820 O->getNumOccurrencesFlag() == cl::OneOrMore;821}822 823static bool EatsUnboundedNumberOfValues(const Option *O) {824 return O->getNumOccurrencesFlag() == cl::ZeroOrMore ||825 O->getNumOccurrencesFlag() == cl::OneOrMore;826}827 828static bool isWhitespace(char C) {829 return C == ' ' || C == '\t' || C == '\r' || C == '\n';830}831 832static bool isWhitespaceOrNull(char C) {833 return isWhitespace(C) || C == '\0';834}835 836static bool isQuote(char C) { return C == '\"' || C == '\''; }837 838void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver,839 SmallVectorImpl<const char *> &NewArgv,840 bool MarkEOLs) {841 SmallString<128> Token;842 for (size_t I = 0, E = Src.size(); I != E; ++I) {843 // Consume runs of whitespace.844 if (Token.empty()) {845 while (I != E && isWhitespace(Src[I])) {846 // Mark the end of lines in response files.847 if (MarkEOLs && Src[I] == '\n')848 NewArgv.push_back(nullptr);849 ++I;850 }851 if (I == E)852 break;853 }854 855 char C = Src[I];856 857 // Backslash escapes the next character.858 if (I + 1 < E && C == '\\') {859 ++I; // Skip the escape.860 Token.push_back(Src[I]);861 continue;862 }863 864 // Consume a quoted string.865 if (isQuote(C)) {866 ++I;867 while (I != E && Src[I] != C) {868 // Backslash escapes the next character.869 if (Src[I] == '\\' && I + 1 != E)870 ++I;871 Token.push_back(Src[I]);872 ++I;873 }874 if (I == E)875 break;876 continue;877 }878 879 // End the token if this is whitespace.880 if (isWhitespace(C)) {881 if (!Token.empty())882 NewArgv.push_back(Saver.save(Token.str()).data());883 // Mark the end of lines in response files.884 if (MarkEOLs && C == '\n')885 NewArgv.push_back(nullptr);886 Token.clear();887 continue;888 }889 890 // This is a normal character. Append it.891 Token.push_back(C);892 }893 894 // Append the last token after hitting EOF with no whitespace.895 if (!Token.empty())896 NewArgv.push_back(Saver.save(Token.str()).data());897}898 899/// Backslashes are interpreted in a rather complicated way in the Windows-style900/// command line, because backslashes are used both to separate path and to901/// escape double quote. This method consumes runs of backslashes as well as the902/// following double quote if it's escaped.903///904/// * If an even number of backslashes is followed by a double quote, one905/// backslash is output for every pair of backslashes, and the last double906/// quote remains unconsumed. The double quote will later be interpreted as907/// the start or end of a quoted string in the main loop outside of this908/// function.909///910/// * If an odd number of backslashes is followed by a double quote, one911/// backslash is output for every pair of backslashes, and a double quote is912/// output for the last pair of backslash-double quote. The double quote is913/// consumed in this case.914///915/// * Otherwise, backslashes are interpreted literally.916static size_t parseBackslash(StringRef Src, size_t I, SmallString<128> &Token) {917 size_t E = Src.size();918 int BackslashCount = 0;919 // Skip the backslashes.920 do {921 ++I;922 ++BackslashCount;923 } while (I != E && Src[I] == '\\');924 925 bool FollowedByDoubleQuote = (I != E && Src[I] == '"');926 if (FollowedByDoubleQuote) {927 Token.append(BackslashCount / 2, '\\');928 if (BackslashCount % 2 == 0)929 return I - 1;930 Token.push_back('"');931 return I;932 }933 Token.append(BackslashCount, '\\');934 return I - 1;935}936 937// Windows treats whitespace, double quotes, and backslashes specially, except938// when parsing the first token of a full command line, in which case939// backslashes are not special.940static bool isWindowsSpecialChar(char C) {941 return isWhitespaceOrNull(C) || C == '\\' || C == '\"';942}943static bool isWindowsSpecialCharInCommandName(char C) {944 return isWhitespaceOrNull(C) || C == '\"';945}946 947// Windows tokenization implementation. The implementation is designed to be948// inlined and specialized for the two user entry points.949static inline void tokenizeWindowsCommandLineImpl(950 StringRef Src, StringSaver &Saver, function_ref<void(StringRef)> AddToken,951 bool AlwaysCopy, function_ref<void()> MarkEOL, bool InitialCommandName) {952 SmallString<128> Token;953 954 // Sometimes, this function will be handling a full command line including an955 // executable pathname at the start. In that situation, the initial pathname956 // needs different handling from the following arguments, because when957 // CreateProcess or cmd.exe scans the pathname, it doesn't treat \ as958 // escaping the quote character, whereas when libc scans the rest of the959 // command line, it does.960 bool CommandName = InitialCommandName;961 962 // Try to do as much work inside the state machine as possible.963 enum { INIT, UNQUOTED, QUOTED } State = INIT;964 965 for (size_t I = 0, E = Src.size(); I < E; ++I) {966 switch (State) {967 case INIT: {968 assert(Token.empty() && "token should be empty in initial state");969 // Eat whitespace before a token.970 while (I < E && isWhitespaceOrNull(Src[I])) {971 if (Src[I] == '\n')972 MarkEOL();973 ++I;974 }975 // Stop if this was trailing whitespace.976 if (I >= E)977 break;978 size_t Start = I;979 if (CommandName) {980 while (I < E && !isWindowsSpecialCharInCommandName(Src[I]))981 ++I;982 } else {983 while (I < E && !isWindowsSpecialChar(Src[I]))984 ++I;985 }986 StringRef NormalChars = Src.slice(Start, I);987 if (I >= E || isWhitespaceOrNull(Src[I])) {988 // No special characters: slice out the substring and start the next989 // token. Copy the string if the caller asks us to.990 AddToken(AlwaysCopy ? Saver.save(NormalChars) : NormalChars);991 if (I < E && Src[I] == '\n') {992 MarkEOL();993 CommandName = InitialCommandName;994 } else {995 CommandName = false;996 }997 } else if (Src[I] == '\"') {998 Token += NormalChars;999 State = QUOTED;1000 } else if (Src[I] == '\\') {1001 assert(!CommandName && "or else we'd have treated it as a normal char");1002 Token += NormalChars;1003 I = parseBackslash(Src, I, Token);1004 State = UNQUOTED;1005 } else {1006 llvm_unreachable("unexpected special character");1007 }1008 break;1009 }1010 1011 case UNQUOTED:1012 if (isWhitespaceOrNull(Src[I])) {1013 // Whitespace means the end of the token. If we are in this state, the1014 // token must have contained a special character, so we must copy the1015 // token.1016 AddToken(Saver.save(Token.str()));1017 Token.clear();1018 if (Src[I] == '\n') {1019 CommandName = InitialCommandName;1020 MarkEOL();1021 } else {1022 CommandName = false;1023 }1024 State = INIT;1025 } else if (Src[I] == '\"') {1026 State = QUOTED;1027 } else if (Src[I] == '\\' && !CommandName) {1028 I = parseBackslash(Src, I, Token);1029 } else {1030 Token.push_back(Src[I]);1031 }1032 break;1033 1034 case QUOTED:1035 if (Src[I] == '\"') {1036 if (I < (E - 1) && Src[I + 1] == '"') {1037 // Consecutive double-quotes inside a quoted string implies one1038 // double-quote.1039 Token.push_back('"');1040 ++I;1041 } else {1042 // Otherwise, end the quoted portion and return to the unquoted state.1043 State = UNQUOTED;1044 }1045 } else if (Src[I] == '\\' && !CommandName) {1046 I = parseBackslash(Src, I, Token);1047 } else {1048 Token.push_back(Src[I]);1049 }1050 break;1051 }1052 }1053 1054 if (State != INIT)1055 AddToken(Saver.save(Token.str()));1056}1057 1058void cl::TokenizeWindowsCommandLine(StringRef Src, StringSaver &Saver,1059 SmallVectorImpl<const char *> &NewArgv,1060 bool MarkEOLs) {1061 auto AddToken = [&](StringRef Tok) { NewArgv.push_back(Tok.data()); };1062 auto OnEOL = [&]() {1063 if (MarkEOLs)1064 NewArgv.push_back(nullptr);1065 };1066 tokenizeWindowsCommandLineImpl(Src, Saver, AddToken,1067 /*AlwaysCopy=*/true, OnEOL, false);1068}1069 1070void cl::TokenizeWindowsCommandLineNoCopy(StringRef Src, StringSaver &Saver,1071 SmallVectorImpl<StringRef> &NewArgv) {1072 auto AddToken = [&](StringRef Tok) { NewArgv.push_back(Tok); };1073 auto OnEOL = []() {};1074 tokenizeWindowsCommandLineImpl(Src, Saver, AddToken, /*AlwaysCopy=*/false,1075 OnEOL, false);1076}1077 1078void cl::TokenizeWindowsCommandLineFull(StringRef Src, StringSaver &Saver,1079 SmallVectorImpl<const char *> &NewArgv,1080 bool MarkEOLs) {1081 auto AddToken = [&](StringRef Tok) { NewArgv.push_back(Tok.data()); };1082 auto OnEOL = [&]() {1083 if (MarkEOLs)1084 NewArgv.push_back(nullptr);1085 };1086 tokenizeWindowsCommandLineImpl(Src, Saver, AddToken,1087 /*AlwaysCopy=*/true, OnEOL, true);1088}1089 1090void cl::tokenizeConfigFile(StringRef Source, StringSaver &Saver,1091 SmallVectorImpl<const char *> &NewArgv,1092 bool MarkEOLs) {1093 for (const char *Cur = Source.begin(); Cur != Source.end();) {1094 SmallString<128> Line;1095 // Check for comment line.1096 if (isWhitespace(*Cur)) {1097 while (Cur != Source.end() && isWhitespace(*Cur))1098 ++Cur;1099 continue;1100 }1101 if (*Cur == '#') {1102 while (Cur != Source.end() && *Cur != '\n')1103 ++Cur;1104 continue;1105 }1106 // Find end of the current line.1107 const char *Start = Cur;1108 for (const char *End = Source.end(); Cur != End; ++Cur) {1109 if (*Cur == '\\') {1110 if (Cur + 1 != End) {1111 ++Cur;1112 if (*Cur == '\n' ||1113 (*Cur == '\r' && (Cur + 1 != End) && Cur[1] == '\n')) {1114 Line.append(Start, Cur - 1);1115 if (*Cur == '\r')1116 ++Cur;1117 Start = Cur + 1;1118 }1119 }1120 } else if (*Cur == '\n')1121 break;1122 }1123 // Tokenize line.1124 Line.append(Start, Cur);1125 cl::TokenizeGNUCommandLine(Line, Saver, NewArgv, MarkEOLs);1126 }1127}1128 1129// It is called byte order marker but the UTF-8 BOM is actually not affected1130// by the host system's endianness.1131static bool hasUTF8ByteOrderMark(ArrayRef<char> S) {1132 return (S.size() >= 3 && S[0] == '\xef' && S[1] == '\xbb' && S[2] == '\xbf');1133}1134 1135// Substitute <CFGDIR> with the file's base path.1136static void ExpandBasePaths(StringRef BasePath, StringSaver &Saver,1137 const char *&Arg) {1138 assert(sys::path::is_absolute(BasePath));1139 constexpr StringLiteral Token("<CFGDIR>");1140 const StringRef ArgString(Arg);1141 1142 SmallString<128> ResponseFile;1143 StringRef::size_type StartPos = 0;1144 for (StringRef::size_type TokenPos = ArgString.find(Token);1145 TokenPos != StringRef::npos;1146 TokenPos = ArgString.find(Token, StartPos)) {1147 // Token may appear more than once per arg (e.g. comma-separated linker1148 // args). Support by using path-append on any subsequent appearances.1149 const StringRef LHS = ArgString.substr(StartPos, TokenPos - StartPos);1150 if (ResponseFile.empty())1151 ResponseFile = LHS;1152 else1153 llvm::sys::path::append(ResponseFile, LHS);1154 ResponseFile.append(BasePath);1155 StartPos = TokenPos + Token.size();1156 }1157 1158 if (!ResponseFile.empty()) {1159 // Path-append the remaining arg substring if at least one token appeared.1160 const StringRef Remaining = ArgString.substr(StartPos);1161 if (!Remaining.empty())1162 llvm::sys::path::append(ResponseFile, Remaining);1163 Arg = Saver.save(ResponseFile.str()).data();1164 }1165}1166 1167// FName must be an absolute path.1168Error ExpansionContext::expandResponseFile(1169 StringRef FName, SmallVectorImpl<const char *> &NewArgv) {1170 assert(sys::path::is_absolute(FName));1171 llvm::ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr =1172 FS->getBufferForFile(FName);1173 if (!MemBufOrErr) {1174 std::error_code EC = MemBufOrErr.getError();1175 return llvm::createStringError(EC, Twine("cannot not open file '") + FName +1176 "': " + EC.message());1177 }1178 MemoryBuffer &MemBuf = *MemBufOrErr.get();1179 StringRef Str(MemBuf.getBufferStart(), MemBuf.getBufferSize());1180 1181 // If we have a UTF-16 byte order mark, convert to UTF-8 for parsing.1182 ArrayRef<char> BufRef(MemBuf.getBufferStart(), MemBuf.getBufferEnd());1183 std::string UTF8Buf;1184 if (hasUTF16ByteOrderMark(BufRef)) {1185 if (!convertUTF16ToUTF8String(BufRef, UTF8Buf))1186 return llvm::createStringError(std::errc::illegal_byte_sequence,1187 "Could not convert UTF16 to UTF8");1188 Str = StringRef(UTF8Buf);1189 }1190 // If we see UTF-8 BOM sequence at the beginning of a file, we shall remove1191 // these bytes before parsing.1192 // Reference: http://en.wikipedia.org/wiki/UTF-8#Byte_order_mark1193 else if (hasUTF8ByteOrderMark(BufRef))1194 Str = StringRef(BufRef.data() + 3, BufRef.size() - 3);1195 1196 // Tokenize the contents into NewArgv.1197 Tokenizer(Str, Saver, NewArgv, MarkEOLs);1198 1199 // Expanded file content may require additional transformations, like using1200 // absolute paths instead of relative in '@file' constructs or expanding1201 // macros.1202 if (!RelativeNames && !InConfigFile)1203 return Error::success();1204 1205 StringRef BasePath = llvm::sys::path::parent_path(FName);1206 for (const char *&Arg : NewArgv) {1207 if (!Arg)1208 continue;1209 1210 // Substitute <CFGDIR> with the file's base path.1211 if (InConfigFile)1212 ExpandBasePaths(BasePath, Saver, Arg);1213 1214 // Discover the case, when argument should be transformed into '@file' and1215 // evaluate 'file' for it.1216 StringRef ArgStr(Arg);1217 StringRef FileName;1218 bool ConfigInclusion = false;1219 if (ArgStr.consume_front("@")) {1220 FileName = ArgStr;1221 if (!llvm::sys::path::is_relative(FileName))1222 continue;1223 } else if (ArgStr.consume_front("--config=")) {1224 FileName = ArgStr;1225 ConfigInclusion = true;1226 } else {1227 continue;1228 }1229 1230 // Update expansion construct.1231 SmallString<128> ResponseFile;1232 ResponseFile.push_back('@');1233 if (ConfigInclusion && !llvm::sys::path::has_parent_path(FileName)) {1234 SmallString<128> FilePath;1235 if (!findConfigFile(FileName, FilePath))1236 return createStringError(1237 std::make_error_code(std::errc::no_such_file_or_directory),1238 "cannot not find configuration file: " + FileName);1239 ResponseFile.append(FilePath);1240 } else {1241 ResponseFile.append(BasePath);1242 llvm::sys::path::append(ResponseFile, FileName);1243 }1244 Arg = Saver.save(ResponseFile.str()).data();1245 }1246 return Error::success();1247}1248 1249/// Expand response files on a command line recursively using the given1250/// StringSaver and tokenization strategy.1251Error ExpansionContext::expandResponseFiles(1252 SmallVectorImpl<const char *> &Argv) {1253 struct ResponseFileRecord {1254 std::string File;1255 size_t End;1256 };1257 1258 // To detect recursive response files, we maintain a stack of files and the1259 // position of the last argument in the file. This position is updated1260 // dynamically as we recursively expand files.1261 SmallVector<ResponseFileRecord, 3> FileStack;1262 1263 // Push a dummy entry that represents the initial command line, removing1264 // the need to check for an empty list.1265 FileStack.push_back({"", Argv.size()});1266 1267 // Don't cache Argv.size() because it can change.1268 for (unsigned I = 0; I != Argv.size();) {1269 while (I == FileStack.back().End) {1270 // Passing the end of a file's argument list, so we can remove it from the1271 // stack.1272 FileStack.pop_back();1273 }1274 1275 const char *Arg = Argv[I];1276 // Check if it is an EOL marker1277 if (Arg == nullptr) {1278 ++I;1279 continue;1280 }1281 1282 if (Arg[0] != '@') {1283 ++I;1284 continue;1285 }1286 1287 const char *FName = Arg + 1;1288 // Note that CurrentDir is only used for top-level rsp files, the rest will1289 // always have an absolute path deduced from the containing file.1290 SmallString<128> CurrDir;1291 if (llvm::sys::path::is_relative(FName)) {1292 if (CurrentDir.empty()) {1293 if (auto CWD = FS->getCurrentWorkingDirectory()) {1294 CurrDir = *CWD;1295 } else {1296 return createStringError(1297 CWD.getError(), Twine("cannot get absolute path for: ") + FName);1298 }1299 } else {1300 CurrDir = CurrentDir;1301 }1302 llvm::sys::path::append(CurrDir, FName);1303 FName = CurrDir.c_str();1304 }1305 1306 ErrorOr<llvm::vfs::Status> Res = FS->status(FName);1307 if (!Res || !Res->exists()) {1308 std::error_code EC = Res.getError();1309 if (!InConfigFile) {1310 // If the specified file does not exist, leave '@file' unexpanded, as1311 // libiberty does.1312 if (!EC || EC == llvm::errc::no_such_file_or_directory) {1313 ++I;1314 continue;1315 }1316 }1317 if (!EC)1318 EC = llvm::errc::no_such_file_or_directory;1319 return createStringError(EC, Twine("cannot not open file '") + FName +1320 "': " + EC.message());1321 }1322 const llvm::vfs::Status &FileStatus = Res.get();1323 1324 auto IsEquivalent =1325 [FileStatus, this](const ResponseFileRecord &RFile) -> ErrorOr<bool> {1326 ErrorOr<llvm::vfs::Status> RHS = FS->status(RFile.File);1327 if (!RHS)1328 return RHS.getError();1329 return FileStatus.equivalent(*RHS);1330 };1331 1332 // Check for recursive response files.1333 for (const auto &F : drop_begin(FileStack)) {1334 if (ErrorOr<bool> R = IsEquivalent(F)) {1335 if (R.get())1336 return createStringError(1337 R.getError(), Twine("recursive expansion of: '") + F.File + "'");1338 } else {1339 return createStringError(R.getError(),1340 Twine("cannot open file: ") + F.File);1341 }1342 }1343 1344 // Replace this response file argument with the tokenization of its1345 // contents. Nested response files are expanded in subsequent iterations.1346 SmallVector<const char *, 0> ExpandedArgv;1347 if (Error Err = expandResponseFile(FName, ExpandedArgv))1348 return Err;1349 1350 for (ResponseFileRecord &Record : FileStack) {1351 // Increase the end of all active records by the number of newly expanded1352 // arguments, minus the response file itself.1353 Record.End += ExpandedArgv.size() - 1;1354 }1355 1356 FileStack.push_back({FName, I + ExpandedArgv.size()});1357 Argv.erase(Argv.begin() + I);1358 Argv.insert(Argv.begin() + I, ExpandedArgv.begin(), ExpandedArgv.end());1359 }1360 1361 // If successful, the top of the file stack will mark the end of the Argv1362 // stream. A failure here indicates a bug in the stack popping logic above.1363 // Note that FileStack may have more than one element at this point because we1364 // don't have a chance to pop the stack when encountering recursive files at1365 // the end of the stream, so seeing that doesn't indicate a bug.1366 assert(FileStack.size() > 0 && Argv.size() == FileStack.back().End);1367 return Error::success();1368}1369 1370bool cl::expandResponseFiles(int Argc, const char *const *Argv,1371 const char *EnvVar, StringSaver &Saver,1372 SmallVectorImpl<const char *> &NewArgv) {1373#ifdef _WIN321374 auto Tokenize = cl::TokenizeWindowsCommandLine;1375#else1376 auto Tokenize = cl::TokenizeGNUCommandLine;1377#endif1378 // The environment variable specifies initial options.1379 if (EnvVar)1380 if (std::optional<std::string> EnvValue = sys::Process::GetEnv(EnvVar))1381 Tokenize(*EnvValue, Saver, NewArgv, /*MarkEOLs=*/false);1382 1383 // Command line options can override the environment variable.1384 NewArgv.append(Argv + 1, Argv + Argc);1385 ExpansionContext ECtx(Saver.getAllocator(), Tokenize);1386 if (Error Err = ECtx.expandResponseFiles(NewArgv)) {1387 errs() << toString(std::move(Err)) << '\n';1388 return false;1389 }1390 return true;1391}1392 1393bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,1394 SmallVectorImpl<const char *> &Argv) {1395 ExpansionContext ECtx(Saver.getAllocator(), Tokenizer);1396 if (Error Err = ECtx.expandResponseFiles(Argv)) {1397 errs() << toString(std::move(Err)) << '\n';1398 return false;1399 }1400 return true;1401}1402 1403ExpansionContext::ExpansionContext(BumpPtrAllocator &A, TokenizerCallback T,1404 vfs::FileSystem *FS)1405 : Saver(A), Tokenizer(T), FS(FS ? FS : vfs::getRealFileSystem().get()) {}1406 1407bool ExpansionContext::findConfigFile(StringRef FileName,1408 SmallVectorImpl<char> &FilePath) {1409 SmallString<128> CfgFilePath;1410 const auto FileExists = [this](SmallString<128> Path) -> bool {1411 auto Status = FS->status(Path);1412 return Status &&1413 Status->getType() == llvm::sys::fs::file_type::regular_file;1414 };1415 1416 // If file name contains directory separator, treat it as a path to1417 // configuration file.1418 if (llvm::sys::path::has_parent_path(FileName)) {1419 CfgFilePath = FileName;1420 if (llvm::sys::path::is_relative(FileName) && FS->makeAbsolute(CfgFilePath))1421 return false;1422 if (!FileExists(CfgFilePath))1423 return false;1424 FilePath.assign(CfgFilePath.begin(), CfgFilePath.end());1425 return true;1426 }1427 1428 // Look for the file in search directories.1429 for (const StringRef &Dir : SearchDirs) {1430 if (Dir.empty())1431 continue;1432 CfgFilePath.assign(Dir);1433 llvm::sys::path::append(CfgFilePath, FileName);1434 llvm::sys::path::native(CfgFilePath);1435 if (FileExists(CfgFilePath)) {1436 FilePath.assign(CfgFilePath.begin(), CfgFilePath.end());1437 return true;1438 }1439 }1440 1441 return false;1442}1443 1444Error ExpansionContext::readConfigFile(StringRef CfgFile,1445 SmallVectorImpl<const char *> &Argv) {1446 SmallString<128> AbsPath;1447 if (sys::path::is_relative(CfgFile)) {1448 AbsPath.assign(CfgFile);1449 if (std::error_code EC = FS->makeAbsolute(AbsPath))1450 return make_error<StringError>(1451 EC, Twine("cannot get absolute path for " + CfgFile));1452 CfgFile = AbsPath.str();1453 }1454 InConfigFile = true;1455 RelativeNames = true;1456 if (Error Err = expandResponseFile(CfgFile, Argv))1457 return Err;1458 return expandResponseFiles(Argv);1459}1460 1461static void initCommonOptions();1462bool cl::ParseCommandLineOptions(int argc, const char *const *argv,1463 StringRef Overview, raw_ostream *Errs,1464 vfs::FileSystem *VFS, const char *EnvVar,1465 bool LongOptionsUseDoubleDash) {1466 initCommonOptions();1467 SmallVector<const char *, 20> NewArgv;1468 BumpPtrAllocator A;1469 StringSaver Saver(A);1470 NewArgv.push_back(argv[0]);1471 1472 // Parse options from environment variable.1473 if (EnvVar) {1474 if (std::optional<std::string> EnvValue =1475 sys::Process::GetEnv(StringRef(EnvVar)))1476 TokenizeGNUCommandLine(*EnvValue, Saver, NewArgv);1477 }1478 1479 // Append options from command line.1480 for (int I = 1; I < argc; ++I)1481 NewArgv.push_back(argv[I]);1482 int NewArgc = static_cast<int>(NewArgv.size());1483 1484 // Parse all options.1485 return GlobalParser->ParseCommandLineOptions(1486 NewArgc, &NewArgv[0], Overview, Errs, VFS, LongOptionsUseDoubleDash);1487}1488 1489/// Reset all options at least once, so that we can parse different options.1490void CommandLineParser::ResetAllOptionOccurrences() {1491 // Reset all option values to look like they have never been seen before.1492 // Options might be reset twice (they can be reference in both OptionsMap1493 // and one of the other members), but that does not harm.1494 for (auto *SC : RegisteredSubCommands) {1495 for (auto &O : SC->OptionsMap)1496 O.second->reset();1497 for (Option *O : SC->PositionalOpts)1498 O->reset();1499 for (Option *O : SC->SinkOpts)1500 O->reset();1501 if (SC->ConsumeAfterOpt)1502 SC->ConsumeAfterOpt->reset();1503 }1504}1505 1506bool CommandLineParser::ParseCommandLineOptions(1507 int argc, const char *const *argv, StringRef Overview, raw_ostream *Errs,1508 vfs::FileSystem *VFS, bool LongOptionsUseDoubleDash) {1509 assert(hasOptions() && "No options specified!");1510 1511 ProgramOverview = Overview;1512 bool IgnoreErrors = Errs;1513 if (!Errs)1514 Errs = &errs();1515 if (!VFS)1516 VFS = vfs::getRealFileSystem().get();1517 bool ErrorParsing = false;1518 1519 // Expand response files.1520 SmallVector<const char *, 20> newArgv(argv, argv + argc);1521 BumpPtrAllocator A;1522#ifdef _WIN321523 auto Tokenize = cl::TokenizeWindowsCommandLine;1524#else1525 auto Tokenize = cl::TokenizeGNUCommandLine;1526#endif1527 ExpansionContext ECtx(A, Tokenize, VFS);1528 if (Error Err = ECtx.expandResponseFiles(newArgv)) {1529 *Errs << toString(std::move(Err)) << '\n';1530 return false;1531 }1532 argv = &newArgv[0];1533 argc = static_cast<int>(newArgv.size());1534 1535 // Copy the program name into ProgName, making sure not to overflow it.1536 ProgramName = std::string(sys::path::filename(StringRef(argv[0])));1537 1538 // Check out the positional arguments to collect information about them.1539 unsigned NumPositionalRequired = 0;1540 1541 // Determine whether or not there are an unlimited number of positionals1542 bool HasUnlimitedPositionals = false;1543 1544 int FirstArg = 1;1545 SubCommand *ChosenSubCommand = &SubCommand::getTopLevel();1546 std::string NearestSubCommandString;1547 bool MaybeNamedSubCommand =1548 argc >= 2 && argv[FirstArg][0] != '-' && hasNamedSubCommands();1549 if (MaybeNamedSubCommand) {1550 // If the first argument specifies a valid subcommand, start processing1551 // options from the second argument.1552 ChosenSubCommand =1553 LookupSubCommand(StringRef(argv[FirstArg]), NearestSubCommandString);1554 if (ChosenSubCommand != &SubCommand::getTopLevel())1555 FirstArg = 2;1556 }1557 GlobalParser->ActiveSubCommand = ChosenSubCommand;1558 1559 assert(ChosenSubCommand);1560 auto &ConsumeAfterOpt = ChosenSubCommand->ConsumeAfterOpt;1561 auto &PositionalOpts = ChosenSubCommand->PositionalOpts;1562 auto &SinkOpts = ChosenSubCommand->SinkOpts;1563 auto &OptionsMap = ChosenSubCommand->OptionsMap;1564 1565 for (auto *O: DefaultOptions) {1566 addOption(O, true);1567 }1568 1569 if (ConsumeAfterOpt) {1570 assert(PositionalOpts.size() > 0 &&1571 "Cannot specify cl::ConsumeAfter without a positional argument!");1572 }1573 if (!PositionalOpts.empty()) {1574 1575 // Calculate how many positional values are _required_.1576 bool UnboundedFound = false;1577 for (size_t i = 0, e = PositionalOpts.size(); i != e; ++i) {1578 Option *Opt = PositionalOpts[i];1579 if (RequiresValue(Opt))1580 ++NumPositionalRequired;1581 else if (ConsumeAfterOpt) {1582 // ConsumeAfter cannot be combined with "optional" positional options1583 // unless there is only one positional argument...1584 if (PositionalOpts.size() > 1) {1585 if (!IgnoreErrors)1586 Opt->error("error - this positional option will never be matched, "1587 "because it does not Require a value, and a "1588 "cl::ConsumeAfter option is active!");1589 ErrorParsing = true;1590 }1591 } else if (UnboundedFound && !Opt->hasArgStr()) {1592 // This option does not "require" a value... Make sure this option is1593 // not specified after an option that eats all extra arguments, or this1594 // one will never get any!1595 //1596 if (!IgnoreErrors)1597 Opt->error("error - option can never match, because "1598 "another positional argument will match an "1599 "unbounded number of values, and this option"1600 " does not require a value!");1601 *Errs << ProgramName << ": CommandLine Error: Option '" << Opt->ArgStr1602 << "' is all messed up!\n";1603 *Errs << PositionalOpts.size();1604 ErrorParsing = true;1605 }1606 UnboundedFound |= EatsUnboundedNumberOfValues(Opt);1607 }1608 HasUnlimitedPositionals = UnboundedFound || ConsumeAfterOpt;1609 }1610 1611 // PositionalVals - A vector of "positional" arguments we accumulate into1612 // the process at the end.1613 //1614 SmallVector<std::pair<StringRef, unsigned>, 4> PositionalVals;1615 1616 // If the program has named positional arguments, and the name has been run1617 // across, keep track of which positional argument was named. Otherwise put1618 // the positional args into the PositionalVals list...1619 Option *ActivePositionalArg = nullptr;1620 1621 // Loop over all of the arguments... processing them.1622 bool DashDashFound = false; // Have we read '--'?1623 for (int i = FirstArg; i < argc; ++i) {1624 Option *Handler = nullptr;1625 std::string NearestHandlerString;1626 StringRef Value;1627 StringRef ArgName = "";1628 bool HaveDoubleDash = false;1629 1630 // Check to see if this is a positional argument. This argument is1631 // considered to be positional if it doesn't start with '-', if it is "-"1632 // itself, or if we have seen "--" already.1633 //1634 if (argv[i][0] != '-' || argv[i][1] == 0 || DashDashFound) {1635 // Positional argument!1636 if (ActivePositionalArg) {1637 ProvidePositionalOption(ActivePositionalArg, StringRef(argv[i]), i);1638 continue; // We are done!1639 }1640 1641 if (!PositionalOpts.empty()) {1642 PositionalVals.push_back(std::make_pair(StringRef(argv[i]), i));1643 1644 // All of the positional arguments have been fulfulled, give the rest to1645 // the consume after option... if it's specified...1646 //1647 if (PositionalVals.size() >= NumPositionalRequired && ConsumeAfterOpt) {1648 for (++i; i < argc; ++i)1649 PositionalVals.push_back(std::make_pair(StringRef(argv[i]), i));1650 break; // Handle outside of the argument processing loop...1651 }1652 1653 // Delay processing positional arguments until the end...1654 continue;1655 }1656 } else if (argv[i][0] == '-' && argv[i][1] == '-' && argv[i][2] == 0 &&1657 !DashDashFound) {1658 DashDashFound = true; // This is the mythical "--"?1659 continue; // Don't try to process it as an argument itself.1660 } else if (ActivePositionalArg &&1661 (ActivePositionalArg->getMiscFlags() & PositionalEatsArgs)) {1662 // If there is a positional argument eating options, check to see if this1663 // option is another positional argument. If so, treat it as an argument,1664 // otherwise feed it to the eating positional.1665 ArgName = StringRef(argv[i] + 1);1666 // Eat second dash.1667 if (ArgName.consume_front("-"))1668 HaveDoubleDash = true;1669 1670 Handler = LookupLongOption(*ChosenSubCommand, ArgName, Value,1671 LongOptionsUseDoubleDash, HaveDoubleDash);1672 if (!Handler || Handler->getFormattingFlag() != cl::Positional) {1673 ProvidePositionalOption(ActivePositionalArg, StringRef(argv[i]), i);1674 continue; // We are done!1675 }1676 } else { // We start with a '-', must be an argument.1677 ArgName = StringRef(argv[i] + 1);1678 // Eat second dash.1679 if (ArgName.consume_front("-"))1680 HaveDoubleDash = true;1681 1682 Handler = LookupLongOption(*ChosenSubCommand, ArgName, Value,1683 LongOptionsUseDoubleDash, HaveDoubleDash);1684 1685 // If Handler is not found in a specialized subcommand, look up handler1686 // in the top-level subcommand.1687 // cl::opt without cl::sub belongs to top-level subcommand.1688 if (!Handler && ChosenSubCommand != &SubCommand::getTopLevel())1689 Handler = LookupLongOption(SubCommand::getTopLevel(), ArgName, Value,1690 LongOptionsUseDoubleDash, HaveDoubleDash);1691 1692 // Check to see if this "option" is really a prefixed or grouped argument.1693 if (!Handler && !(LongOptionsUseDoubleDash && HaveDoubleDash))1694 Handler = HandlePrefixedOrGroupedOption(ArgName, Value, ErrorParsing,1695 OptionsMap);1696 1697 // Otherwise, look for the closest available option to report to the user1698 // in the upcoming error.1699 if (!Handler && SinkOpts.empty())1700 LookupNearestOption(ArgName, OptionsMap, NearestHandlerString);1701 }1702 1703 if (!Handler) {1704 if (!SinkOpts.empty()) {1705 for (Option *SinkOpt : SinkOpts)1706 SinkOpt->addOccurrence(i, "", StringRef(argv[i]));1707 continue;1708 }1709 1710 auto ReportUnknownArgument = [&](bool IsArg,1711 StringRef NearestArgumentName) {1712 *Errs << ProgramName << ": Unknown "1713 << (IsArg ? "command line argument" : "subcommand") << " '"1714 << argv[i] << "'. Try: '" << argv[0] << " --help'\n";1715 1716 if (NearestArgumentName.empty())1717 return;1718 1719 *Errs << ProgramName << ": Did you mean '";1720 if (IsArg)1721 *Errs << PrintArg(NearestArgumentName, 0);1722 else1723 *Errs << NearestArgumentName;1724 *Errs << "'?\n";1725 };1726 1727 if (i > 1 || !MaybeNamedSubCommand)1728 ReportUnknownArgument(/*IsArg=*/true, NearestHandlerString);1729 else1730 ReportUnknownArgument(/*IsArg=*/false, NearestSubCommandString);1731 1732 ErrorParsing = true;1733 continue;1734 }1735 1736 // If this is a named positional argument, just remember that it is the1737 // active one...1738 if (Handler->getFormattingFlag() == cl::Positional) {1739 if ((Handler->getMiscFlags() & PositionalEatsArgs) && !Value.empty()) {1740 Handler->error("This argument does not take a value.\n"1741 "\tInstead, it consumes any positional arguments until "1742 "the next recognized option.", *Errs);1743 ErrorParsing = true;1744 }1745 ActivePositionalArg = Handler;1746 }1747 else1748 ErrorParsing |= ProvideOption(Handler, ArgName, Value, argc, argv, i);1749 }1750 1751 // Check and handle positional arguments now...1752 if (NumPositionalRequired > PositionalVals.size()) {1753 *Errs << ProgramName1754 << ": Not enough positional command line arguments specified!\n"1755 << "Must specify at least " << NumPositionalRequired1756 << " positional argument" << (NumPositionalRequired > 1 ? "s" : "")1757 << ": See: " << argv[0] << " --help\n";1758 1759 ErrorParsing = true;1760 } else if (!HasUnlimitedPositionals &&1761 PositionalVals.size() > PositionalOpts.size()) {1762 *Errs << ProgramName << ": Too many positional arguments specified!\n"1763 << "Can specify at most " << PositionalOpts.size()1764 << " positional arguments: See: " << argv[0] << " --help\n";1765 ErrorParsing = true;1766 1767 } else if (!ConsumeAfterOpt) {1768 // Positional args have already been handled if ConsumeAfter is specified.1769 unsigned ValNo = 0, NumVals = static_cast<unsigned>(PositionalVals.size());1770 for (Option *Opt : PositionalOpts) {1771 if (RequiresValue(Opt)) {1772 ProvidePositionalOption(Opt, PositionalVals[ValNo].first,1773 PositionalVals[ValNo].second);1774 ValNo++;1775 --NumPositionalRequired; // We fulfilled our duty...1776 }1777 1778 // If we _can_ give this option more arguments, do so now, as long as we1779 // do not give it values that others need. 'Done' controls whether the1780 // option even _WANTS_ any more.1781 //1782 bool Done = Opt->getNumOccurrencesFlag() == cl::Required;1783 while (NumVals - ValNo > NumPositionalRequired && !Done) {1784 switch (Opt->getNumOccurrencesFlag()) {1785 case cl::Optional:1786 Done = true; // Optional arguments want _at most_ one value1787 [[fallthrough]];1788 case cl::ZeroOrMore: // Zero or more will take all they can get...1789 case cl::OneOrMore: // One or more will take all they can get...1790 ProvidePositionalOption(Opt, PositionalVals[ValNo].first,1791 PositionalVals[ValNo].second);1792 ValNo++;1793 break;1794 default:1795 llvm_unreachable("Internal error, unexpected NumOccurrences flag in "1796 "positional argument processing!");1797 }1798 }1799 }1800 } else {1801 assert(ConsumeAfterOpt && NumPositionalRequired <= PositionalVals.size());1802 unsigned ValNo = 0;1803 for (Option *Opt : PositionalOpts)1804 if (RequiresValue(Opt)) {1805 ErrorParsing |= ProvidePositionalOption(1806 Opt, PositionalVals[ValNo].first, PositionalVals[ValNo].second);1807 ValNo++;1808 }1809 1810 // Handle the case where there is just one positional option, and it's1811 // optional. In this case, we want to give JUST THE FIRST option to the1812 // positional option and keep the rest for the consume after. The above1813 // loop would have assigned no values to positional options in this case.1814 //1815 if (PositionalOpts.size() == 1 && ValNo == 0 && !PositionalVals.empty()) {1816 ErrorParsing |= ProvidePositionalOption(PositionalOpts[0],1817 PositionalVals[ValNo].first,1818 PositionalVals[ValNo].second);1819 ValNo++;1820 }1821 1822 // Handle over all of the rest of the arguments to the1823 // cl::ConsumeAfter command line option...1824 for (; ValNo != PositionalVals.size(); ++ValNo)1825 ErrorParsing |=1826 ProvidePositionalOption(ConsumeAfterOpt, PositionalVals[ValNo].first,1827 PositionalVals[ValNo].second);1828 }1829 1830 // Loop over args and make sure all required args are specified!1831 for (const auto &Opt : OptionsMap) {1832 switch (Opt.second->getNumOccurrencesFlag()) {1833 case Required:1834 case OneOrMore:1835 if (Opt.second->getNumOccurrences() == 0) {1836 Opt.second->error("must be specified at least once!");1837 ErrorParsing = true;1838 }1839 [[fallthrough]];1840 default:1841 break;1842 }1843 }1844 1845 // Now that we know if -debug is specified, we can use it.1846 // Note that if ReadResponseFiles == true, this must be done before the1847 // memory allocated for the expanded command line is free()d below.1848 LLVM_DEBUG(dbgs() << "Args: ";1849 for (int i = 0; i < argc; ++i) dbgs() << argv[i] << ' ';1850 dbgs() << '\n';);1851 1852 // Free all of the memory allocated to the map. Command line options may only1853 // be processed once!1854 MoreHelp.clear();1855 1856 // If we had an error processing our arguments, don't let the program execute1857 if (ErrorParsing) {1858 if (!IgnoreErrors)1859 exit(1);1860 return false;1861 }1862 return true;1863}1864 1865//===----------------------------------------------------------------------===//1866// Option Base class implementation1867//1868 1869bool Option::error(const Twine &Message, StringRef ArgName, raw_ostream &Errs) {1870 if (!ArgName.data())1871 ArgName = ArgStr;1872 if (ArgName.empty())1873 Errs << HelpStr; // Be nice for positional arguments1874 else1875 Errs << GlobalParser->ProgramName << ": for the " << PrintArg(ArgName, 0);1876 1877 Errs << " option: " << Message << "\n";1878 return true;1879}1880 1881bool Option::addOccurrence(unsigned pos, StringRef ArgName, StringRef Value,1882 bool MultiArg) {1883 if (!MultiArg)1884 NumOccurrences++; // Increment the number of times we have been seen1885 1886 return handleOccurrence(pos, ArgName, Value);1887}1888 1889// getValueStr - Get the value description string, using "DefaultMsg" if nothing1890// has been specified yet.1891//1892static StringRef getValueStr(const Option &O, StringRef DefaultMsg) {1893 if (O.ValueStr.empty())1894 return DefaultMsg;1895 return O.ValueStr;1896}1897 1898//===----------------------------------------------------------------------===//1899// cl::alias class implementation1900//1901 1902// Return the width of the option tag for printing...1903size_t alias::getOptionWidth() const {1904 return argPlusPrefixesSize(ArgStr);1905}1906 1907void Option::printHelpStr(StringRef HelpStr, size_t Indent,1908 size_t FirstLineIndentedBy) {1909 assert(Indent >= FirstLineIndentedBy);1910 std::pair<StringRef, StringRef> Split = HelpStr.split('\n');1911 outs().indent(Indent - FirstLineIndentedBy)1912 << ArgHelpPrefix << Split.first << "\n";1913 while (!Split.second.empty()) {1914 Split = Split.second.split('\n');1915 outs().indent(Indent) << Split.first << "\n";1916 }1917}1918 1919void Option::printEnumValHelpStr(StringRef HelpStr, size_t BaseIndent,1920 size_t FirstLineIndentedBy) {1921 const StringRef ValHelpPrefix = " ";1922 assert(BaseIndent >= FirstLineIndentedBy);1923 std::pair<StringRef, StringRef> Split = HelpStr.split('\n');1924 outs().indent(BaseIndent - FirstLineIndentedBy)1925 << ArgHelpPrefix << ValHelpPrefix << Split.first << "\n";1926 while (!Split.second.empty()) {1927 Split = Split.second.split('\n');1928 outs().indent(BaseIndent + ValHelpPrefix.size()) << Split.first << "\n";1929 }1930}1931 1932// Print out the option for the alias.1933void alias::printOptionInfo(size_t GlobalWidth) const {1934 outs() << PrintArg(ArgStr);1935 printHelpStr(HelpStr, GlobalWidth, argPlusPrefixesSize(ArgStr));1936}1937 1938//===----------------------------------------------------------------------===//1939// Parser Implementation code...1940//1941 1942// basic_parser implementation1943//1944 1945// Return the width of the option tag for printing...1946size_t basic_parser_impl::getOptionWidth(const Option &O) const {1947 size_t Len = argPlusPrefixesSize(O.ArgStr);1948 auto ValName = getValueName();1949 if (!ValName.empty()) {1950 size_t FormattingLen = 3;1951 if (O.getMiscFlags() & PositionalEatsArgs)1952 FormattingLen = 6;1953 Len += getValueStr(O, ValName).size() + FormattingLen;1954 }1955 1956 return Len;1957}1958 1959// printOptionInfo - Print out information about this option. The1960// to-be-maintained width is specified.1961//1962void basic_parser_impl::printOptionInfo(const Option &O,1963 size_t GlobalWidth) const {1964 outs() << PrintArg(O.ArgStr);1965 1966 auto ValName = getValueName();1967 if (!ValName.empty()) {1968 if (O.getMiscFlags() & PositionalEatsArgs) {1969 outs() << " <" << getValueStr(O, ValName) << ">...";1970 } else if (O.getValueExpectedFlag() == ValueOptional)1971 outs() << "[=<" << getValueStr(O, ValName) << ">]";1972 else {1973 outs() << (O.ArgStr.size() == 1 ? " <" : "=<") << getValueStr(O, ValName)1974 << '>';1975 }1976 }1977 1978 Option::printHelpStr(O.HelpStr, GlobalWidth, getOptionWidth(O));1979}1980 1981void basic_parser_impl::printOptionName(const Option &O,1982 size_t GlobalWidth) const {1983 outs() << PrintArg(O.ArgStr);1984 outs().indent(GlobalWidth - O.ArgStr.size());1985}1986 1987// parser<bool> implementation1988//1989bool parser<bool>::parse(Option &O, StringRef ArgName, StringRef Arg,1990 bool &Value) {1991 return parseBool<bool, true, false>(O, ArgName, Arg, Value);1992}1993 1994// parser<boolOrDefault> implementation1995//1996bool parser<boolOrDefault>::parse(Option &O, StringRef ArgName, StringRef Arg,1997 boolOrDefault &Value) {1998 return parseBool<boolOrDefault, BOU_TRUE, BOU_FALSE>(O, ArgName, Arg, Value);1999}2000 2001// parser<int> implementation2002//2003bool parser<int>::parse(Option &O, StringRef ArgName, StringRef Arg,2004 int &Value) {2005 if (Arg.getAsInteger(0, Value))2006 return O.error("'" + Arg + "' value invalid for integer argument!");2007 return false;2008}2009 2010// parser<long> implementation2011//2012bool parser<long>::parse(Option &O, StringRef ArgName, StringRef Arg,2013 long &Value) {2014 if (Arg.getAsInteger(0, Value))2015 return O.error("'" + Arg + "' value invalid for long argument!");2016 return false;2017}2018 2019// parser<long long> implementation2020//2021bool parser<long long>::parse(Option &O, StringRef ArgName, StringRef Arg,2022 long long &Value) {2023 if (Arg.getAsInteger(0, Value))2024 return O.error("'" + Arg + "' value invalid for llong argument!");2025 return false;2026}2027 2028// parser<unsigned> implementation2029//2030bool parser<unsigned>::parse(Option &O, StringRef ArgName, StringRef Arg,2031 unsigned &Value) {2032 2033 if (Arg.getAsInteger(0, Value))2034 return O.error("'" + Arg + "' value invalid for uint argument!");2035 return false;2036}2037 2038// parser<unsigned long> implementation2039//2040bool parser<unsigned long>::parse(Option &O, StringRef ArgName, StringRef Arg,2041 unsigned long &Value) {2042 2043 if (Arg.getAsInteger(0, Value))2044 return O.error("'" + Arg + "' value invalid for ulong argument!");2045 return false;2046}2047 2048// parser<unsigned long long> implementation2049//2050bool parser<unsigned long long>::parse(Option &O, StringRef ArgName,2051 StringRef Arg,2052 unsigned long long &Value) {2053 2054 if (Arg.getAsInteger(0, Value))2055 return O.error("'" + Arg + "' value invalid for ullong argument!");2056 return false;2057}2058 2059// parser<double>/parser<float> implementation2060//2061static bool parseDouble(Option &O, StringRef Arg, double &Value) {2062 if (to_float(Arg, Value))2063 return false;2064 return O.error("'" + Arg + "' value invalid for floating point argument!");2065}2066 2067bool parser<double>::parse(Option &O, StringRef ArgName, StringRef Arg,2068 double &Val) {2069 return parseDouble(O, Arg, Val);2070}2071 2072bool parser<float>::parse(Option &O, StringRef ArgName, StringRef Arg,2073 float &Val) {2074 double dVal;2075 if (parseDouble(O, Arg, dVal))2076 return true;2077 Val = (float)dVal;2078 return false;2079}2080 2081// generic_parser_base implementation2082//2083 2084// findOption - Return the option number corresponding to the specified2085// argument string. If the option is not found, getNumOptions() is returned.2086//2087unsigned generic_parser_base::findOption(StringRef Name) {2088 unsigned e = getNumOptions();2089 2090 for (unsigned i = 0; i != e; ++i) {2091 if (getOption(i) == Name)2092 return i;2093 }2094 return e;2095}2096 2097static StringRef EqValue = "=<value>";2098static StringRef EmptyOption = "<empty>";2099static StringRef OptionPrefix = " =";2100static size_t getOptionPrefixesSize() {2101 return OptionPrefix.size() + ArgHelpPrefix.size();2102}2103 2104static bool shouldPrintOption(StringRef Name, StringRef Description,2105 const Option &O) {2106 return O.getValueExpectedFlag() != ValueOptional || !Name.empty() ||2107 !Description.empty();2108}2109 2110// Return the width of the option tag for printing...2111size_t generic_parser_base::getOptionWidth(const Option &O) const {2112 if (O.hasArgStr()) {2113 size_t Size =2114 argPlusPrefixesSize(O.ArgStr) + EqValue.size();2115 for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {2116 StringRef Name = getOption(i);2117 if (!shouldPrintOption(Name, getDescription(i), O))2118 continue;2119 size_t NameSize = Name.empty() ? EmptyOption.size() : Name.size();2120 Size = std::max(Size, NameSize + getOptionPrefixesSize());2121 }2122 return Size;2123 } else {2124 size_t BaseSize = 0;2125 for (unsigned i = 0, e = getNumOptions(); i != e; ++i)2126 BaseSize = std::max(BaseSize, getOption(i).size() + 8);2127 return BaseSize;2128 }2129}2130 2131// printOptionInfo - Print out information about this option. The2132// to-be-maintained width is specified.2133//2134void generic_parser_base::printOptionInfo(const Option &O,2135 size_t GlobalWidth) const {2136 if (O.hasArgStr()) {2137 // When the value is optional, first print a line just describing the2138 // option without values.2139 if (O.getValueExpectedFlag() == ValueOptional) {2140 for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {2141 if (getOption(i).empty()) {2142 outs() << PrintArg(O.ArgStr);2143 Option::printHelpStr(O.HelpStr, GlobalWidth,2144 argPlusPrefixesSize(O.ArgStr));2145 break;2146 }2147 }2148 }2149 2150 outs() << PrintArg(O.ArgStr) << EqValue;2151 Option::printHelpStr(O.HelpStr, GlobalWidth,2152 EqValue.size() +2153 argPlusPrefixesSize(O.ArgStr));2154 for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {2155 StringRef OptionName = getOption(i);2156 StringRef Description = getDescription(i);2157 if (!shouldPrintOption(OptionName, Description, O))2158 continue;2159 size_t FirstLineIndent = OptionName.size() + getOptionPrefixesSize();2160 outs() << OptionPrefix << OptionName;2161 if (OptionName.empty()) {2162 outs() << EmptyOption;2163 assert(FirstLineIndent >= EmptyOption.size());2164 FirstLineIndent += EmptyOption.size();2165 }2166 if (!Description.empty())2167 Option::printEnumValHelpStr(Description, GlobalWidth, FirstLineIndent);2168 else2169 outs() << '\n';2170 }2171 } else {2172 if (!O.HelpStr.empty())2173 outs() << " " << O.HelpStr << '\n';2174 for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {2175 StringRef Option = getOption(i);2176 outs() << " " << PrintArg(Option);2177 Option::printHelpStr(getDescription(i), GlobalWidth, Option.size() + 8);2178 }2179 }2180}2181 2182static const size_t MaxOptWidth = 8; // arbitrary spacing for printOptionDiff2183 2184// printGenericOptionDiff - Print the value of this option and it's default.2185//2186// "Generic" options have each value mapped to a name.2187void generic_parser_base::printGenericOptionDiff(2188 const Option &O, const GenericOptionValue &Value,2189 const GenericOptionValue &Default, size_t GlobalWidth) const {2190 outs() << " " << PrintArg(O.ArgStr);2191 outs().indent(GlobalWidth - O.ArgStr.size());2192 2193 unsigned NumOpts = getNumOptions();2194 for (unsigned i = 0; i != NumOpts; ++i) {2195 if (!Value.compare(getOptionValue(i)))2196 continue;2197 2198 outs() << "= " << getOption(i);2199 size_t L = getOption(i).size();2200 size_t NumSpaces = MaxOptWidth > L ? MaxOptWidth - L : 0;2201 outs().indent(NumSpaces) << " (default: ";2202 for (unsigned j = 0; j != NumOpts; ++j) {2203 if (!Default.compare(getOptionValue(j)))2204 continue;2205 outs() << getOption(j);2206 break;2207 }2208 outs() << ")\n";2209 return;2210 }2211 outs() << "= *unknown option value*\n";2212}2213 2214// printOptionDiff - Specializations for printing basic value types.2215//2216#define PRINT_OPT_DIFF(T) \2217 void parser<T>::printOptionDiff(const Option &O, T V, OptionValue<T> D, \2218 size_t GlobalWidth) const { \2219 printOptionName(O, GlobalWidth); \2220 std::string Str; \2221 { \2222 raw_string_ostream SS(Str); \2223 SS << V; \2224 } \2225 outs() << "= " << Str; \2226 size_t NumSpaces = \2227 MaxOptWidth > Str.size() ? MaxOptWidth - Str.size() : 0; \2228 outs().indent(NumSpaces) << " (default: "; \2229 if (D.hasValue()) \2230 outs() << D.getValue(); \2231 else \2232 outs() << "*no default*"; \2233 outs() << ")\n"; \2234 }2235 2236PRINT_OPT_DIFF(bool)2237PRINT_OPT_DIFF(boolOrDefault)2238PRINT_OPT_DIFF(int)2239PRINT_OPT_DIFF(long)2240PRINT_OPT_DIFF(long long)2241PRINT_OPT_DIFF(unsigned)2242PRINT_OPT_DIFF(unsigned long)2243PRINT_OPT_DIFF(unsigned long long)2244PRINT_OPT_DIFF(double)2245PRINT_OPT_DIFF(float)2246PRINT_OPT_DIFF(char)2247 2248void parser<std::string>::printOptionDiff(const Option &O, StringRef V,2249 const OptionValue<std::string> &D,2250 size_t GlobalWidth) const {2251 printOptionName(O, GlobalWidth);2252 outs() << "= " << V;2253 size_t NumSpaces = MaxOptWidth > V.size() ? MaxOptWidth - V.size() : 0;2254 outs().indent(NumSpaces) << " (default: ";2255 if (D.hasValue())2256 outs() << D.getValue();2257 else2258 outs() << "*no default*";2259 outs() << ")\n";2260}2261 2262void parser<std::optional<std::string>>::printOptionDiff(2263 const Option &O, std::optional<StringRef> V,2264 const OptionValue<std::optional<std::string>> &D,2265 size_t GlobalWidth) const {2266 printOptionName(O, GlobalWidth);2267 outs() << "= " << V;2268 size_t VSize = V.has_value() ? V.value().size() : 0;2269 size_t NumSpaces = MaxOptWidth > VSize ? MaxOptWidth - VSize : 0;2270 outs().indent(NumSpaces) << " (default: ";2271 if (D.hasValue() && D.getValue().has_value())2272 outs() << D.getValue();2273 else2274 outs() << "*no value*";2275 outs() << ")\n";2276}2277 2278// Print a placeholder for options that don't yet support printOptionDiff().2279void basic_parser_impl::printOptionNoValue(const Option &O,2280 size_t GlobalWidth) const {2281 printOptionName(O, GlobalWidth);2282 outs() << "= *cannot print option value*\n";2283}2284 2285//===----------------------------------------------------------------------===//2286// -help and -help-hidden option implementation2287//2288 2289static int OptNameCompare(const std::pair<const char *, Option *> *LHS,2290 const std::pair<const char *, Option *> *RHS) {2291 return strcmp(LHS->first, RHS->first);2292}2293 2294static int SubNameCompare(const std::pair<const char *, SubCommand *> *LHS,2295 const std::pair<const char *, SubCommand *> *RHS) {2296 return strcmp(LHS->first, RHS->first);2297}2298 2299// Copy Options into a vector so we can sort them as we like.2300static void sortOpts(StringMap<Option *> &OptMap,2301 SmallVectorImpl<std::pair<const char *, Option *>> &Opts,2302 bool ShowHidden) {2303 SmallPtrSet<Option *, 32> OptionSet; // Duplicate option detection.2304 2305 for (StringMap<Option *>::iterator I = OptMap.begin(), E = OptMap.end();2306 I != E; ++I) {2307 // Ignore really-hidden options.2308 if (I->second->getOptionHiddenFlag() == ReallyHidden)2309 continue;2310 2311 // Unless showhidden is set, ignore hidden flags.2312 if (I->second->getOptionHiddenFlag() == Hidden && !ShowHidden)2313 continue;2314 2315 // If we've already seen this option, don't add it to the list again.2316 if (!OptionSet.insert(I->second).second)2317 continue;2318 2319 Opts.push_back(2320 std::pair<const char *, Option *>(I->getKey().data(), I->second));2321 }2322 2323 // Sort the options list alphabetically.2324 array_pod_sort(Opts.begin(), Opts.end(), OptNameCompare);2325}2326 2327static void2328sortSubCommands(const SmallPtrSetImpl<SubCommand *> &SubMap,2329 SmallVectorImpl<std::pair<const char *, SubCommand *>> &Subs) {2330 for (auto *S : SubMap) {2331 if (S->getName().empty())2332 continue;2333 Subs.push_back(std::make_pair(S->getName().data(), S));2334 }2335 array_pod_sort(Subs.begin(), Subs.end(), SubNameCompare);2336}2337 2338namespace {2339 2340class HelpPrinter {2341protected:2342 const bool ShowHidden;2343 using StrOptionPairVector =2344 SmallVector<std::pair<const char *, Option *>, 128>;2345 using StrSubCommandPairVector =2346 SmallVector<std::pair<const char *, SubCommand *>, 128>;2347 // Print the options. Opts is assumed to be alphabetically sorted.2348 virtual void printOptions(StrOptionPairVector &Opts, size_t MaxArgLen) {2349 for (const auto &Opt : Opts)2350 Opt.second->printOptionInfo(MaxArgLen);2351 }2352 2353 void printSubCommands(StrSubCommandPairVector &Subs, size_t MaxSubLen) {2354 for (const auto &S : Subs) {2355 outs() << " " << S.first;2356 if (!S.second->getDescription().empty()) {2357 outs().indent(MaxSubLen - strlen(S.first));2358 outs() << " - " << S.second->getDescription();2359 }2360 outs() << "\n";2361 }2362 }2363 2364public:2365 explicit HelpPrinter(bool showHidden) : ShowHidden(showHidden) {}2366 virtual ~HelpPrinter() = default;2367 2368 // Invoke the printer.2369 void operator=(bool Value) {2370 if (!Value)2371 return;2372 printHelp();2373 2374 // Halt the program since help information was printed2375 exit(0);2376 }2377 2378 void printHelp() {2379 SubCommand *Sub = GlobalParser->getActiveSubCommand();2380 auto &OptionsMap = Sub->OptionsMap;2381 auto &PositionalOpts = Sub->PositionalOpts;2382 auto &ConsumeAfterOpt = Sub->ConsumeAfterOpt;2383 2384 StrOptionPairVector Opts;2385 sortOpts(OptionsMap, Opts, ShowHidden);2386 2387 StrSubCommandPairVector Subs;2388 sortSubCommands(GlobalParser->RegisteredSubCommands, Subs);2389 2390 if (!GlobalParser->ProgramOverview.empty())2391 outs() << "OVERVIEW: " << GlobalParser->ProgramOverview << "\n";2392 2393 if (Sub == &SubCommand::getTopLevel()) {2394 outs() << "USAGE: " << GlobalParser->ProgramName;2395 if (!Subs.empty())2396 outs() << " [subcommand]";2397 outs() << " [options]";2398 } else {2399 if (!Sub->getDescription().empty()) {2400 outs() << "SUBCOMMAND '" << Sub->getName()2401 << "': " << Sub->getDescription() << "\n\n";2402 }2403 outs() << "USAGE: " << GlobalParser->ProgramName << " " << Sub->getName()2404 << " [options]";2405 }2406 2407 for (auto *Opt : PositionalOpts) {2408 if (Opt->hasArgStr())2409 outs() << " --" << Opt->ArgStr;2410 outs() << " " << Opt->HelpStr;2411 }2412 2413 // Print the consume after option info if it exists...2414 if (ConsumeAfterOpt)2415 outs() << " " << ConsumeAfterOpt->HelpStr;2416 2417 if (Sub == &SubCommand::getTopLevel() && !Subs.empty()) {2418 // Compute the maximum subcommand length...2419 size_t MaxSubLen = 0;2420 for (const auto &Sub : Subs)2421 MaxSubLen = std::max(MaxSubLen, strlen(Sub.first));2422 2423 outs() << "\n\n";2424 outs() << "SUBCOMMANDS:\n\n";2425 printSubCommands(Subs, MaxSubLen);2426 outs() << "\n";2427 outs() << " Type \"" << GlobalParser->ProgramName2428 << " <subcommand> --help\" to get more help on a specific "2429 "subcommand";2430 }2431 2432 outs() << "\n\n";2433 2434 // Compute the maximum argument length...2435 size_t MaxArgLen = 0;2436 for (const auto &Opt : Opts)2437 MaxArgLen = std::max(MaxArgLen, Opt.second->getOptionWidth());2438 2439 outs() << "OPTIONS:\n";2440 printOptions(Opts, MaxArgLen);2441 2442 // Print any extra help the user has declared.2443 for (const auto &I : GlobalParser->MoreHelp)2444 outs() << I;2445 GlobalParser->MoreHelp.clear();2446 }2447};2448 2449class CategorizedHelpPrinter : public HelpPrinter {2450public:2451 explicit CategorizedHelpPrinter(bool showHidden) : HelpPrinter(showHidden) {}2452 2453 // Helper function for printOptions().2454 // It shall return a negative value if A's name should be lexicographically2455 // ordered before B's name. It returns a value greater than zero if B's name2456 // should be ordered before A's name, and it returns 0 otherwise.2457 static int OptionCategoryCompare(OptionCategory *const *A,2458 OptionCategory *const *B) {2459 return (*A)->getName().compare((*B)->getName());2460 }2461 2462 // Make sure we inherit our base class's operator=()2463 using HelpPrinter::operator=;2464 2465protected:2466 void printOptions(StrOptionPairVector &Opts, size_t MaxArgLen) override {2467 std::vector<OptionCategory *> SortedCategories;2468 DenseMap<OptionCategory *, std::vector<Option *>> CategorizedOptions;2469 2470 // Collect registered option categories into vector in preparation for2471 // sorting.2472 llvm::append_range(SortedCategories,2473 GlobalParser->RegisteredOptionCategories);2474 2475 // Sort the different option categories alphabetically.2476 assert(SortedCategories.size() > 0 && "No option categories registered!");2477 array_pod_sort(SortedCategories.begin(), SortedCategories.end(),2478 OptionCategoryCompare);2479 2480 // Walk through pre-sorted options and assign into categories.2481 // Because the options are already alphabetically sorted the2482 // options within categories will also be alphabetically sorted.2483 for (const auto &I : Opts) {2484 Option *Opt = I.second;2485 for (OptionCategory *Cat : Opt->Categories) {2486 assert(llvm::is_contained(SortedCategories, Cat) &&2487 "Option has an unregistered category");2488 CategorizedOptions[Cat].push_back(Opt);2489 }2490 }2491 2492 // Now do printing.2493 for (OptionCategory *Category : SortedCategories) {2494 // Hide empty categories for --help, but show for --help-hidden.2495 const auto &CategoryOptions = CategorizedOptions[Category];2496 if (CategoryOptions.empty())2497 continue;2498 2499 // Print category information.2500 outs() << "\n";2501 outs() << Category->getName() << ":\n";2502 2503 // Check if description is set.2504 if (!Category->getDescription().empty())2505 outs() << Category->getDescription() << "\n\n";2506 else2507 outs() << "\n";2508 2509 // Loop over the options in the category and print.2510 for (const Option *Opt : CategoryOptions)2511 Opt->printOptionInfo(MaxArgLen);2512 }2513 }2514};2515 2516// This wraps the Uncategorizing and Categorizing printers and decides2517// at run time which should be invoked.2518class HelpPrinterWrapper {2519private:2520 HelpPrinter &UncategorizedPrinter;2521 CategorizedHelpPrinter &CategorizedPrinter;2522 2523public:2524 explicit HelpPrinterWrapper(HelpPrinter &UncategorizedPrinter,2525 CategorizedHelpPrinter &CategorizedPrinter)2526 : UncategorizedPrinter(UncategorizedPrinter),2527 CategorizedPrinter(CategorizedPrinter) {}2528 2529 // Invoke the printer.2530 void operator=(bool Value);2531};2532 2533} // End anonymous namespace2534 2535#if defined(__GNUC__)2536// GCC and GCC-compatible compilers define __OPTIMIZE__ when optimizations are2537// enabled.2538# if defined(__OPTIMIZE__)2539# define LLVM_IS_DEBUG_BUILD 02540# else2541# define LLVM_IS_DEBUG_BUILD 12542# endif2543#elif defined(_MSC_VER)2544// MSVC doesn't have a predefined macro indicating if optimizations are enabled.2545// Use _DEBUG instead. This macro actually corresponds to the choice between2546// debug and release CRTs, but it is a reasonable proxy.2547# if defined(_DEBUG)2548# define LLVM_IS_DEBUG_BUILD 12549# else2550# define LLVM_IS_DEBUG_BUILD 02551# endif2552#else2553// Otherwise, for an unknown compiler, assume this is an optimized build.2554# define LLVM_IS_DEBUG_BUILD 02555#endif2556 2557namespace {2558class VersionPrinter {2559public:2560 void print(std::vector<VersionPrinterTy> ExtraPrinters = {}) {2561 raw_ostream &OS = outs();2562#ifdef PACKAGE_VENDOR2563 OS << PACKAGE_VENDOR << " ";2564#else2565 OS << "LLVM (http://llvm.org/):\n ";2566#endif2567 OS << PACKAGE_NAME << " version " << PACKAGE_VERSION << "\n ";2568#if LLVM_IS_DEBUG_BUILD2569 OS << "DEBUG build";2570#else2571 OS << "Optimized build";2572#endif2573#ifndef NDEBUG2574 OS << " with assertions";2575#endif2576 OS << ".\n";2577 2578 // Iterate over any registered extra printers and call them to add further2579 // information.2580 if (!ExtraPrinters.empty()) {2581 for (const auto &I : ExtraPrinters)2582 I(outs());2583 }2584 }2585 void operator=(bool OptionWasSpecified);2586};2587 2588struct CommandLineCommonOptions {2589 // Declare the four HelpPrinter instances that are used to print out help, or2590 // help-hidden as an uncategorized list or in categories.2591 HelpPrinter UncategorizedNormalPrinter{false};2592 HelpPrinter UncategorizedHiddenPrinter{true};2593 CategorizedHelpPrinter CategorizedNormalPrinter{false};2594 CategorizedHelpPrinter CategorizedHiddenPrinter{true};2595 // Declare HelpPrinter wrappers that will decide whether or not to invoke2596 // a categorizing help printer2597 HelpPrinterWrapper WrappedNormalPrinter{UncategorizedNormalPrinter,2598 CategorizedNormalPrinter};2599 HelpPrinterWrapper WrappedHiddenPrinter{UncategorizedHiddenPrinter,2600 CategorizedHiddenPrinter};2601 // Define a category for generic options that all tools should have.2602 cl::OptionCategory GenericCategory{"Generic Options"};2603 2604 // Define uncategorized help printers.2605 // --help-list is hidden by default because if Option categories are being2606 // used then --help behaves the same as --help-list.2607 cl::opt<HelpPrinter, true, parser<bool>> HLOp{2608 "help-list",2609 cl::desc(2610 "Display list of available options (--help-list-hidden for more)"),2611 cl::location(UncategorizedNormalPrinter),2612 cl::Hidden,2613 cl::ValueDisallowed,2614 cl::cat(GenericCategory),2615 cl::sub(SubCommand::getAll())};2616 2617 cl::opt<HelpPrinter, true, parser<bool>> HLHOp{2618 "help-list-hidden",2619 cl::desc("Display list of all available options"),2620 cl::location(UncategorizedHiddenPrinter),2621 cl::Hidden,2622 cl::ValueDisallowed,2623 cl::cat(GenericCategory),2624 cl::sub(SubCommand::getAll())};2625 2626 // Define uncategorized/categorized help printers. These printers change their2627 // behaviour at runtime depending on whether one or more Option categories2628 // have been declared.2629 cl::opt<HelpPrinterWrapper, true, parser<bool>> HOp{2630 "help",2631 cl::desc("Display available options (--help-hidden for more)"),2632 cl::location(WrappedNormalPrinter),2633 cl::ValueDisallowed,2634 cl::cat(GenericCategory),2635 cl::sub(SubCommand::getAll())};2636 2637 cl::alias HOpA{"h", cl::desc("Alias for --help"), cl::aliasopt(HOp),2638 cl::DefaultOption};2639 2640 cl::opt<HelpPrinterWrapper, true, parser<bool>> HHOp{2641 "help-hidden",2642 cl::desc("Display all available options"),2643 cl::location(WrappedHiddenPrinter),2644 cl::Hidden,2645 cl::ValueDisallowed,2646 cl::cat(GenericCategory),2647 cl::sub(SubCommand::getAll())};2648 2649 cl::opt<bool> PrintOptions{2650 "print-options",2651 cl::desc("Print non-default options after command line parsing"),2652 cl::Hidden,2653 cl::init(false),2654 cl::cat(GenericCategory),2655 cl::sub(SubCommand::getAll())};2656 2657 cl::opt<bool> PrintAllOptions{2658 "print-all-options",2659 cl::desc("Print all option values after command line parsing"),2660 cl::Hidden,2661 cl::init(false),2662 cl::cat(GenericCategory),2663 cl::sub(SubCommand::getAll())};2664 2665 VersionPrinterTy OverrideVersionPrinter = nullptr;2666 2667 std::vector<VersionPrinterTy> ExtraVersionPrinters;2668 2669 // Define the --version option that prints out the LLVM version for the tool2670 VersionPrinter VersionPrinterInstance;2671 2672 cl::opt<VersionPrinter, true, parser<bool>> VersOp{2673 "version", cl::desc("Display the version of this program"),2674 cl::location(VersionPrinterInstance), cl::ValueDisallowed,2675 cl::cat(GenericCategory)};2676};2677} // End anonymous namespace2678 2679// Lazy-initialized global instance of options controlling the command-line2680// parser and general handling.2681static ManagedStatic<CommandLineCommonOptions> CommonOptions;2682 2683static void initCommonOptions() {2684 *CommonOptions;2685 initDebugCounterOptions();2686 initGraphWriterOptions();2687 initSignalsOptions();2688 initStatisticOptions();2689 initTimerOptions();2690 initWithColorOptions();2691 initDebugOptions();2692 initRandomSeedOptions();2693}2694 2695OptionCategory &cl::getGeneralCategory() {2696 // Initialise the general option category.2697 static OptionCategory GeneralCategory{"General options"};2698 return GeneralCategory;2699}2700 2701void VersionPrinter::operator=(bool OptionWasSpecified) {2702 if (!OptionWasSpecified)2703 return;2704 2705 if (CommonOptions->OverrideVersionPrinter != nullptr) {2706 CommonOptions->OverrideVersionPrinter(outs());2707 exit(0);2708 }2709 print(CommonOptions->ExtraVersionPrinters);2710 2711 exit(0);2712}2713 2714void HelpPrinterWrapper::operator=(bool Value) {2715 if (!Value)2716 return;2717 2718 // Decide which printer to invoke. If more than one option category is2719 // registered then it is useful to show the categorized help instead of2720 // uncategorized help.2721 if (GlobalParser->RegisteredOptionCategories.size() > 1) {2722 // unhide --help-list option so user can have uncategorized output if they2723 // want it.2724 CommonOptions->HLOp.setHiddenFlag(NotHidden);2725 2726 CategorizedPrinter = true; // Invoke categorized printer2727 } else {2728 UncategorizedPrinter = true; // Invoke uncategorized printer2729 }2730}2731 2732// Print the value of each option.2733void cl::PrintOptionValues() { GlobalParser->printOptionValues(); }2734 2735void CommandLineParser::printOptionValues() {2736 if (!CommonOptions->PrintOptions && !CommonOptions->PrintAllOptions)2737 return;2738 2739 SmallVector<std::pair<const char *, Option *>, 128> Opts;2740 sortOpts(ActiveSubCommand->OptionsMap, Opts, /*ShowHidden*/ true);2741 2742 // Compute the maximum argument length...2743 size_t MaxArgLen = 0;2744 for (const auto &Opt : Opts)2745 MaxArgLen = std::max(MaxArgLen, Opt.second->getOptionWidth());2746 2747 for (const auto &Opt : Opts)2748 Opt.second->printOptionValue(MaxArgLen, CommonOptions->PrintAllOptions);2749}2750 2751// Utility function for printing the help message.2752void cl::PrintHelpMessage(bool Hidden, bool Categorized) {2753 if (!Hidden && !Categorized)2754 CommonOptions->UncategorizedNormalPrinter.printHelp();2755 else if (!Hidden && Categorized)2756 CommonOptions->CategorizedNormalPrinter.printHelp();2757 else if (Hidden && !Categorized)2758 CommonOptions->UncategorizedHiddenPrinter.printHelp();2759 else2760 CommonOptions->CategorizedHiddenPrinter.printHelp();2761}2762 2763ArrayRef<StringRef> cl::getCompilerBuildConfig() {2764 static const StringRef Config[] = {2765 // Placeholder to ensure the array always has elements, since it's an2766 // error to have a zero-sized array. Slice this off before returning.2767 "",2768 // Actual compiler build config feature list:2769#if LLVM_IS_DEBUG_BUILD2770 "+unoptimized",2771#endif2772#ifndef NDEBUG2773 "+assertions",2774#endif2775#ifdef EXPENSIVE_CHECKS2776 "+expensive-checks",2777#endif2778#if __has_feature(address_sanitizer)2779 "+asan",2780#endif2781#if __has_feature(dataflow_sanitizer)2782 "+dfsan",2783#endif2784#if __has_feature(hwaddress_sanitizer)2785 "+hwasan",2786#endif2787#if __has_feature(memory_sanitizer)2788 "+msan",2789#endif2790#if __has_feature(thread_sanitizer)2791 "+tsan",2792#endif2793#if __has_feature(undefined_behavior_sanitizer)2794 "+ubsan",2795#endif2796 };2797 return ArrayRef(Config).drop_front(1);2798}2799 2800// Utility function for printing the build config.2801void cl::printBuildConfig(raw_ostream &OS) {2802#if LLVM_VERSION_PRINTER_SHOW_BUILD_CONFIG2803 OS << "Build config: ";2804 llvm::interleaveComma(cl::getCompilerBuildConfig(), OS);2805 OS << '\n';2806#endif2807}2808 2809/// Utility function for printing version number.2810void cl::PrintVersionMessage() {2811 CommonOptions->VersionPrinterInstance.print(CommonOptions->ExtraVersionPrinters);2812}2813 2814void cl::SetVersionPrinter(VersionPrinterTy func) {2815 CommonOptions->OverrideVersionPrinter = func;2816}2817 2818void cl::AddExtraVersionPrinter(VersionPrinterTy func) {2819 CommonOptions->ExtraVersionPrinters.push_back(func);2820}2821 2822StringMap<Option *> &cl::getRegisteredOptions(SubCommand &Sub) {2823 initCommonOptions();2824 auto &Subs = GlobalParser->RegisteredSubCommands;2825 (void)Subs;2826 assert(Subs.contains(&Sub));2827 return Sub.OptionsMap;2828}2829 2830iterator_range<SmallPtrSet<SubCommand *, 4>::iterator>2831cl::getRegisteredSubcommands() {2832 return GlobalParser->getRegisteredSubcommands();2833}2834 2835void cl::HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub) {2836 initCommonOptions();2837 for (auto &I : Sub.OptionsMap) {2838 bool Unrelated = true;2839 for (auto &Cat : I.second->Categories) {2840 if (Cat == &Category || Cat == &CommonOptions->GenericCategory)2841 Unrelated = false;2842 }2843 if (Unrelated)2844 I.second->setHiddenFlag(cl::ReallyHidden);2845 }2846}2847 2848void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories,2849 SubCommand &Sub) {2850 initCommonOptions();2851 for (auto &I : Sub.OptionsMap) {2852 bool Unrelated = true;2853 for (auto &Cat : I.second->Categories) {2854 if (is_contained(Categories, Cat) ||2855 Cat == &CommonOptions->GenericCategory)2856 Unrelated = false;2857 }2858 if (Unrelated)2859 I.second->setHiddenFlag(cl::ReallyHidden);2860 }2861}2862 2863void cl::ResetCommandLineParser() { GlobalParser->reset(); }2864void cl::ResetAllOptionOccurrences() {2865 GlobalParser->ResetAllOptionOccurrences();2866}2867 2868void LLVMParseCommandLineOptions(int argc, const char *const *argv,2869 const char *Overview) {2870 llvm::cl::ParseCommandLineOptions(argc, argv, StringRef(Overview),2871 &llvm::nulls());2872}2873