summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/lib/Support/CommandLine.cpp
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2016-12-26 20:36:37 +0000
committerdim <dim@FreeBSD.org>2016-12-26 20:36:37 +0000
commit06210ae42d418d50d8d9365d5c9419308ae9e7ee (patch)
treeab60b4cdd6e430dda1f292a46a77ddb744723f31 /contrib/llvm/lib/Support/CommandLine.cpp
parent2dd166267f53df1c3748b4325d294b9b839de74b (diff)
downloadFreeBSD-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.cpp545
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);
}
OpenPOWER on IntegriCloud