diff options
author | dim <dim@FreeBSD.org> | 2016-12-26 20:36:37 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2016-12-26 20:36:37 +0000 |
commit | 06210ae42d418d50d8d9365d5c9419308ae9e7ee (patch) | |
tree | ab60b4cdd6e430dda1f292a46a77ddb744723f31 /contrib/llvm/lib/Support/CommandLine.cpp | |
parent | 2dd166267f53df1c3748b4325d294b9b839de74b (diff) | |
download | FreeBSD-src-06210ae42d418d50d8d9365d5c9419308ae9e7ee.zip FreeBSD-src-06210ae42d418d50d8d9365d5c9419308ae9e7ee.tar.gz |
MFC r309124:
Upgrade our copies of clang, llvm, lldb, compiler-rt and libc++ to 3.9.0
release, and add lld 3.9.0. Also completely revamp the build system for
clang, llvm, lldb and their related tools.
Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11
support to build; see UPDATING for more information.
Release notes for llvm, clang and lld are available here:
<http://llvm.org/releases/3.9.0/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.9.0/tools/clang/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.9.0/tools/lld/docs/ReleaseNotes.html>
Thanks to Ed Maste, Bryan Drewery, Andrew Turner, Antoine Brodin and Jan
Beich for their help.
Relnotes: yes
MFC r309147:
Pull in r282174 from upstream llvm trunk (by Krzysztof Parzyszek):
[PPC] Set SP after loading data from stack frame, if no red zone is
present
Follow-up to r280705: Make sure that the SP is only restored after
all data is loaded from the stack frame, if there is no red zone.
This completes the fix for
https://llvm.org/bugs/show_bug.cgi?id=26519.
Differential Revision: https://reviews.llvm.org/D24466
Reported by: Mark Millard
PR: 214433
MFC r309149:
Pull in r283060 from upstream llvm trunk (by Hal Finkel):
[PowerPC] Refactor soft-float support, and enable PPC64 soft float
This change enables soft-float for PowerPC64, and also makes
soft-float disable all vector instruction sets for both 32-bit and
64-bit modes. This latter part is necessary because the PPC backend
canonicalizes many Altivec vector types to floating-point types, and
so soft-float breaks scalarization support for many operations. Both
for embedded targets and for operating-system kernels desiring
soft-float support, it seems reasonable that disabling hardware
floating-point also disables vector instructions (embedded targets
without hardware floating point support are unlikely to have Altivec,
etc. and operating system kernels desiring not to use floating-point
registers to lower syscall cost are unlikely to want to use vector
registers either). If someone needs this to work, we'll need to
change the fact that we promote many Altivec operations to act on
v4f32. To make it possible to disable Altivec when soft-float is
enabled, hardware floating-point support needs to be expressed as a
positive feature, like the others, and not a negative feature,
because target features cannot have dependencies on the disabling of
some other feature. So +soft-float has now become -hard-float.
Fixes PR26970.
Pull in r283061 from upstream clang trunk (by Hal Finkel):
[PowerPC] Enable soft-float for PPC64, and +soft-float -> -hard-float
Enable soft-float support on PPC64, as the backend now supports it.
Also, the backend now uses -hard-float instead of +soft-float, so set
the target features accordingly.
Fixes PR26970.
Reported by: Mark Millard
PR: 214433
MFC r309212:
Add a few missed clang 3.9.0 files to OptionalObsoleteFiles.
MFC r309262:
Fix packaging for clang, lldb and lld 3.9.0
During the upgrade of clang/llvm etc to 3.9.0 in r309124, the PACKAGE
directive in the usr.bin/clang/*.mk files got dropped accidentally.
Restore it, with a few minor changes and additions:
* Correct license in clang.ucl to NCSA
* Add PACKAGE=clang for clang and most of the "ll" tools
* Put lldb in its own package
* Put lld in its own package
Reviewed by: gjb, jmallett
Differential Revision: https://reviews.freebsd.org/D8666
MFC r309656:
During the bootstrap phase, when building the minimal llvm library on
PowerPC, add lib/Support/Atomic.cpp. This is needed because upstream
llvm revision r271821 disabled the use of std::call_once, which causes
some fallback functions from Atomic.cpp to be used instead.
Reported by: Mark Millard
PR: 214902
MFC r309835:
Tentatively apply https://reviews.llvm.org/D18730 to work around gcc PR
70528 (bogus error: constructor required before non-static data member).
This should fix buildworld with the external gcc package.
Reported by: https://jenkins.freebsd.org/job/FreeBSD_HEAD_amd64_gcc/
MFC r310194:
Upgrade our copies of clang, llvm, lld, lldb, compiler-rt and libc++ to
3.9.1 release.
Please note that from 3.5.0 onwards, clang, llvm and lldb require C++11
support to build; see UPDATING for more information.
Release notes for llvm, clang and lld will be available here:
<http://releases.llvm.org/3.9.1/docs/ReleaseNotes.html>
<http://releases.llvm.org/3.9.1/tools/clang/docs/ReleaseNotes.html>
<http://releases.llvm.org/3.9.1/tools/lld/docs/ReleaseNotes.html>
Relnotes: yes
Diffstat (limited to 'contrib/llvm/lib/Support/CommandLine.cpp')
-rw-r--r-- | contrib/llvm/lib/Support/CommandLine.cpp | 545 |
1 files changed, 422 insertions, 123 deletions
diff --git a/contrib/llvm/lib/Support/CommandLine.cpp b/contrib/llvm/lib/Support/CommandLine.cpp index fdcdb03..a5d2ba2 100644 --- a/contrib/llvm/lib/Support/CommandLine.cpp +++ b/contrib/llvm/lib/Support/CommandLine.cpp @@ -19,6 +19,7 @@ #include "llvm/Support/CommandLine.h" #include "llvm-c/Support.h" #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallString.h" @@ -94,35 +95,56 @@ public: // This collects additional help to be printed. std::vector<const char *> MoreHelp; - SmallVector<Option *, 4> PositionalOpts; - SmallVector<Option *, 4> SinkOpts; - StringMap<Option *> OptionsMap; - - Option *ConsumeAfterOpt; // The ConsumeAfter option if it exists. - // This collects the different option categories that have been registered. SmallPtrSet<OptionCategory *, 16> RegisteredOptionCategories; - CommandLineParser() : ProgramOverview(nullptr), ConsumeAfterOpt(nullptr) {} + // This collects the different subcommands that have been registered. + SmallPtrSet<SubCommand *, 4> RegisteredSubCommands; - void ParseCommandLineOptions(int argc, const char *const *argv, - const char *Overview); + CommandLineParser() : ProgramOverview(nullptr), ActiveSubCommand(nullptr) { + registerSubCommand(&*TopLevelSubCommand); + registerSubCommand(&*AllSubCommands); + } - void addLiteralOption(Option &Opt, const char *Name) { - if (!Opt.hasArgStr()) { - if (!OptionsMap.insert(std::make_pair(Name, &Opt)).second) { - errs() << ProgramName << ": CommandLine Error: Option '" << Name - << "' registered more than once!\n"; - report_fatal_error("inconsistency in registered CommandLine options"); + void ResetAllOptionOccurrences(); + + bool ParseCommandLineOptions(int argc, const char *const *argv, + const char *Overview, bool IgnoreErrors); + + void addLiteralOption(Option &Opt, SubCommand *SC, const char *Name) { + if (Opt.hasArgStr()) + return; + if (!SC->OptionsMap.insert(std::make_pair(Name, &Opt)).second) { + errs() << ProgramName << ": CommandLine Error: Option '" << Name + << "' registered more than once!\n"; + report_fatal_error("inconsistency in registered CommandLine options"); + } + + // If we're adding this to all sub-commands, add it to the ones that have + // already been registered. + if (SC == &*AllSubCommands) { + for (const auto &Sub : RegisteredSubCommands) { + if (SC == Sub) + continue; + addLiteralOption(Opt, Sub, Name); } } } - void addOption(Option *O) { + void addLiteralOption(Option &Opt, const char *Name) { + if (Opt.Subs.empty()) + addLiteralOption(Opt, &*TopLevelSubCommand, Name); + else { + for (auto SC : Opt.Subs) + addLiteralOption(Opt, SC, Name); + } + } + + void addOption(Option *O, SubCommand *SC) { bool HadErrors = false; if (O->hasArgStr()) { // Add argument to the argument map! - if (!OptionsMap.insert(std::make_pair(O->ArgStr, O)).second) { + if (!SC->OptionsMap.insert(std::make_pair(O->ArgStr, O)).second) { errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr << "' registered more than once!\n"; HadErrors = true; @@ -131,15 +153,15 @@ public: // Remember information about positional options. if (O->getFormattingFlag() == cl::Positional) - PositionalOpts.push_back(O); + SC->PositionalOpts.push_back(O); else if (O->getMiscFlags() & cl::Sink) // Remember sink options - SinkOpts.push_back(O); + SC->SinkOpts.push_back(O); else if (O->getNumOccurrencesFlag() == cl::ConsumeAfter) { - if (ConsumeAfterOpt) { + if (SC->ConsumeAfterOpt) { O->error("Cannot specify more than one option with cl::ConsumeAfter!"); HadErrors = true; } - ConsumeAfterOpt = O; + SC->ConsumeAfterOpt = O; } // Fail hard if there were errors. These are strictly unrecoverable and @@ -148,64 +170,165 @@ public: // linked LLVM distribution. if (HadErrors) report_fatal_error("inconsistency in registered CommandLine options"); + + // If we're adding this to all sub-commands, add it to the ones that have + // already been registered. + if (SC == &*AllSubCommands) { + for (const auto &Sub : RegisteredSubCommands) { + if (SC == Sub) + continue; + addOption(O, Sub); + } + } } - void removeOption(Option *O) { + void addOption(Option *O) { + if (O->Subs.empty()) { + addOption(O, &*TopLevelSubCommand); + } else { + for (auto SC : O->Subs) + addOption(O, SC); + } + } + + void removeOption(Option *O, SubCommand *SC) { SmallVector<StringRef, 16> OptionNames; O->getExtraOptionNames(OptionNames); if (O->hasArgStr()) OptionNames.push_back(O->ArgStr); + + SubCommand &Sub = *SC; for (auto Name : OptionNames) - OptionsMap.erase(Name); + Sub.OptionsMap.erase(Name); if (O->getFormattingFlag() == cl::Positional) - for (auto Opt = PositionalOpts.begin(); Opt != PositionalOpts.end(); - ++Opt) { + for (auto Opt = Sub.PositionalOpts.begin(); + Opt != Sub.PositionalOpts.end(); ++Opt) { if (*Opt == O) { - PositionalOpts.erase(Opt); + Sub.PositionalOpts.erase(Opt); break; } } else if (O->getMiscFlags() & cl::Sink) - for (auto Opt = SinkOpts.begin(); Opt != SinkOpts.end(); ++Opt) { + for (auto Opt = Sub.SinkOpts.begin(); Opt != Sub.SinkOpts.end(); ++Opt) { if (*Opt == O) { - SinkOpts.erase(Opt); + Sub.SinkOpts.erase(Opt); break; } } - else if (O == ConsumeAfterOpt) - ConsumeAfterOpt = nullptr; + else if (O == Sub.ConsumeAfterOpt) + Sub.ConsumeAfterOpt = nullptr; } - bool hasOptions() { - return (!OptionsMap.empty() || !PositionalOpts.empty() || - nullptr != ConsumeAfterOpt); + void removeOption(Option *O) { + if (O->Subs.empty()) + removeOption(O, &*TopLevelSubCommand); + else { + if (O->isInAllSubCommands()) { + for (auto SC : RegisteredSubCommands) + removeOption(O, SC); + } else { + for (auto SC : O->Subs) + removeOption(O, SC); + } + } } - void updateArgStr(Option *O, StringRef NewName) { - if (!OptionsMap.insert(std::make_pair(NewName, O)).second) { + bool hasOptions(const SubCommand &Sub) const { + return (!Sub.OptionsMap.empty() || !Sub.PositionalOpts.empty() || + nullptr != Sub.ConsumeAfterOpt); + } + + bool hasOptions() const { + for (const auto &S : RegisteredSubCommands) { + if (hasOptions(*S)) + return true; + } + return false; + } + + SubCommand *getActiveSubCommand() { return ActiveSubCommand; } + + void updateArgStr(Option *O, StringRef NewName, SubCommand *SC) { + SubCommand &Sub = *SC; + if (!Sub.OptionsMap.insert(std::make_pair(NewName, O)).second) { errs() << ProgramName << ": CommandLine Error: Option '" << O->ArgStr << "' registered more than once!\n"; report_fatal_error("inconsistency in registered CommandLine options"); } - OptionsMap.erase(O->ArgStr); + Sub.OptionsMap.erase(O->ArgStr); + } + + void updateArgStr(Option *O, StringRef NewName) { + if (O->Subs.empty()) + updateArgStr(O, NewName, &*TopLevelSubCommand); + else { + for (auto SC : O->Subs) + updateArgStr(O, NewName, SC); + } } void printOptionValues(); void registerCategory(OptionCategory *cat) { - assert(std::count_if(RegisteredOptionCategories.begin(), - RegisteredOptionCategories.end(), - [cat](const OptionCategory *Category) { - return cat->getName() == Category->getName(); - }) == 0 && + assert(count_if(RegisteredOptionCategories, + [cat](const OptionCategory *Category) { + return cat->getName() == Category->getName(); + }) == 0 && "Duplicate option categories"); RegisteredOptionCategories.insert(cat); } + void registerSubCommand(SubCommand *sub) { + assert(count_if(RegisteredSubCommands, + [sub](const SubCommand *Sub) { + return (sub->getName() != nullptr) && + (Sub->getName() == sub->getName()); + }) == 0 && + "Duplicate subcommands"); + RegisteredSubCommands.insert(sub); + + // For all options that have been registered for all subcommands, add the + // option to this subcommand now. + if (sub != &*AllSubCommands) { + for (auto &E : AllSubCommands->OptionsMap) { + Option *O = E.second; + if ((O->isPositional() || O->isSink() || O->isConsumeAfter()) || + O->hasArgStr()) + addOption(O, sub); + else + addLiteralOption(*O, sub, E.first().str().c_str()); + } + } + } + + void unregisterSubCommand(SubCommand *sub) { + RegisteredSubCommands.erase(sub); + } + + void reset() { + ActiveSubCommand = nullptr; + ProgramName.clear(); + ProgramOverview = nullptr; + + MoreHelp.clear(); + RegisteredOptionCategories.clear(); + + ResetAllOptionOccurrences(); + RegisteredSubCommands.clear(); + + TopLevelSubCommand->reset(); + AllSubCommands->reset(); + registerSubCommand(&*TopLevelSubCommand); + registerSubCommand(&*AllSubCommands); + } + private: - Option *LookupOption(StringRef &Arg, StringRef &Value); + SubCommand *ActiveSubCommand; + + Option *LookupOption(SubCommand &Sub, StringRef &Arg, StringRef &Value); + SubCommand *LookupSubCommand(const char *Name); }; } // namespace @@ -240,6 +363,32 @@ void OptionCategory::registerCategory() { GlobalParser->registerCategory(this); } +// A special subcommand representing no subcommand +ManagedStatic<SubCommand> llvm::cl::TopLevelSubCommand; + +// A special subcommand that can be used to put an option into all subcommands. +ManagedStatic<SubCommand> llvm::cl::AllSubCommands; + +void SubCommand::registerSubCommand() { + GlobalParser->registerSubCommand(this); +} + +void SubCommand::unregisterSubCommand() { + GlobalParser->unregisterSubCommand(this); +} + +void SubCommand::reset() { + PositionalOpts.clear(); + SinkOpts.clear(); + OptionsMap.clear(); + + ConsumeAfterOpt = nullptr; +} + +SubCommand::operator bool() const { + return (GlobalParser->getActiveSubCommand() == this); +} + //===----------------------------------------------------------------------===// // Basic, shared command line option processing machinery. // @@ -247,25 +396,29 @@ void OptionCategory::registerCategory() { /// LookupOption - Lookup the option specified by the specified option on the /// command line. If there is a value specified (after an equal sign) return /// that as well. This assumes that leading dashes have already been stripped. -Option *CommandLineParser::LookupOption(StringRef &Arg, StringRef &Value) { +Option *CommandLineParser::LookupOption(SubCommand &Sub, StringRef &Arg, + StringRef &Value) { // Reject all dashes. if (Arg.empty()) return nullptr; + assert(&Sub != &*AllSubCommands); size_t EqualPos = Arg.find('='); // If we have an equals sign, remember the value. if (EqualPos == StringRef::npos) { // Look up the option. - StringMap<Option *>::const_iterator I = OptionsMap.find(Arg); - return I != OptionsMap.end() ? I->second : nullptr; + auto I = Sub.OptionsMap.find(Arg); + if (I == Sub.OptionsMap.end()) + return nullptr; + + return I != Sub.OptionsMap.end() ? I->second : nullptr; } // If the argument before the = is a valid option name, we match. If not, // return Arg unmolested. - StringMap<Option *>::const_iterator I = - OptionsMap.find(Arg.substr(0, EqualPos)); - if (I == OptionsMap.end()) + auto I = Sub.OptionsMap.find(Arg.substr(0, EqualPos)); + if (I == Sub.OptionsMap.end()) return nullptr; Value = Arg.substr(EqualPos + 1); @@ -273,6 +426,21 @@ Option *CommandLineParser::LookupOption(StringRef &Arg, StringRef &Value) { return I->second; } +SubCommand *CommandLineParser::LookupSubCommand(const char *Name) { + if (Name == nullptr) + return &*TopLevelSubCommand; + for (auto S : RegisteredSubCommands) { + if (S == &*AllSubCommands) + continue; + if (S->getName() == nullptr) + continue; + + if (StringRef(S->getName()) == StringRef(Name)) + return S; + } + return &*TopLevelSubCommand; +} + /// LookupNearestOption - Lookup the closest match to the option specified by /// the specified option on the command line. If there is a value specified /// (after an equal sign) return that as well. This assumes that leading dashes @@ -515,8 +683,6 @@ static bool isWhitespace(char C) { return strchr(" \t\n\r\f\v", C); } static bool isQuote(char C) { return C == '\"' || C == '\''; } -static bool isGNUSpecial(char C) { return strchr("\\\"\' ", C); } - void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver, SmallVectorImpl<const char *> &NewArgv, bool MarkEOLs) { @@ -534,9 +700,8 @@ void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver, break; } - // Backslashes can escape backslashes, spaces, and other quotes. Otherwise - // they are literal. This makes it much easier to read Windows file paths. - if (I + 1 < E && Src[I] == '\\' && isGNUSpecial(Src[I + 1])) { + // Backslash escapes the next character. + if (I + 1 < E && Src[I] == '\\') { ++I; // Skip the escape. Token.push_back(Src[I]); continue; @@ -546,8 +711,8 @@ void cl::TokenizeGNUCommandLine(StringRef Src, StringSaver &Saver, if (isQuote(Src[I])) { char Quote = Src[I++]; while (I != E && Src[I] != Quote) { - // Backslashes are literal, unless they escape a special character. - if (Src[I] == '\\' && I + 1 != E && isGNUSpecial(Src[I + 1])) + // Backslash escapes the next character. + if (Src[I] == '\\' && I + 1 != E) ++I; Token.push_back(Src[I]); ++I; @@ -787,9 +952,28 @@ void cl::ParseEnvironmentOptions(const char *progName, const char *envVar, assert(envVar && "Environment variable name missing"); // Get the environment variable they want us to parse options out of. +#ifdef _WIN32 + std::wstring wenvVar; + if (!llvm::ConvertUTF8toWide(envVar, wenvVar)) { + assert(false && + "Unicode conversion of environment variable name failed"); + return; + } + const wchar_t *wenvValue = _wgetenv(wenvVar.c_str()); + if (!wenvValue) + return; + std::string envValueBuffer; + if (!llvm::convertWideToUTF8(wenvValue, envValueBuffer)) { + assert(false && + "Unicode conversion of environment variable value failed"); + return; + } + const char *envValue = envValueBuffer.c_str(); +#else const char *envValue = getenv(envVar); if (!envValue) return; +#endif // Get program's "name", which we wouldn't know without the caller // telling us. @@ -805,14 +989,25 @@ void cl::ParseEnvironmentOptions(const char *progName, const char *envVar, ParseCommandLineOptions(newArgc, &newArgv[0], Overview); } -void cl::ParseCommandLineOptions(int argc, const char *const *argv, - const char *Overview) { - GlobalParser->ParseCommandLineOptions(argc, argv, Overview); +bool cl::ParseCommandLineOptions(int argc, const char *const *argv, + const char *Overview, bool IgnoreErrors) { + return GlobalParser->ParseCommandLineOptions(argc, argv, Overview, + IgnoreErrors); } -void CommandLineParser::ParseCommandLineOptions(int argc, +void CommandLineParser::ResetAllOptionOccurrences() { + // So that we can parse different command lines multiple times in succession + // we reset all option values to look like they have never been seen before. + for (auto SC : RegisteredSubCommands) { + for (auto &O : SC->OptionsMap) + O.second->reset(); + } +} + +bool CommandLineParser::ParseCommandLineOptions(int argc, const char *const *argv, - const char *Overview) { + const char *Overview, + bool IgnoreErrors) { assert(hasOptions() && "No options specified!"); // Expand response files. @@ -835,6 +1030,23 @@ void CommandLineParser::ParseCommandLineOptions(int argc, // Determine whether or not there are an unlimited number of positionals bool HasUnlimitedPositionals = false; + int FirstArg = 1; + SubCommand *ChosenSubCommand = &*TopLevelSubCommand; + if (argc >= 2 && argv[FirstArg][0] != '-') { + // If the first argument specifies a valid subcommand, start processing + // options from the second argument. + ChosenSubCommand = LookupSubCommand(argv[FirstArg]); + if (ChosenSubCommand != &*TopLevelSubCommand) + FirstArg = 2; + } + GlobalParser->ActiveSubCommand = ChosenSubCommand; + + assert(ChosenSubCommand); + auto &ConsumeAfterOpt = ChosenSubCommand->ConsumeAfterOpt; + auto &PositionalOpts = ChosenSubCommand->PositionalOpts; + auto &SinkOpts = ChosenSubCommand->SinkOpts; + auto &OptionsMap = ChosenSubCommand->OptionsMap; + if (ConsumeAfterOpt) { assert(PositionalOpts.size() > 0 && "Cannot specify cl::ConsumeAfter without a positional argument!"); @@ -850,23 +1062,28 @@ void CommandLineParser::ParseCommandLineOptions(int argc, else if (ConsumeAfterOpt) { // ConsumeAfter cannot be combined with "optional" positional options // unless there is only one positional argument... - if (PositionalOpts.size() > 1) - ErrorParsing |= Opt->error( - "error - this positional option will never be matched, " - "because it does not Require a value, and a " - "cl::ConsumeAfter option is active!"); + if (PositionalOpts.size() > 1) { + if (!IgnoreErrors) + Opt->error("error - this positional option will never be matched, " + "because it does not Require a value, and a " + "cl::ConsumeAfter option is active!"); + ErrorParsing = true; + } } else if (UnboundedFound && !Opt->hasArgStr()) { // This option does not "require" a value... Make sure this option is // not specified after an option that eats all extra arguments, or this // one will never get any! // - ErrorParsing |= Opt->error("error - option can never match, because " - "another positional argument will match an " - "unbounded number of values, and this option" - " does not require a value!"); - errs() << ProgramName << ": CommandLine Error: Option '" << Opt->ArgStr - << "' is all messed up!\n"; - errs() << PositionalOpts.size(); + if (!IgnoreErrors) { + Opt->error("error - option can never match, because " + "another positional argument will match an " + "unbounded number of values, and this option" + " does not require a value!"); + errs() << ProgramName << ": CommandLine Error: Option '" + << Opt->ArgStr << "' is all messed up!\n"; + errs() << PositionalOpts.size(); + } + ErrorParsing = true; } UnboundedFound |= EatsUnboundedNumberOfValues(Opt); } @@ -885,7 +1102,7 @@ void CommandLineParser::ParseCommandLineOptions(int argc, // Loop over all of the arguments... processing them. bool DashDashFound = false; // Have we read '--'? - for (int i = 1; i < argc; ++i) { + for (int i = FirstArg; i < argc; ++i) { Option *Handler = nullptr; Option *NearestHandler = nullptr; std::string NearestHandlerString; @@ -932,7 +1149,7 @@ void CommandLineParser::ParseCommandLineOptions(int argc, while (!ArgName.empty() && ArgName[0] == '-') ArgName = ArgName.substr(1); - Handler = LookupOption(ArgName, Value); + Handler = LookupOption(*ChosenSubCommand, ArgName, Value); if (!Handler || Handler->getFormattingFlag() != cl::Positional) { ProvidePositionalOption(ActivePositionalArg, argv[i], i); continue; // We are done! @@ -944,7 +1161,7 @@ void CommandLineParser::ParseCommandLineOptions(int argc, while (!ArgName.empty() && ArgName[0] == '-') ArgName = ArgName.substr(1); - Handler = LookupOption(ArgName, Value); + Handler = LookupOption(*ChosenSubCommand, ArgName, Value); // Check to see if this "option" is really a prefixed or grouped argument. if (!Handler) @@ -960,13 +1177,15 @@ void CommandLineParser::ParseCommandLineOptions(int argc, if (!Handler) { if (SinkOpts.empty()) { - errs() << ProgramName << ": Unknown command line argument '" << argv[i] - << "'. Try: '" << argv[0] << " -help'\n"; - - if (NearestHandler) { - // If we know a near match, report it as well. - errs() << ProgramName << ": Did you mean '-" << NearestHandlerString - << "'?\n"; + if (!IgnoreErrors) { + errs() << ProgramName << ": Unknown command line argument '" + << argv[i] << "'. Try: '" << argv[0] << " -help'\n"; + + if (NearestHandler) { + // If we know a near match, report it as well. + errs() << ProgramName << ": Did you mean '-" << NearestHandlerString + << "'?\n"; + } } ErrorParsing = true; @@ -989,17 +1208,21 @@ void CommandLineParser::ParseCommandLineOptions(int argc, // Check and handle positional arguments now... if (NumPositionalRequired > PositionalVals.size()) { - errs() << ProgramName - << ": Not enough positional command line arguments specified!\n" - << "Must specify at least " << NumPositionalRequired - << " positional arguments: See: " << argv[0] << " -help\n"; + if (!IgnoreErrors) { + errs() << ProgramName + << ": Not enough positional command line arguments specified!\n" + << "Must specify at least " << NumPositionalRequired + << " positional arguments: See: " << argv[0] << " -help\n"; + } ErrorParsing = true; } else if (!HasUnlimitedPositionals && PositionalVals.size() > PositionalOpts.size()) { - errs() << ProgramName << ": Too many positional arguments specified!\n" - << "Can specify at most " << PositionalOpts.size() - << " positional arguments: See: " << argv[0] << " -help\n"; + if (!IgnoreErrors) { + errs() << ProgramName << ": Too many positional arguments specified!\n" + << "Can specify at most " << PositionalOpts.size() + << " positional arguments: See: " << argv[0] << " -help\n"; + } ErrorParsing = true; } else if (!ConsumeAfterOpt) { @@ -1094,8 +1317,12 @@ void CommandLineParser::ParseCommandLineOptions(int argc, MoreHelp.clear(); // If we had an error processing our arguments, don't let the program execute - if (ErrorParsing) - exit(1); + if (ErrorParsing) { + if (!IgnoreErrors) + exit(1); + return false; + } + return true; } //===----------------------------------------------------------------------===// @@ -1416,7 +1643,7 @@ PRINT_OPT_DIFF(float) PRINT_OPT_DIFF(char) void parser<std::string>::printOptionDiff(const Option &O, StringRef V, - OptionValue<std::string> D, + const OptionValue<std::string> &D, size_t GlobalWidth) const { printOptionName(O, GlobalWidth); outs() << "= " << V; @@ -1445,11 +1672,16 @@ static int OptNameCompare(const std::pair<const char *, Option *> *LHS, return strcmp(LHS->first, RHS->first); } +static int SubNameCompare(const std::pair<const char *, SubCommand *> *LHS, + const std::pair<const char *, SubCommand *> *RHS) { + return strcmp(LHS->first, RHS->first); +} + // Copy Options into a vector so we can sort them as we like. static void sortOpts(StringMap<Option *> &OptMap, SmallVectorImpl<std::pair<const char *, Option *>> &Opts, bool ShowHidden) { - SmallPtrSet<Option *, 128> OptionSet; // Duplicate option detection. + SmallPtrSet<Option *, 32> OptionSet; // Duplicate option detection. for (StringMap<Option *>::iterator I = OptMap.begin(), E = OptMap.end(); I != E; ++I) { @@ -1473,6 +1705,17 @@ static void sortOpts(StringMap<Option *> &OptMap, array_pod_sort(Opts.begin(), Opts.end(), OptNameCompare); } +static void +sortSubCommands(const SmallPtrSetImpl<SubCommand *> &SubMap, + SmallVectorImpl<std::pair<const char *, SubCommand *>> &Subs) { + for (const auto &S : SubMap) { + if (S->getName() == nullptr) + continue; + Subs.push_back(std::make_pair(S->getName(), S)); + } + array_pod_sort(Subs.begin(), Subs.end(), SubNameCompare); +} + namespace { class HelpPrinter { @@ -1480,12 +1723,25 @@ protected: const bool ShowHidden; typedef SmallVector<std::pair<const char *, Option *>, 128> StrOptionPairVector; + typedef SmallVector<std::pair<const char *, SubCommand *>, 128> + StrSubCommandPairVector; // Print the options. Opts is assumed to be alphabetically sorted. virtual void printOptions(StrOptionPairVector &Opts, size_t MaxArgLen) { for (size_t i = 0, e = Opts.size(); i != e; ++i) Opts[i].second->printOptionInfo(MaxArgLen); } + void printSubCommands(StrSubCommandPairVector &Subs, size_t MaxSubLen) { + for (const auto &S : Subs) { + outs() << " " << S.first; + if (S.second->getDescription()) { + outs().indent(MaxSubLen - strlen(S.first)); + outs() << " - " << S.second->getDescription(); + } + outs() << "\n"; + } + } + public: explicit HelpPrinter(bool showHidden) : ShowHidden(showHidden) {} virtual ~HelpPrinter() {} @@ -1495,23 +1751,56 @@ public: if (!Value) return; + SubCommand *Sub = GlobalParser->getActiveSubCommand(); + auto &OptionsMap = Sub->OptionsMap; + auto &PositionalOpts = Sub->PositionalOpts; + auto &ConsumeAfterOpt = Sub->ConsumeAfterOpt; + StrOptionPairVector Opts; - sortOpts(GlobalParser->OptionsMap, Opts, ShowHidden); + sortOpts(OptionsMap, Opts, ShowHidden); + + StrSubCommandPairVector Subs; + sortSubCommands(GlobalParser->RegisteredSubCommands, Subs); if (GlobalParser->ProgramOverview) outs() << "OVERVIEW: " << GlobalParser->ProgramOverview << "\n"; - outs() << "USAGE: " << GlobalParser->ProgramName << " [options]"; + if (Sub == &*TopLevelSubCommand) + outs() << "USAGE: " << GlobalParser->ProgramName + << " [subcommand] [options]"; + else { + if (Sub->getDescription() != nullptr) { + outs() << "SUBCOMMAND '" << Sub->getName() + << "': " << Sub->getDescription() << "\n\n"; + } + outs() << "USAGE: " << GlobalParser->ProgramName << " " << Sub->getName() + << " [options]"; + } - for (auto Opt : GlobalParser->PositionalOpts) { + for (auto Opt : PositionalOpts) { if (Opt->hasArgStr()) outs() << " --" << Opt->ArgStr; outs() << " " << Opt->HelpStr; } // Print the consume after option info if it exists... - if (GlobalParser->ConsumeAfterOpt) - outs() << " " << GlobalParser->ConsumeAfterOpt->HelpStr; + if (ConsumeAfterOpt) + outs() << " " << ConsumeAfterOpt->HelpStr; + + if (Sub == &*TopLevelSubCommand && Subs.size() > 2) { + // Compute the maximum subcommand length... + size_t MaxSubLen = 0; + for (size_t i = 0, e = Subs.size(); i != e; ++i) + MaxSubLen = std::max(MaxSubLen, strlen(Subs[i].first)); + + outs() << "\n\n"; + outs() << "SUBCOMMANDS:\n\n"; + printSubCommands(Subs, MaxSubLen); + outs() << "\n"; + outs() << " Type \"" << GlobalParser->ProgramName + << " <subcommand> -help\" to get more help on a specific " + "subcommand"; + } outs() << "\n\n"; @@ -1589,7 +1878,8 @@ protected: E = SortedCategories.end(); Category != E; ++Category) { // Hide empty categories for -help, but show for -help-hidden. - bool IsEmptyCategory = CategorizedOptions[*Category].size() == 0; + const auto &CategoryOptions = CategorizedOptions[*Category]; + bool IsEmptyCategory = CategoryOptions.empty(); if (!ShowHidden && IsEmptyCategory) continue; @@ -1610,11 +1900,8 @@ protected: continue; } // Loop over the options in the category and print. - for (std::vector<Option *>::const_iterator - Opt = CategorizedOptions[*Category].begin(), - E = CategorizedOptions[*Category].end(); - Opt != E; ++Opt) - (*Opt)->printOptionInfo(MaxArgLen); + for (const Option *Opt : CategoryOptions) + Opt->printOptionInfo(MaxArgLen); } } }; @@ -1662,12 +1949,13 @@ static cl::opt<HelpPrinter, true, parser<bool>> HLOp( "help-list", cl::desc("Display list of available options (-help-list-hidden for more)"), cl::location(UncategorizedNormalPrinter), cl::Hidden, cl::ValueDisallowed, - cl::cat(GenericCategory)); + cl::cat(GenericCategory), cl::sub(*AllSubCommands)); static cl::opt<HelpPrinter, true, parser<bool>> HLHOp("help-list-hidden", cl::desc("Display list of all available options"), cl::location(UncategorizedHiddenPrinter), cl::Hidden, - cl::ValueDisallowed, cl::cat(GenericCategory)); + cl::ValueDisallowed, cl::cat(GenericCategory), + cl::sub(*AllSubCommands)); // Define uncategorized/categorized help printers. These printers change their // behaviour at runtime depending on whether one or more Option categories have @@ -1675,22 +1963,23 @@ static cl::opt<HelpPrinter, true, parser<bool>> static cl::opt<HelpPrinterWrapper, true, parser<bool>> HOp("help", cl::desc("Display available options (-help-hidden for more)"), cl::location(WrappedNormalPrinter), cl::ValueDisallowed, - cl::cat(GenericCategory)); + cl::cat(GenericCategory), cl::sub(*AllSubCommands)); static cl::opt<HelpPrinterWrapper, true, parser<bool>> HHOp("help-hidden", cl::desc("Display all available options"), cl::location(WrappedHiddenPrinter), cl::Hidden, cl::ValueDisallowed, - cl::cat(GenericCategory)); + cl::cat(GenericCategory), cl::sub(*AllSubCommands)); static cl::opt<bool> PrintOptions( "print-options", cl::desc("Print non-default options after command line parsing"), - cl::Hidden, cl::init(false), cl::cat(GenericCategory)); + cl::Hidden, cl::init(false), cl::cat(GenericCategory), + cl::sub(*AllSubCommands)); static cl::opt<bool> PrintAllOptions( "print-all-options", cl::desc("Print all option values after command line parsing"), cl::Hidden, - cl::init(false), cl::cat(GenericCategory)); + cl::init(false), cl::cat(GenericCategory), cl::sub(*AllSubCommands)); void HelpPrinterWrapper::operator=(bool Value) { if (!Value) @@ -1717,7 +2006,7 @@ void CommandLineParser::printOptionValues() { return; SmallVector<std::pair<const char *, Option *>, 128> Opts; - sortOpts(OptionsMap, Opts, /*ShowHidden*/ true); + sortOpts(ActiveSubCommand->OptionsMap, Opts, /*ShowHidden*/ true); // Compute the maximum argument length... size_t MaxArgLen = 0; @@ -1737,8 +2026,12 @@ class VersionPrinter { public: void print() { raw_ostream &OS = outs(); - OS << "LLVM (http://llvm.org/):\n" - << " " << PACKAGE_NAME << " version " << PACKAGE_VERSION; +#ifdef PACKAGE_VENDOR + OS << PACKAGE_VENDOR << " "; +#else + OS << "LLVM (http://llvm.org/):\n "; +#endif + OS << PACKAGE_NAME << " version " << PACKAGE_VERSION; #ifdef LLVM_VERSION_INFO OS << " " << LLVM_VERSION_INFO; #endif @@ -1755,9 +2048,6 @@ public: if (CPU == "generic") CPU = "(unknown)"; OS << ".\n" -#if (ENABLE_TIMESTAMPS == 1) - << " Built " << __DATE__ << " (" << __TIME__ << ").\n" -#endif << " Default target: " << sys::getDefaultTargetTriple() << '\n' << " Host CPU: " << CPU << '\n'; } @@ -1825,22 +2115,26 @@ void cl::AddExtraVersionPrinter(void (*func)()) { ExtraVersionPrinters->push_back(func); } -StringMap<Option *> &cl::getRegisteredOptions() { - return GlobalParser->OptionsMap; +StringMap<Option *> &cl::getRegisteredOptions(SubCommand &Sub) { + auto &Subs = GlobalParser->RegisteredSubCommands; + (void)Subs; + assert(std::find(Subs.begin(), Subs.end(), &Sub) != Subs.end()); + return Sub.OptionsMap; } -void cl::HideUnrelatedOptions(cl::OptionCategory &Category) { - for (auto &I : GlobalParser->OptionsMap) { +void cl::HideUnrelatedOptions(cl::OptionCategory &Category, SubCommand &Sub) { + for (auto &I : Sub.OptionsMap) { if (I.second->Category != &Category && I.second->Category != &GenericCategory) I.second->setHiddenFlag(cl::ReallyHidden); } } -void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories) { +void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories, + SubCommand &Sub) { auto CategoriesBegin = Categories.begin(); auto CategoriesEnd = Categories.end(); - for (auto &I : GlobalParser->OptionsMap) { + for (auto &I : Sub.OptionsMap) { if (std::find(CategoriesBegin, CategoriesEnd, I.second->Category) == CategoriesEnd && I.second->Category != &GenericCategory) @@ -1848,7 +2142,12 @@ void cl::HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories) { } } +void cl::ResetCommandLineParser() { GlobalParser->reset(); } +void cl::ResetAllOptionOccurrences() { + GlobalParser->ResetAllOptionOccurrences(); +} + void LLVMParseCommandLineOptions(int argc, const char *const *argv, const char *Overview) { - llvm::cl::ParseCommandLineOptions(argc, argv, Overview); + llvm::cl::ParseCommandLineOptions(argc, argv, Overview, true); } |