Page MenuHomePhabricator

D21485.id61148.diff
No OneTemporary

File Metadata

Created
Jan 24 2020, 4:06 PM

D21485.id61148.diff

Index: include/llvm/Support/CommandLine.h
===================================================================
--- include/llvm/Support/CommandLine.h
+++ include/llvm/Support/CommandLine.h
@@ -21,10 +21,12 @@
#define LLVM_SUPPORT_COMMANDLINE_H
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/ManagedStatic.h"
#include <cassert>
#include <climits>
#include <cstdarg>
@@ -171,6 +173,42 @@
extern OptionCategory GeneralCategory;
//===----------------------------------------------------------------------===//
+// SubCommand class
+//
+class SubCommand {
+private:
+ const char *const Name;
+ const char *const Description;
+
+ void registerSubCommand();
+
+public:
+ SubCommand(const char *const Name, const char *const Description = nullptr)
+ : Name(Name), Description(Description), ConsumeAfterOpt(nullptr) {
+ registerSubCommand();
+ }
+ SubCommand()
+ : Name(nullptr), Description(nullptr), ConsumeAfterOpt(nullptr) {}
+
+ operator bool() const;
+
+ const char *getName() const { return Name; }
+ const char *getDescription() const { return Description; }
+
+ SmallVector<Option *, 4> PositionalOpts;
+ SmallVector<Option *, 4> SinkOpts;
+ StringMap<Option *> OptionsMap;
+
+ Option *ConsumeAfterOpt; // The ConsumeAfter option if it exists.
+};
+
+// A special subcommand representing no subcommand
+extern ManagedStatic<SubCommand> TopLevelSubCommand;
+
+// A special subcommand that can be used to put an option into all subcommands.
+extern ManagedStatic<SubCommand> AllSubCommands;
+
+//===----------------------------------------------------------------------===//
// Option Base class
//
class alias;
@@ -209,6 +247,7 @@
StringRef HelpStr; // The descriptive text message for -help
StringRef ValueStr; // String describing what the value of this option is
OptionCategory *Category; // The Category this option belongs to
+ SmallPtrSet<SubCommand *, 4> Subs; // The subcommands this option belongs to.
bool FullyInitialized; // Has addArguemnt been called?
inline enum NumOccurrencesFlag getNumOccurrencesFlag() const {
@@ -229,6 +268,11 @@
// hasArgStr - Return true if the argstr != ""
bool hasArgStr() const { return !ArgStr.empty(); }
+ bool isPositional() const { return getFormattingFlag() == cl::Positional; }
+ bool isSink() const { return getMiscFlags() & cl::Sink; }
+ bool isConsumeAfter() const {
+ return getNumOccurrencesFlag() == cl::ConsumeAfter;
+ }
//-------------------------------------------------------------------------===
// Accessor functions set by OptionModifiers
@@ -243,6 +287,7 @@
void setMiscFlag(enum MiscFlags M) { Misc |= M; }
void setPosition(unsigned pos) { Position = pos; }
void setCategory(OptionCategory &C) { Category = &C; }
+ void addSubCommand(SubCommand &S) { Subs.insert(&S); }
protected:
explicit Option(enum NumOccurrencesFlag OccurrencesFlag,
@@ -349,6 +394,14 @@
template <class Opt> void apply(Opt &O) const { O.setCategory(Category); }
};
+// sub - Specify the subcommand that this option belongs to.
+struct sub {
+ SubCommand &Sub;
+ sub(SubCommand &S) : Sub(S) {}
+
+ template <class Opt> void apply(Opt &O) const { O.addSubCommand(Sub); }
+};
+
//===----------------------------------------------------------------------===//
// OptionValue class
@@ -1589,6 +1642,7 @@
error("cl::alias must have argument name specified!");
if (!AliasFor)
error("cl::alias must have an cl::aliasopt(option) specified!");
+ Subs = AliasFor->Subs;
addArgument();
}
@@ -1669,7 +1723,7 @@
/// Hopefully this API can be depricated soon. Any situation where options need
/// to be modified by tools or libraries should be handled by sane APIs rather
/// than just handing around a global list.
-StringMap<Option *> &getRegisteredOptions();
+StringMap<Option *> &getRegisteredOptions(SubCommand &Sub);
//===----------------------------------------------------------------------===//
// Standalone command line processing utilities.
@@ -1737,7 +1791,8 @@
/// Some tools (like clang-format) like to be able to hide all options that are
/// not specific to the tool. This function allows a tool to specify a single
/// option category to display in the -help output.
-void HideUnrelatedOptions(cl::OptionCategory &Category);
+void HideUnrelatedOptions(cl::OptionCategory &Category,
+ SubCommand &Sub = *TopLevelSubCommand);
/// \brief Mark all options not part of the categories as cl::ReallyHidden.
///
@@ -1746,7 +1801,8 @@
/// Some tools (like clang-format) like to be able to hide all options that are
/// not specific to the tool. This function allows a tool to specify a single
/// option category to display in the -help output.
-void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories);
+void HideUnrelatedOptions(ArrayRef<const cl::OptionCategory *> Categories,
+ SubCommand &Sub = *TopLevelSubCommand);
} // End namespace cl
Index: lib/Support/CommandLine.cpp
===================================================================
--- lib/Support/CommandLine.cpp
+++ 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,55 @@
// 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 *, 16> RegisteredSubCommands;
+
+ CommandLineParser()
+ : ProgramOverview(nullptr), ActiveSubCommand(&*TopLevelSubCommand) {
+ registerSubCommand(&*TopLevelSubCommand);
+ registerSubCommand(&*AllSubCommands);
+ }
void ParseCommandLineOptions(int argc, const char *const *argv,
const char *Overview);
- void addLiteralOption(Option &Opt, const char *Name) {
+ void addLiteralOption(Option &Opt, SubCommand *SC, const char *Name) {
if (!Opt.hasArgStr()) {
- if (!OptionsMap.insert(std::make_pair(Name, &Opt)).second) {
+ 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 +152,15 @@
// 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,47 +169,97 @@
// 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 {
+ 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();
@@ -203,8 +274,33 @@
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())
+ addOption(O, sub);
+ else
+ addLiteralOption(*O, sub, E.first().str().c_str());
+ }
+ }
+ }
+
private:
- Option *LookupOption(StringRef &Arg, StringRef &Value);
+ SubCommand *ActiveSubCommand;
+
+ Option *LookupOption(SubCommand &Sub, StringRef &Arg, StringRef &Value);
+ SubCommand *LookupSubCommand(const char *Name);
};
} // namespace
@@ -239,6 +335,20 @@
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);
+}
+
+SubCommand::operator bool() const {
+ return (GlobalParser->getActiveSubCommand() == this);
+}
+
//===----------------------------------------------------------------------===//
// Basic, shared command line option processing machinery.
//
@@ -246,25 +356,29 @@
/// 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);
@@ -272,6 +386,21 @@
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
@@ -850,6 +979,23 @@
// 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!");
@@ -900,7 +1046,7 @@
// 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;
@@ -947,7 +1093,7 @@
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!
@@ -959,7 +1105,7 @@
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)
@@ -1460,6 +1606,11 @@
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,
@@ -1488,6 +1639,17 @@
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 {
@@ -1495,12 +1657,25 @@
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() {}
@@ -1510,23 +1685,58 @@
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) {
+ if (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";
@@ -1675,12 +1885,13 @@
"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
@@ -1688,22 +1899,23 @@
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)
@@ -1730,7 +1942,7 @@
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;
@@ -1839,22 +2051,25 @@
ExtraVersionPrinters->push_back(func);
}
-StringMap<Option *> &cl::getRegisteredOptions() {
- return GlobalParser->OptionsMap;
+StringMap<Option *> &cl::getRegisteredOptions(SubCommand &Sub) {
+ auto &Subs = GlobalParser->RegisteredSubCommands;
+ 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)
Index: test/DebugInfo/PDB/DIA/pdbdump-flags.test
===================================================================
--- test/DebugInfo/PDB/DIA/pdbdump-flags.test
+++ test/DebugInfo/PDB/DIA/pdbdump-flags.test
@@ -1,7 +1,7 @@
-; RUN: llvm-pdbdump %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=NO_ARGS
-; RUN: llvm-pdbdump -types %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=TYPES
-; RUN: llvm-pdbdump -compilands %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=COMPILANDS
-; RUN: llvm-pdbdump -types -compilands %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=MULTIPLE
+; RUN: llvm-pdbdump pretty %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=NO_ARGS
+; RUN: llvm-pdbdump pretty -types %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=TYPES
+; RUN: llvm-pdbdump pretty -compilands %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=COMPILANDS
+; RUN: llvm-pdbdump pretty -types -compilands %p/../Inputs/empty.pdb | FileCheck %s -check-prefix=MULTIPLE
; Check that neither symbols nor compilands are dumped when neither argument specified.
; NO_ARGS: empty.pdb
Index: test/DebugInfo/PDB/DIA/pdbdump-linenumbers.test
===================================================================
--- test/DebugInfo/PDB/DIA/pdbdump-linenumbers.test
+++ test/DebugInfo/PDB/DIA/pdbdump-linenumbers.test
@@ -1,4 +1,4 @@
-; RUN: llvm-pdbdump -lines %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=LINE_NUMS %s
+; RUN: llvm-pdbdump pretty -lines %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=LINE_NUMS %s
; LINE_NUMS: llvm\test\debuginfo\pdb\inputs\symbolformat-fpo.cpp
; LINE_NUMS: Line 5, Address: [0x000011a0 - 0x000011a5] (6 bytes)
Index: test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test
===================================================================
--- test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test
+++ test/DebugInfo/PDB/DIA/pdbdump-symbol-format.test
@@ -1,10 +1,10 @@
-; RUN: llvm-pdbdump -symbols %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=SYM_FORMAT %s
-; RUN: llvm-pdbdump -types %p/../Inputs/symbolformat.pdb > %t.types
+; RUN: llvm-pdbdump pretty -symbols %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=SYM_FORMAT %s
+; RUN: llvm-pdbdump pretty -types %p/../Inputs/symbolformat.pdb > %t.types
; RUN: FileCheck --check-prefix=TYPES_FORMAT %s < %t.types
; RUN: FileCheck --check-prefix=TYPES_1 %s < %t.types
; RUN: FileCheck --check-prefix=TYPES_2 %s < %t.types
-; RUN: llvm-pdbdump -types %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=TYPES_FORMAT %s
-; RUN: llvm-pdbdump -globals %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=GLOBALS %s
+; RUN: llvm-pdbdump pretty -types %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=TYPES_FORMAT %s
+; RUN: llvm-pdbdump pretty -globals %p/../Inputs/symbolformat.pdb | FileCheck --check-prefix=GLOBALS %s
; The format is func [0x<rva_start>+<prologue_length> - 0x<rva_end>-<epilogue_length>]
; SYM_FORMAT: ---SYMBOLS---
Index: test/DebugInfo/PDB/pdbdump-headers.test
===================================================================
--- test/DebugInfo/PDB/pdbdump-headers.test
+++ test/DebugInfo/PDB/pdbdump-headers.test
@@ -1,12 +1,12 @@
-; RUN: llvm-pdbdump -raw-headers -raw-tpi-records -raw-tpi-record-bytes -raw-module-syms \
-; RUN: -raw-sym-record-bytes -raw-publics -raw-module-files -raw-stream-name=/names \
-; RUN: -raw-stream-summary -raw-stream-blocks -raw-ipi-records -raw-ipi-record-bytes \
-; RUN: -raw-section-contribs -raw-section-map -raw-section-headers -raw-line-info \
-; RUN: -raw-tpi-hash -raw-fpo %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s
-; RUN: llvm-pdbdump -raw-all %p/Inputs/empty.pdb | FileCheck -check-prefix=ALL %s
-; RUN: llvm-pdbdump -raw-headers -raw-stream-name=/names -raw-modules -raw-module-files \
+; RUN: llvm-pdbdump raw -headers -tpi-records -tpi-record-bytes -module-syms \
+; RUN: -sym-record-bytes -publics -module-files -stream-name=/names \
+; RUN: -stream-summary -stream-blocks -ipi-records -ipi-record-bytes \
+; RUN: -section-contribs -section-map -section-headers -line-info \
+; RUN: -tpi-hash -fpo %p/Inputs/empty.pdb | FileCheck -check-prefix=EMPTY %s
+; RUN: llvm-pdbdump raw -all %p/Inputs/empty.pdb | FileCheck -check-prefix=ALL %s
+; RUN: llvm-pdbdump raw -headers -stream-name=/names -modules -module-files \
; RUN: %p/Inputs/big-read.pdb | FileCheck -check-prefix=BIG %s
-; RUN: not llvm-pdbdump -raw-headers %p/Inputs/bad-block-size.pdb 2>&1 | FileCheck -check-prefix=BAD-BLOCK-SIZE %s
+; RUN: not llvm-pdbdump raw -headers %p/Inputs/bad-block-size.pdb 2>&1 | FileCheck -check-prefix=BAD-BLOCK-SIZE %s
; EMPTY: FileHeaders {
; EMPTY-NEXT: BlockSize: 4096
Index: test/DebugInfo/PDB/pdbdump-yaml.test
===================================================================
--- test/DebugInfo/PDB/pdbdump-yaml.test
+++ test/DebugInfo/PDB/pdbdump-yaml.test
@@ -1,5 +1,4 @@
-; RUN: llvm-pdbdump -raw-headers -raw-output-style=YAML %p/Inputs/empty.pdb \
-; RUN: | FileCheck -check-prefix=YAML %s
+; RUN: llvm-pdbdump pdb2yaml -headers %p/Inputs/empty.pdb | FileCheck -check-prefix=YAML %s
; YAML: ---
; YAML-NEXT: MSF:
Index: test/tools/llvm-pdbdump/class-layout.test
===================================================================
--- test/tools/llvm-pdbdump/class-layout.test
+++ test/tools/llvm-pdbdump/class-layout.test
@@ -1,4 +1,4 @@
-; RUN: llvm-pdbdump -all %p/Inputs/ClassLayoutTest.pdb > %t
+; RUN: llvm-pdbdump pretty -all %p/Inputs/ClassLayoutTest.pdb > %t
; RUN: FileCheck -input-file=%t %s -check-prefix=GLOBALS_TEST
; RUN: FileCheck -input-file=%t %s -check-prefix=MEMBERS_TEST
; RUN: FileCheck -input-file=%t %s -check-prefix=BASE_CLASS_A
Index: test/tools/llvm-pdbdump/enum-layout.test
===================================================================
--- test/tools/llvm-pdbdump/enum-layout.test
+++ test/tools/llvm-pdbdump/enum-layout.test
@@ -1,4 +1,4 @@
-; RUN: llvm-pdbdump -types %p/Inputs/ClassLayoutTest.pdb > %t
+; RUN: llvm-pdbdump pretty -types %p/Inputs/ClassLayoutTest.pdb > %t
; RUN: FileCheck -input-file=%t %s -check-prefix=GLOBAL_ENUM
; RUN: FileCheck -input-file=%t %s -check-prefix=MEMBER_ENUM
Index: test/tools/llvm-pdbdump/load-address.test
===================================================================
--- test/tools/llvm-pdbdump/load-address.test
+++ test/tools/llvm-pdbdump/load-address.test
@@ -1,6 +1,6 @@
-; RUN: llvm-pdbdump -externals %p/Inputs/LoadAddressTest.pdb \
+; RUN: llvm-pdbdump pretty -externals %p/Inputs/LoadAddressTest.pdb \
; RUN: | FileCheck --check-prefix=RVA %s
-; RUN: llvm-pdbdump -externals -load-address=0x40000000 \
+; RUN: llvm-pdbdump pretty -externals -load-address=0x40000000 \
; RUN: %p/Inputs/LoadAddressTest.pdb | FileCheck --check-prefix=VA %s
; RVA: ---EXTERNALS---
Index: test/tools/llvm-pdbdump/regex-filter.test
===================================================================
--- test/tools/llvm-pdbdump/regex-filter.test
+++ test/tools/llvm-pdbdump/regex-filter.test
@@ -1,18 +1,18 @@
-; RUN: llvm-pdbdump -symbols -globals -types %p/Inputs/FilterTest.pdb \
+; RUN: llvm-pdbdump pretty -symbols -globals -types %p/Inputs/FilterTest.pdb \
; RUN: | FileCheck --check-prefix=NO_FILTER %s
-; RUN: llvm-pdbdump -types -exclude-types="GlobalTypedef|NestedTypedef" \
+; RUN: llvm-pdbdump pretty -types -exclude-types="GlobalTypedef|NestedTypedef" \
; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=EXCLUDE_TYPEDEFS %s
-; RUN: llvm-pdbdump -types -exclude-types="GlobalEnum|NestedEnum" \
+; RUN: llvm-pdbdump pretty -types -exclude-types="GlobalEnum|NestedEnum" \
; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=EXCLUDE_ENUMS %s
-; RUN: llvm-pdbdump -types -symbols -globals -exclude-symbols="MemberVar|GlobalVar" \
+; RUN: llvm-pdbdump pretty -types -symbols -globals -exclude-symbols="MemberVar|GlobalVar" \
; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=EXCLUDE_VARS %s
-; RUN: llvm-pdbdump -types -exclude-types="FilterTestClass" \
+; RUN: llvm-pdbdump pretty -types -exclude-types="FilterTestClass" \
; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=EXCLUDE_WHOLE_CLASS %s
-; RUN: llvm-pdbdump -symbols -globals -exclude-compilands="FilterTest.obj" \
+; RUN: llvm-pdbdump pretty -symbols -globals -exclude-compilands="FilterTest.obj" \
; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=EXCLUDE_COMPILAND %s
-; RUN: llvm-pdbdump -types -include-types="FilterTestClass" \
+; RUN: llvm-pdbdump pretty -types -include-types="FilterTestClass" \
; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=INCLUDE_ONLY_TYPES %s
-; RUN: llvm-pdbdump -types -symbols -globals -include-symbols="[[:<:]](IntGlobalVar|DoubleGlobalVar)[[:>:]]" \
+; RUN: llvm-pdbdump pretty -types -symbols -globals -include-symbols="[[:<:]](IntGlobalVar|DoubleGlobalVar)[[:>:]]" \
; RUN: %p/Inputs/FilterTest.pdb | FileCheck --check-prefix=INCLUDE_ONLY_VARS %s
; NO_FILTER: ---TYPES---
Index: tools/llvm-pdbdump/ClassDefinitionDumper.cpp
===================================================================
--- tools/llvm-pdbdump/ClassDefinitionDumper.cpp
+++ tools/llvm-pdbdump/ClassDefinitionDumper.cpp
@@ -85,7 +85,7 @@
auto &AccessGroup = Groups.find((int)Access)->second;
if (auto Func = dyn_cast<PDBSymbolFunc>(Child.get())) {
- if (Func->isCompilerGenerated() && opts::ExcludeCompilerGenerated)
+ if (Func->isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
continue;
if (Func->getLength() == 0 && !Func->isPureVirtual() &&
!Func->isIntroVirtualFunction())
Index: tools/llvm-pdbdump/EnumDumper.cpp
===================================================================
--- tools/llvm-pdbdump/EnumDumper.cpp
+++ tools/llvm-pdbdump/EnumDumper.cpp
@@ -25,7 +25,7 @@
void EnumDumper::start(const PDBSymbolTypeEnum &Symbol) {
WithColor(Printer, PDB_ColorItem::Keyword).get() << "enum ";
WithColor(Printer, PDB_ColorItem::Type).get() << Symbol.getName();
- if (!opts::NoEnumDefs) {
+ if (!opts::pretty::NoEnumDefs) {
auto BuiltinType = Symbol.getUnderlyingType();
if (BuiltinType->getBuiltinType() != PDB_BuiltinType::Int ||
BuiltinType->getLength() != 4) {
Index: tools/llvm-pdbdump/LLVMOutputStyle.cpp
===================================================================
--- tools/llvm-pdbdump/LLVMOutputStyle.cpp
+++ tools/llvm-pdbdump/LLVMOutputStyle.cpp
@@ -42,7 +42,7 @@
: File(File), P(outs()), TD(&P, false) {}
Error LLVMOutputStyle::dumpFileHeaders() {
- if (!opts::DumpHeaders)
+ if (!opts::raw::DumpHeaders)
return Error::success();
DictScope D(P, "FileHeaders");
@@ -64,7 +64,7 @@
}
Error LLVMOutputStyle::dumpStreamSummary() {
- if (!opts::DumpStreamSummary)
+ if (!opts::raw::DumpStreamSummary)
return Error::success();
// It's OK if we fail to load some of these streams, we still attempt to print
@@ -186,7 +186,7 @@
}
Error LLVMOutputStyle::dumpStreamBlocks() {
- if (!opts::DumpStreamBlocks)
+ if (!opts::raw::DumpStreamBlocks)
return Error::success();
ListScope L(P, "StreamBlocks");
@@ -202,7 +202,7 @@
Error LLVMOutputStyle::dumpStreamData() {
uint32_t StreamCount = File.getNumStreams();
- StringRef DumpStreamStr = opts::DumpStreamDataIdx;
+ StringRef DumpStreamStr = opts::raw::DumpStreamDataIdx;
uint32_t DumpStreamNum;
if (DumpStreamStr.getAsInteger(/*Radix=*/0U, DumpStreamNum))
return Error::success();
@@ -228,7 +228,7 @@
}
Error LLVMOutputStyle::dumpInfoStream() {
- if (!opts::DumpHeaders)
+ if (!opts::raw::DumpHeaders)
return Error::success();
auto IS = File.getPDBInfoStream();
if (!IS)
@@ -243,20 +243,21 @@
}
Error LLVMOutputStyle::dumpNamedStream() {
- if (opts::DumpStreamDataName.empty())
+ if (opts::raw::DumpStreamDataName.empty())
return Error::success();
auto IS = File.getPDBInfoStream();
if (!IS)
return IS.takeError();
- uint32_t NameStreamIndex = IS->getNamedStreamIndex(opts::DumpStreamDataName);
+ uint32_t NameStreamIndex =
+ IS->getNamedStreamIndex(opts::raw::DumpStreamDataName);
if (NameStreamIndex == 0 || NameStreamIndex >= File.getNumStreams())
return make_error<RawError>(raw_error_code::no_stream);
if (NameStreamIndex != 0) {
std::string Name("Stream '");
- Name += opts::DumpStreamDataName;
+ Name += opts::raw::DumpStreamDataName;
Name += "'";
DictScope D(P, Name);
P.printNumber("Index", NameStreamIndex);
@@ -290,7 +291,7 @@
}
static void dumpTpiHash(ScopedPrinter &P, TpiStream &Tpi) {
- if (!opts::DumpTpiHash)
+ if (!opts::raw::DumpTpiHash)
return;
DictScope DD(P, "Hash");
P.printNumber("Number of Hash Buckets", Tpi.NumHashBuckets());
@@ -311,17 +312,17 @@
StringRef Label;
StringRef VerLabel;
if (StreamIdx == StreamTPI) {
- DumpRecordBytes = opts::DumpTpiRecordBytes;
- DumpRecords = opts::DumpTpiRecords;
+ DumpRecordBytes = opts::raw::DumpTpiRecordBytes;
+ DumpRecords = opts::raw::DumpTpiRecords;
Label = "Type Info Stream (TPI)";
VerLabel = "TPI Version";
} else if (StreamIdx == StreamIPI) {
- DumpRecordBytes = opts::DumpIpiRecordBytes;
- DumpRecords = opts::DumpIpiRecords;
+ DumpRecordBytes = opts::raw::DumpIpiRecordBytes;
+ DumpRecords = opts::raw::DumpIpiRecords;
Label = "Type Info Stream (IPI)";
VerLabel = "IPI Version";
}
- if (!DumpRecordBytes && !DumpRecords && !opts::DumpModuleSyms)
+ if (!DumpRecordBytes && !DumpRecords && !opts::raw::DumpModuleSyms)
return Error::success();
auto Tpi = (StreamIdx == StreamTPI) ? File.getPDBTpiStream()
@@ -353,7 +354,7 @@
if (HadError)
return make_error<RawError>(raw_error_code::corrupt_file,
"TPI stream contained corrupt record");
- } else if (opts::DumpModuleSyms) {
+ } else if (opts::raw::DumpModuleSyms) {
// Even if the user doesn't want to dump type records, we still need to
// iterate them in order to build the list of types so that we can print
// them when dumping module symbols. So when they want to dump symbols
@@ -378,9 +379,9 @@
}
Error LLVMOutputStyle::dumpDbiStream() {
- bool DumpModules = opts::DumpModules || opts::DumpModuleSyms ||
- opts::DumpModuleFiles || opts::DumpLineInfo;
- if (!opts::DumpHeaders && !DumpModules)
+ bool DumpModules = opts::raw::DumpModules || opts::raw::DumpModuleSyms ||
+ opts::raw::DumpModuleFiles || opts::raw::DumpLineInfo;
+ if (!opts::raw::DumpHeaders && !DumpModules)
return Error::success();
auto DS = File.getPDBDbiStream();
@@ -424,7 +425,7 @@
P.printNumber("Symbol Byte Size", Modi.Info.getSymbolDebugInfoByteSize());
P.printNumber("Type Server Index", Modi.Info.getTypeServerIndex());
P.printBoolean("Has EC Info", Modi.Info.hasECInfo());
- if (opts::DumpModuleFiles) {
+ if (opts::raw::DumpModuleFiles) {
std::string FileListName =
to_string(Modi.SourceFiles.size()) + " Contributing Source Files";
ListScope LL(P, FileListName);
@@ -434,8 +435,8 @@
bool HasModuleDI =
(Modi.Info.getModuleStreamIndex() < File.getNumStreams());
bool ShouldDumpSymbols =
- (opts::DumpModuleSyms || opts::DumpSymRecordBytes);
- if (HasModuleDI && (ShouldDumpSymbols || opts::DumpLineInfo)) {
+ (opts::raw::DumpModuleSyms || opts::raw::DumpSymRecordBytes);
+ if (HasModuleDI && (ShouldDumpSymbols || opts::raw::DumpLineInfo)) {
auto ModStreamData = MappedBlockStream::createIndexedStream(
Modi.Info.getModuleStreamIndex(), File);
if (!ModStreamData)
@@ -451,9 +452,9 @@
for (const auto &S : ModS.symbols(&HadError)) {
DictScope DD(P, "");
- if (opts::DumpModuleSyms)
+ if (opts::raw::DumpModuleSyms)
SD.dump(S);
- if (opts::DumpSymRecordBytes)
+ if (opts::raw::DumpSymRecordBytes)
P.printBinaryBlock("Bytes", S.Data);
}
if (HadError)
@@ -461,7 +462,7 @@
raw_error_code::corrupt_file,
"DBI stream contained corrupt symbol record");
}
- if (opts::DumpLineInfo) {
+ if (opts::raw::DumpLineInfo) {
ListScope SS(P, "LineInfo");
bool HadError = false;
// Define a locally scoped visitor to print the different
@@ -561,7 +562,7 @@
}
Error LLVMOutputStyle::dumpSectionContribs() {
- if (!opts::DumpSectionContribs)
+ if (!opts::raw::DumpSectionContribs)
return Error::success();
auto Dbi = File.getPDBDbiStream();
@@ -608,7 +609,7 @@
}
Error LLVMOutputStyle::dumpSectionMap() {
- if (!opts::DumpSectionMap)
+ if (!opts::raw::DumpSectionMap)
return Error::success();
auto Dbi = File.getPDBDbiStream();
@@ -633,7 +634,7 @@
}
Error LLVMOutputStyle::dumpPublicsStream() {
- if (!opts::DumpPublics)
+ if (!opts::raw::DumpPublics)
return Error::success();
DictScope D(P, "Publics Stream");
@@ -661,7 +662,7 @@
DictScope DD(P, "");
SD.dump(S);
- if (opts::DumpSymRecordBytes)
+ if (opts::raw::DumpSymRecordBytes)
P.printBinaryBlock("Bytes", S.Data);
}
if (HadError)
@@ -673,7 +674,7 @@
}
Error LLVMOutputStyle::dumpSectionHeaders() {
- if (!opts::DumpSectionHeaders)
+ if (!opts::raw::DumpSectionHeaders)
return Error::success();
auto Dbi = File.getPDBDbiStream();
@@ -702,7 +703,7 @@
}
Error LLVMOutputStyle::dumpFpoStream() {
- if (!opts::DumpFpo)
+ if (!opts::raw::DumpFpo)
return Error::success();
auto Dbi = File.getPDBDbiStream();
Index: tools/llvm-pdbdump/LinePrinter.cpp
===================================================================
--- tools/llvm-pdbdump/LinePrinter.cpp
+++ tools/llvm-pdbdump/LinePrinter.cpp
@@ -44,19 +44,19 @@
LinePrinter::LinePrinter(int Indent, llvm::raw_ostream &Stream)
: OS(Stream), IndentSpaces(Indent), CurrentIndent(0) {
- SetFilters(ExcludeTypeFilters, opts::ExcludeTypes.begin(),
- opts::ExcludeTypes.end());
- SetFilters(ExcludeSymbolFilters, opts::ExcludeSymbols.begin(),
- opts::ExcludeSymbols.end());
- SetFilters(ExcludeCompilandFilters, opts::ExcludeCompilands.begin(),
- opts::ExcludeCompilands.end());
-
- SetFilters(IncludeTypeFilters, opts::IncludeTypes.begin(),
- opts::IncludeTypes.end());
- SetFilters(IncludeSymbolFilters, opts::IncludeSymbols.begin(),
- opts::IncludeSymbols.end());
- SetFilters(IncludeCompilandFilters, opts::IncludeCompilands.begin(),
- opts::IncludeCompilands.end());
+ SetFilters(ExcludeTypeFilters, opts::pretty::ExcludeTypes.begin(),
+ opts::pretty::ExcludeTypes.end());
+ SetFilters(ExcludeSymbolFilters, opts::pretty::ExcludeSymbols.begin(),
+ opts::pretty::ExcludeSymbols.end());
+ SetFilters(ExcludeCompilandFilters, opts::pretty::ExcludeCompilands.begin(),
+ opts::pretty::ExcludeCompilands.end());
+
+ SetFilters(IncludeTypeFilters, opts::pretty::IncludeTypes.begin(),
+ opts::pretty::IncludeTypes.end());
+ SetFilters(IncludeSymbolFilters, opts::pretty::IncludeSymbols.begin(),
+ opts::pretty::IncludeSymbols.end());
+ SetFilters(IncludeCompilandFilters, opts::pretty::IncludeCompilands.begin(),
+ opts::pretty::IncludeCompilands.end());
}
void LinePrinter::Indent() { CurrentIndent += IndentSpaces; }
Index: tools/llvm-pdbdump/TypeDumper.cpp
===================================================================
--- tools/llvm-pdbdump/TypeDumper.cpp
+++ tools/llvm-pdbdump/TypeDumper.cpp
@@ -88,7 +88,7 @@
Printer.NewLine();
- if (opts::NoClassDefs) {
+ if (opts::pretty::NoClassDefs) {
WithColor(Printer, PDB_ColorItem::Keyword).get() << "class ";
WithColor(Printer, PDB_ColorItem::Identifier).get() << Symbol.getName();
} else {
Index: tools/llvm-pdbdump/VariableDumper.cpp
===================================================================
--- tools/llvm-pdbdump/VariableDumper.cpp
+++ tools/llvm-pdbdump/VariableDumper.cpp
@@ -33,7 +33,7 @@
: PDBSymDumper(true), Printer(P) {}
void VariableDumper::start(const PDBSymbolData &Var) {
- if (Var.isCompilerGenerated() && opts::ExcludeCompilerGenerated)
+ if (Var.isCompilerGenerated() && opts::pretty::ExcludeCompilerGenerated)
return;
if (Printer.IsSymbolExcluded(Var.getName()))
return;
Index: tools/llvm-pdbdump/YAMLOutputStyle.cpp
===================================================================
--- tools/llvm-pdbdump/YAMLOutputStyle.cpp
+++ tools/llvm-pdbdump/YAMLOutputStyle.cpp
@@ -20,7 +20,7 @@
YAMLOutputStyle::YAMLOutputStyle(PDBFile &File) : File(File), Out(outs()) {}
Error YAMLOutputStyle::dumpFileHeaders() {
- if (!opts::DumpHeaders)
+ if (!opts::raw::DumpHeaders)
return Error::success();
yaml::MsfHeaders Headers;
@@ -41,7 +41,7 @@
}
Error YAMLOutputStyle::dumpStreamSummary() {
- if (!opts::DumpStreamSummary)
+ if (!opts::raw::DumpStreamSummary)
return Error::success();
Obj.StreamSizes = File.getStreamSizes();
@@ -49,7 +49,7 @@
}
Error YAMLOutputStyle::dumpStreamBlocks() {
- if (!opts::DumpStreamBlocks)
+ if (!opts::raw::DumpStreamBlocks)
return Error::success();
auto StreamMap = File.getStreamMap();
@@ -65,7 +65,7 @@
Error YAMLOutputStyle::dumpStreamData() {
uint32_t StreamCount = File.getNumStreams();
- StringRef DumpStreamStr = opts::DumpStreamDataIdx;
+ StringRef DumpStreamStr = opts::raw::DumpStreamDataIdx;
uint32_t DumpStreamNum;
if (DumpStreamStr.getAsInteger(/*Radix=*/0U, DumpStreamNum) ||
DumpStreamNum >= StreamCount)
@@ -75,13 +75,13 @@
}
Error YAMLOutputStyle::dumpInfoStream() {
- if (!opts::DumpHeaders)
+ if (!opts::raw::DumpHeaders)
return Error::success();
return Error::success();
}
Error YAMLOutputStyle::dumpNamedStream() {
- if (opts::DumpStreamDataName.empty())
+ if (opts::raw::DumpStreamDataName.empty())
return Error::success();
return Error::success();
@@ -94,35 +94,35 @@
Error YAMLOutputStyle::dumpDbiStream() { return Error::success(); }
Error YAMLOutputStyle::dumpSectionContribs() {
- if (!opts::DumpSectionContribs)
+ if (!opts::raw::DumpSectionContribs)
return Error::success();
return Error::success();
}
Error YAMLOutputStyle::dumpSectionMap() {
- if (!opts::DumpSectionMap)
+ if (!opts::raw::DumpSectionMap)
return Error::success();
return Error::success();
}
Error YAMLOutputStyle::dumpPublicsStream() {
- if (!opts::DumpPublics)
+ if (!opts::raw::DumpPublics)
return Error::success();
return Error::success();
}
Error YAMLOutputStyle::dumpSectionHeaders() {
- if (!opts::DumpSectionHeaders)
+ if (!opts::raw::DumpSectionHeaders)
return Error::success();
return Error::success();
}
Error YAMLOutputStyle::dumpFpoStream() {
- if (!opts::DumpFpo)
+ if (!opts::raw::DumpFpo)
return Error::success();
return Error::success();
Index: tools/llvm-pdbdump/llvm-pdbdump.h
===================================================================
--- tools/llvm-pdbdump/llvm-pdbdump.h
+++ tools/llvm-pdbdump/llvm-pdbdump.h
@@ -15,15 +15,25 @@
namespace opts {
-enum OutputStyleTy { LLVM, YAML };
-
+namespace pretty {
extern llvm::cl::opt<bool> Compilands;
extern llvm::cl::opt<bool> Symbols;
extern llvm::cl::opt<bool> Globals;
extern llvm::cl::opt<bool> Types;
extern llvm::cl::opt<bool> All;
+extern llvm::cl::opt<bool> ExcludeCompilerGenerated;
+
+extern llvm::cl::opt<bool> NoClassDefs;
+extern llvm::cl::opt<bool> NoEnumDefs;
+extern llvm::cl::list<std::string> ExcludeTypes;
+extern llvm::cl::list<std::string> ExcludeSymbols;
+extern llvm::cl::list<std::string> ExcludeCompilands;
+extern llvm::cl::list<std::string> IncludeTypes;
+extern llvm::cl::list<std::string> IncludeSymbols;
+extern llvm::cl::list<std::string> IncludeCompilands;
+}
-extern llvm::cl::opt<OutputStyleTy> RawOutputStyle;
+namespace raw {
extern llvm::cl::opt<bool> DumpHeaders;
extern llvm::cl::opt<bool> DumpStreamBlocks;
extern llvm::cl::opt<bool> DumpStreamSummary;
@@ -44,17 +54,7 @@
extern llvm::cl::opt<bool> DumpSymRecordBytes;
extern llvm::cl::opt<bool> DumpSectionHeaders;
extern llvm::cl::opt<bool> DumpFpo;
-
-extern llvm::cl::opt<bool> ExcludeCompilerGenerated;
-
-extern llvm::cl::opt<bool> NoClassDefs;
-extern llvm::cl::opt<bool> NoEnumDefs;
-extern llvm::cl::list<std::string> ExcludeTypes;
-extern llvm::cl::list<std::string> ExcludeSymbols;
-extern llvm::cl::list<std::string> ExcludeCompilands;
-extern llvm::cl::list<std::string> IncludeTypes;
-extern llvm::cl::list<std::string> IncludeSymbols;
-extern llvm::cl::list<std::string> IncludeCompilands;
+}
}
#endif
Index: tools/llvm-pdbdump/llvm-pdbdump.cpp
===================================================================
--- tools/llvm-pdbdump/llvm-pdbdump.cpp
+++ tools/llvm-pdbdump/llvm-pdbdump.cpp
@@ -79,155 +79,191 @@
namespace opts {
-enum class PDB_DumpType { ByType, ByObjFile, Both };
-
-cl::list<std::string> InputFilenames(cl::Positional,
- cl::desc("<input PDB files>"),
- cl::OneOrMore);
+cl::SubCommand RawSubcommand("raw", "Dump raw structure of the PDB file");
+cl::SubCommand
+ PrettySubcommand("pretty",
+ "Dump semantic information about types and symbols");
+cl::SubCommand YamlToPdbSubcommand("yaml2pdb", "Generate YAML from a PDB File");
+cl::SubCommand
+ PdbToYamlSubcommand("pdb2yaml",
+ "Generate a PDB file from a YAML description");
cl::OptionCategory TypeCategory("Symbol Type Options");
cl::OptionCategory FilterCategory("Filtering Options");
cl::OptionCategory OtherOptions("Other Options");
cl::OptionCategory NativeOptions("Native Options");
+namespace pretty {
+cl::list<std::string> InputFilenames(cl::Positional,
+ cl::desc("<input PDB files>"),
+ cl::OneOrMore, cl::sub(PrettySubcommand));
+
cl::opt<bool> Compilands("compilands", cl::desc("Display compilands"),
- cl::cat(TypeCategory));
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
cl::opt<bool> Symbols("symbols", cl::desc("Display symbols for each compiland"),
- cl::cat(TypeCategory));
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
cl::opt<bool> Globals("globals", cl::desc("Dump global symbols"),
- cl::cat(TypeCategory));
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
cl::opt<bool> Externals("externals", cl::desc("Dump external symbols"),
- cl::cat(TypeCategory));
-cl::opt<bool> Types("types", cl::desc("Display types"), cl::cat(TypeCategory));
-cl::opt<bool> Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory));
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> Types("types", cl::desc("Display types"), cl::cat(TypeCategory),
+ cl::sub(PrettySubcommand));
+cl::opt<bool> Lines("lines", cl::desc("Line tables"), cl::cat(TypeCategory),
+ cl::sub(PrettySubcommand));
cl::opt<bool>
All("all", cl::desc("Implies all other options in 'Symbol Types' category"),
- cl::cat(TypeCategory));
+ cl::cat(TypeCategory), cl::sub(PrettySubcommand));
cl::opt<uint64_t> LoadAddress(
"load-address",
cl::desc("Assume the module is loaded at the specified address"),
- cl::cat(OtherOptions));
+ cl::cat(OtherOptions), cl::sub(PrettySubcommand));
+cl::list<std::string> ExcludeTypes(
+ "exclude-types", cl::desc("Exclude types by regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::list<std::string> ExcludeSymbols(
+ "exclude-symbols", cl::desc("Exclude symbols by regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::list<std::string> ExcludeCompilands(
+ "exclude-compilands", cl::desc("Exclude compilands by regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
-cl::opt<OutputStyleTy>
- RawOutputStyle("raw-output-style", cl::desc("Specify dump outpout style"),
- cl::values(clEnumVal(LLVM, "LLVM default style"),
- clEnumVal(YAML, "YAML style"), clEnumValEnd),
- cl::init(LLVM), cl::cat(NativeOptions));
+cl::list<std::string> IncludeTypes(
+ "include-types",
+ cl::desc("Include only types which match a regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::list<std::string> IncludeSymbols(
+ "include-symbols",
+ cl::desc("Include only symbols which match a regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::list<std::string> IncludeCompilands(
+ "include-compilands",
+ cl::desc("Include only compilands those which match a regular expression"),
+ cl::ZeroOrMore, cl::cat(FilterCategory), cl::sub(PrettySubcommand));
-cl::opt<bool> DumpHeaders("raw-headers", cl::desc("dump PDB headers"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpStreamBlocks("raw-stream-blocks",
+cl::opt<bool> ExcludeCompilerGenerated(
+ "no-compiler-generated",
+ cl::desc("Don't show compiler generated types and symbols"),
+ cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::opt<bool>
+ ExcludeSystemLibraries("no-system-libs",
+ cl::desc("Don't show symbols from system libraries"),
+ cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> NoClassDefs("no-class-definitions",
+ cl::desc("Don't display full class definitions"),
+ cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+cl::opt<bool> NoEnumDefs("no-enum-definitions",
+ cl::desc("Don't display full enum definitions"),
+ cl::cat(FilterCategory), cl::sub(PrettySubcommand));
+}
+
+namespace raw {
+
+cl::opt<bool> DumpHeaders("headers", cl::desc("dump PDB headers"),
+ cl::cat(NativeOptions), cl::sub(RawSubcommand),
+ cl::sub(RawSubcommand), cl::sub(PdbToYamlSubcommand));
+cl::opt<bool> DumpStreamBlocks("stream-blocks",
cl::desc("dump PDB stream blocks"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpStreamSummary("raw-stream-summary",
+ cl::cat(NativeOptions), cl::sub(RawSubcommand),
+ cl::sub(PdbToYamlSubcommand));
+cl::opt<bool> DumpStreamSummary("stream-summary",
cl::desc("dump summary of the PDB streams"),
- cl::cat(NativeOptions));
+ cl::cat(NativeOptions), cl::sub(RawSubcommand),
+ cl::sub(PdbToYamlSubcommand));
cl::opt<bool>
- DumpTpiRecords("raw-tpi-records",
+ DumpTpiRecords("tpi-records",
cl::desc("dump CodeView type records from TPI stream"),
- cl::cat(NativeOptions));
+ cl::cat(NativeOptions), cl::sub(RawSubcommand),
+ cl::sub(PdbToYamlSubcommand));
cl::opt<bool> DumpTpiRecordBytes(
- "raw-tpi-record-bytes",
+ "tpi-record-bytes",
cl::desc("dump CodeView type record raw bytes from TPI stream"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpTpiHash("raw-tpi-hash",
- cl::desc("dump CodeView TPI hash stream"),
- cl::cat(NativeOptions));
+ cl::cat(NativeOptions), cl::sub(RawSubcommand),
+ cl::sub(PdbToYamlSubcommand));
+cl::opt<bool> DumpTpiHash("tpi-hash", cl::desc("dump CodeView TPI hash stream"),
+ cl::cat(NativeOptions), cl::sub(RawSubcommand),
+ cl::sub(PdbToYamlSubcommand));
cl::opt<bool>
- DumpIpiRecords("raw-ipi-records",
+ DumpIpiRecords("ipi-records",
cl::desc("dump CodeView type records from IPI stream"),
- cl::cat(NativeOptions));
+ cl::cat(NativeOptions), cl::sub(RawSubcommand),
+ cl::sub(PdbToYamlSubcommand));
cl::opt<bool> DumpIpiRecordBytes(
- "raw-ipi-record-bytes",
+ "ipi-record-bytes",
cl::desc("dump CodeView type record raw bytes from IPI stream"),
- cl::cat(NativeOptions));
-cl::opt<std::string> DumpStreamDataIdx("raw-stream",
- cl::desc("dump stream data"),
- cl::cat(NativeOptions));
-cl::opt<std::string> DumpStreamDataName("raw-stream-name",
+ cl::cat(NativeOptions), cl::sub(RawSubcommand));
+cl::opt<std::string> DumpStreamDataIdx("stream", cl::desc("dump stream data"),
+ cl::cat(NativeOptions),
+ cl::sub(RawSubcommand),
+ cl::sub(PdbToYamlSubcommand));
+cl::opt<std::string> DumpStreamDataName("stream-name",
cl::desc("dump stream data"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpModules("raw-modules", cl::desc("dump compiland information"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpModuleFiles("raw-module-files",
- cl::desc("dump file information"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpModuleSyms("raw-module-syms", cl::desc("dump module symbols"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpPublics("raw-publics", cl::desc("dump Publics stream data"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpSectionContribs("raw-section-contribs",
+ cl::cat(NativeOptions),
+ cl::sub(RawSubcommand),
+ cl::sub(PdbToYamlSubcommand));
+cl::opt<bool> DumpModules("modules", cl::desc("dump compiland information"),
+ cl::cat(NativeOptions), cl::sub(RawSubcommand),
+ cl::sub(PdbToYamlSubcommand));
+cl::opt<bool> DumpModuleFiles("module-files", cl::desc("dump file information"),
+ cl::cat(NativeOptions), cl::sub(RawSubcommand),
+ cl::sub(PdbToYamlSubcommand));
+cl::opt<bool> DumpModuleSyms("module-syms", cl::desc("dump module symbols"),
+ cl::cat(NativeOptions), cl::sub(RawSubcommand),
+ cl::sub(PdbToYamlSubcommand));
+cl::opt<bool> DumpPublics("publics", cl::desc("dump Publics stream data"),
+ cl::cat(NativeOptions), cl::sub(RawSubcommand),
+ cl::sub(PdbToYamlSubcommand));
+cl::opt<bool> DumpSectionContribs("section-contribs",
cl::desc("dump section contributions"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpLineInfo("raw-line-info",
+ cl::cat(NativeOptions),
+ cl::sub(RawSubcommand),
+ cl::sub(PdbToYamlSubcommand));
+cl::opt<bool> DumpLineInfo("line-info",
cl::desc("dump file and line information"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpSectionMap("raw-section-map", cl::desc("dump section map"),
- cl::cat(NativeOptions));
+ cl::cat(NativeOptions), cl::sub(RawSubcommand),
+ cl::sub(PdbToYamlSubcommand));
+cl::opt<bool> DumpSectionMap("section-map", cl::desc("dump section map"),
+ cl::cat(NativeOptions), cl::sub(RawSubcommand),
+ cl::sub(PdbToYamlSubcommand));
cl::opt<bool>
- DumpSymRecordBytes("raw-sym-record-bytes",
+ DumpSymRecordBytes("sym-record-bytes",
cl::desc("dump CodeView symbol record raw bytes"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpSectionHeaders("raw-section-headers",
+ cl::cat(NativeOptions), cl::sub(RawSubcommand),
+ cl::sub(PdbToYamlSubcommand));
+cl::opt<bool> DumpSectionHeaders("section-headers",
cl::desc("dump section headers"),
- cl::cat(NativeOptions));
-cl::opt<bool> DumpFpo("raw-fpo", cl::desc("dump FPO records"),
- cl::cat(NativeOptions));
+ cl::cat(NativeOptions),
+ cl::sub(RawSubcommand));
+cl::opt<bool> DumpFpo("fpo", cl::desc("dump FPO records"),
+ cl::cat(NativeOptions), cl::sub(RawSubcommand),
+ cl::sub(PdbToYamlSubcommand));
cl::opt<bool>
- RawAll("raw-all",
+ RawAll("all",
cl::desc("Implies most other options in 'Native Options' category"),
- cl::cat(NativeOptions));
+ cl::cat(NativeOptions), cl::sub(RawSubcommand),
+ cl::sub(PdbToYamlSubcommand));
-cl::opt<bool>
- YamlToPdb("yaml-to-pdb",
- cl::desc("The input file is yaml, and the tool outputs a pdb"),
- cl::cat(NativeOptions));
-cl::opt<std::string> YamlPdbOutputFile(
- "pdb-output", cl::desc("When yaml-to-pdb is specified, the output file"),
- cl::cat(NativeOptions));
-
-cl::list<std::string>
- ExcludeTypes("exclude-types",
- cl::desc("Exclude types by regular expression"),
- cl::ZeroOrMore, cl::cat(FilterCategory));
-cl::list<std::string>
- ExcludeSymbols("exclude-symbols",
- cl::desc("Exclude symbols by regular expression"),
- cl::ZeroOrMore, cl::cat(FilterCategory));
-cl::list<std::string>
- ExcludeCompilands("exclude-compilands",
- cl::desc("Exclude compilands by regular expression"),
- cl::ZeroOrMore, cl::cat(FilterCategory));
+cl::list<std::string> InputFilenames(cl::Positional,
+ cl::desc("<input PDB files>"),
+ cl::OneOrMore, cl::sub(RawSubcommand));
+}
-cl::list<std::string> IncludeTypes(
- "include-types",
- cl::desc("Include only types which match a regular expression"),
- cl::ZeroOrMore, cl::cat(FilterCategory));
-cl::list<std::string> IncludeSymbols(
- "include-symbols",
- cl::desc("Include only symbols which match a regular expression"),
- cl::ZeroOrMore, cl::cat(FilterCategory));
-cl::list<std::string> IncludeCompilands(
- "include-compilands",
- cl::desc("Include only compilands those which match a regular expression"),
- cl::ZeroOrMore, cl::cat(FilterCategory));
+namespace yaml2pdb {
+cl::opt<std::string>
+ YamlPdbOutputFile("pdb", cl::desc("the name of the PDB file to write"),
+ cl::cat(NativeOptions), cl::sub(YamlToPdbSubcommand));
-cl::opt<bool> ExcludeCompilerGenerated(
- "no-compiler-generated",
- cl::desc("Don't show compiler generated types and symbols"),
- cl::cat(FilterCategory));
-cl::opt<bool>
- ExcludeSystemLibraries("no-system-libs",
- cl::desc("Don't show symbols from system libraries"),
- cl::cat(FilterCategory));
-cl::opt<bool> NoClassDefs("no-class-definitions",
- cl::desc("Don't display full class definitions"),
- cl::cat(FilterCategory));
-cl::opt<bool> NoEnumDefs("no-enum-definitions",
- cl::desc("Don't display full enum definitions"),
- cl::cat(FilterCategory));
+cl::list<std::string> InputFilename(cl::Positional,
+ cl::desc("<input YAML file>"), cl::Required,
+ cl::sub(YamlToPdbSubcommand));
+}
+
+namespace pdb2yaml {
+cl::list<std::string> InputFilename(cl::Positional,
+ cl::desc("<input PDB file>"), cl::Required,
+ cl::sub(PdbToYamlSubcommand));
+}
}
static ExitOnError ExitOnErr;
@@ -235,13 +271,10 @@
static Error dumpStructure(RawSession &RS) {
PDBFile &File = RS.getPDBFile();
std::unique_ptr<OutputStyle> O;
- if (opts::RawOutputStyle == opts::OutputStyleTy::LLVM)
- O = llvm::make_unique<LLVMOutputStyle>(File);
- else if (opts::RawOutputStyle == opts::OutputStyleTy::YAML)
+ if (opts::PdbToYamlSubcommand)
O = llvm::make_unique<YAMLOutputStyle>(File);
else
- return make_error<RawError>(raw_error_code::feature_unsupported,
- "Requested output style unsupported");
+ O = llvm::make_unique<LLVMOutputStyle>(File);
if (auto EC = O->dumpFileHeaders())
return EC;
@@ -289,45 +322,45 @@
}
bool isRawDumpEnabled() {
- if (opts::DumpHeaders)
+ if (opts::raw::DumpHeaders)
return true;
- if (opts::DumpModules)
+ if (opts::raw::DumpModules)
return true;
- if (opts::DumpModuleFiles)
+ if (opts::raw::DumpModuleFiles)
return true;
- if (opts::DumpModuleSyms)
+ if (opts::raw::DumpModuleSyms)
return true;
- if (!opts::DumpStreamDataIdx.empty())
+ if (!opts::raw::DumpStreamDataIdx.empty())
return true;
- if (!opts::DumpStreamDataName.empty())
+ if (!opts::raw::DumpStreamDataName.empty())
return true;
- if (opts::DumpPublics)
+ if (opts::raw::DumpPublics)
return true;
- if (opts::DumpStreamSummary)
+ if (opts::raw::DumpStreamSummary)
return true;
- if (opts::DumpStreamBlocks)
+ if (opts::raw::DumpStreamBlocks)
return true;
- if (opts::DumpSymRecordBytes)
+ if (opts::raw::DumpSymRecordBytes)
return true;
- if (opts::DumpTpiRecordBytes)
+ if (opts::raw::DumpTpiRecordBytes)
return true;
- if (opts::DumpTpiRecords)
+ if (opts::raw::DumpTpiRecords)
return true;
- if (opts::DumpTpiHash)
+ if (opts::raw::DumpTpiHash)
return true;
- if (opts::DumpIpiRecords)
+ if (opts::raw::DumpIpiRecords)
return true;
- if (opts::DumpIpiRecordBytes)
+ if (opts::raw::DumpIpiRecordBytes)
return true;
- if (opts::DumpSectionHeaders)
+ if (opts::raw::DumpSectionHeaders)
return true;
- if (opts::DumpSectionContribs)
+ if (opts::raw::DumpSectionContribs)
return true;
- if (opts::DumpSectionMap)
+ if (opts::raw::DumpSectionMap)
return true;
- if (opts::DumpLineInfo)
+ if (opts::raw::DumpLineInfo)
return true;
- if (opts::DumpFpo)
+ if (opts::raw::DumpFpo)
return true;
return false;
}
@@ -347,11 +380,11 @@
pdb::yaml::PdbObject YamlObj;
In >> YamlObj;
- auto OutFileOrError = FileOutputBuffer::create(opts::YamlPdbOutputFile,
- YamlObj.Headers.FileSize);
+ auto OutFileOrError = FileOutputBuffer::create(
+ opts::yaml2pdb::YamlPdbOutputFile, YamlObj.Headers.FileSize);
if (OutFileOrError.getError())
ExitOnErr(make_error<GenericError>(generic_error_code::invalid_path,
- opts::YamlPdbOutputFile));
+ opts::yaml2pdb::YamlPdbOutputFile));
auto FileByteStream =
llvm::make_unique<FileBufferByteStream>(std::move(*OutFileOrError));
@@ -371,20 +404,21 @@
Pdb.commit();
}
-static void dumpInput(StringRef Path) {
+static void dumpRaw(StringRef Path) {
std::unique_ptr<IPDBSession> Session;
- if (isRawDumpEnabled()) {
- ExitOnErr(loadDataForPDB(PDB_ReaderType::Raw, Path, Session));
+ ExitOnErr(loadDataForPDB(PDB_ReaderType::Raw, Path, Session));
- RawSession *RS = static_cast<RawSession *>(Session.get());
- ExitOnErr(dumpStructure(*RS));
- return;
- }
+ RawSession *RS = static_cast<RawSession *>(Session.get());
+ ExitOnErr(dumpStructure(*RS));
+}
+
+static void dumpPretty(StringRef Path) {
+ std::unique_ptr<IPDBSession> Session;
ExitOnErr(loadDataForPDB(PDB_ReaderType::DIA, Path, Session));
- if (opts::LoadAddress)
- Session->setLoadAddress(opts::LoadAddress);
+ if (opts::pretty::LoadAddress)
+ Session->setLoadAddress(opts::pretty::LoadAddress);
LinePrinter Printer(2, outs());
@@ -421,7 +455,7 @@
outs() << "HasPrivateSymbols ";
Printer.Unindent();
- if (opts::Compilands) {
+ if (opts::pretty::Compilands) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::SectionHeader).get()
<< "---COMPILANDS---";
@@ -429,14 +463,14 @@
auto Compilands = GlobalScope->findAllChildren<PDBSymbolCompiland>();
CompilandDumper Dumper(Printer);
CompilandDumpFlags options = CompilandDumper::Flags::None;
- if (opts::Lines)
+ if (opts::pretty::Lines)
options = options | CompilandDumper::Flags::Lines;
while (auto Compiland = Compilands->getNext())
Dumper.start(*Compiland, options);
Printer.Unindent();
}
- if (opts::Types) {
+ if (opts::pretty::Types) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---TYPES---";
Printer.Indent();
@@ -445,7 +479,7 @@
Printer.Unindent();
}
- if (opts::Symbols) {
+ if (opts::pretty::Symbols) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---SYMBOLS---";
Printer.Indent();
@@ -456,7 +490,7 @@
Printer.Unindent();
}
- if (opts::Globals) {
+ if (opts::pretty::Globals) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---GLOBALS---";
Printer.Indent();
@@ -482,14 +516,14 @@
}
Printer.Unindent();
}
- if (opts::Externals) {
+ if (opts::pretty::Externals) {
Printer.NewLine();
WithColor(Printer, PDB_ColorItem::SectionHeader).get() << "---EXTERNALS---";
Printer.Indent();
ExternalSymbolDumper Dumper(Printer);
Dumper.start(*GlobalScope);
}
- if (opts::Lines) {
+ if (opts::pretty::Lines) {
Printer.NewLine();
}
outs().flush();
@@ -510,60 +544,68 @@
llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
cl::ParseCommandLineOptions(argv.size(), argv.data(), "LLVM PDB Dumper\n");
- if (opts::Lines)
- opts::Compilands = true;
-
- if (opts::All) {
- opts::Compilands = true;
- opts::Symbols = true;
- opts::Globals = true;
- opts::Types = true;
- opts::Externals = true;
- opts::Lines = true;
- }
- if (opts::RawAll) {
- opts::DumpHeaders = true;
- opts::DumpModules = true;
- opts::DumpModuleFiles = true;
- opts::DumpModuleSyms = true;
- opts::DumpPublics = true;
- opts::DumpSectionHeaders = true;
- opts::DumpStreamSummary = true;
- opts::DumpStreamBlocks = true;
- opts::DumpTpiRecords = true;
- opts::DumpTpiHash = true;
- opts::DumpIpiRecords = true;
- opts::DumpSectionMap = true;
- opts::DumpSectionContribs = true;
- opts::DumpLineInfo = true;
- opts::DumpFpo = true;
- }
-
- // When adding filters for excluded compilands and types, we need to remember
- // that these are regexes. So special characters such as * and \ need to be
- // escaped in the regex. In the case of a literal \, this means it needs to
- // be escaped again in the C++. So matching a single \ in the input requires
- // 4 \es in the C++.
- if (opts::ExcludeCompilerGenerated) {
- opts::ExcludeTypes.push_back("__vc_attributes");
- opts::ExcludeCompilands.push_back("\\* Linker \\*");
- }
- if (opts::ExcludeSystemLibraries) {
- opts::ExcludeCompilands.push_back(
- "f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld");
- opts::ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt");
- opts::ExcludeCompilands.push_back("d:\\\\th.obj.x86fre\\\\minkernel");
+ // These options are shared by two subcommands.
+ if ((opts::PdbToYamlSubcommand || opts::RawSubcommand) && opts::raw::RawAll) {
+ opts::raw::DumpHeaders = true;
+ opts::raw::DumpModules = true;
+ opts::raw::DumpModuleFiles = true;
+ opts::raw::DumpModuleSyms = true;
+ opts::raw::DumpPublics = true;
+ opts::raw::DumpSectionHeaders = true;
+ opts::raw::DumpStreamSummary = true;
+ opts::raw::DumpStreamBlocks = true;
+ opts::raw::DumpTpiRecords = true;
+ opts::raw::DumpTpiHash = true;
+ opts::raw::DumpIpiRecords = true;
+ opts::raw::DumpSectionMap = true;
+ opts::raw::DumpSectionContribs = true;
+ opts::raw::DumpLineInfo = true;
+ opts::raw::DumpFpo = true;
}
llvm::sys::InitializeCOMRAII COM(llvm::sys::COMThreadingMode::MultiThreaded);
- if (opts::YamlToPdb) {
- std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(),
- yamlToPdb);
- } else {
- std::for_each(opts::InputFilenames.begin(), opts::InputFilenames.end(),
- dumpInput);
+ if (opts::PdbToYamlSubcommand) {
+ dumpRaw(opts::pdb2yaml::InputFilename.front());
+ } else if (opts::YamlToPdbSubcommand) {
+ yamlToPdb(opts::yaml2pdb::InputFilename.front());
+ } else if (opts::PrettySubcommand) {
+ if (opts::pretty::Lines)
+ opts::pretty::Compilands = true;
+
+ if (opts::pretty::All) {
+ opts::pretty::Compilands = true;
+ opts::pretty::Symbols = true;
+ opts::pretty::Globals = true;
+ opts::pretty::Types = true;
+ opts::pretty::Externals = true;
+ opts::pretty::Lines = true;
+ }
+
+ // When adding filters for excluded compilands and types, we need to
+ // remember
+ // that these are regexes. So special characters such as * and \ need to be
+ // escaped in the regex. In the case of a literal \, this means it needs to
+ // be escaped again in the C++. So matching a single \ in the input
+ // requires
+ // 4 \es in the C++.
+ if (opts::pretty::ExcludeCompilerGenerated) {
+ opts::pretty::ExcludeTypes.push_back("__vc_attributes");
+ opts::pretty::ExcludeCompilands.push_back("\\* Linker \\*");
+ }
+ if (opts::pretty::ExcludeSystemLibraries) {
+ opts::pretty::ExcludeCompilands.push_back(
+ "f:\\\\binaries\\\\Intermediate\\\\vctools\\\\crt_bld");
+ opts::pretty::ExcludeCompilands.push_back("f:\\\\dd\\\\vctools\\\\crt");
+ opts::pretty::ExcludeCompilands.push_back(
+ "d:\\\\th.obj.x86fre\\\\minkernel");
+ }
+ std::for_each(opts::pretty::InputFilenames.begin(),
+ opts::pretty::InputFilenames.end(), dumpPretty);
+ } else if (opts::RawSubcommand) {
+ std::for_each(opts::raw::InputFilenames.begin(),
+ opts::raw::InputFilenames.end(), dumpRaw);
}
outs().flush();
Index: unittests/Support/CommandLineTest.cpp
===================================================================
--- unittests/Support/CommandLineTest.cpp
+++ unittests/Support/CommandLineTest.cpp
@@ -78,7 +78,8 @@
const char ArgString[] = "new-test-option";
const char ValueString[] = "Integer";
- StringMap<cl::Option *> &Map = cl::getRegisteredOptions();
+ StringMap<cl::Option *> &Map =
+ cl::getRegisteredOptions(*cl::TopLevelSubCommand);
ASSERT_TRUE(Map.count("test-option") == 1) <<
"Could not find option in map.";
@@ -237,7 +238,8 @@
ASSERT_EQ(cl::NotHidden, TestOption2.getOptionHiddenFlag())
<< "Hid extra option that should be visable.";
- StringMap<cl::Option *> &Map = cl::getRegisteredOptions();
+ StringMap<cl::Option *> &Map =
+ cl::getRegisteredOptions(*cl::TopLevelSubCommand);
ASSERT_EQ(cl::NotHidden, Map["help"]->getOptionHiddenFlag())
<< "Hid default option that should be visable.";
}
@@ -261,7 +263,8 @@
ASSERT_EQ(cl::NotHidden, TestOption3.getOptionHiddenFlag())
<< "Hid extra option that should be visable.";
- StringMap<cl::Option *> &Map = cl::getRegisteredOptions();
+ StringMap<cl::Option *> &Map =
+ cl::getRegisteredOptions(*cl::TopLevelSubCommand);
ASSERT_EQ(cl::NotHidden, Map["help"]->getOptionHiddenFlag())
<< "Hid default option that should be visable.";
}
Index: unittests/Support/ProgramTest.cpp
===================================================================
--- unittests/Support/ProgramTest.cpp
+++ unittests/Support/ProgramTest.cpp
@@ -231,7 +231,7 @@
// LoopCount should only be incremented once.
while (true) {
++LoopCount;
- ProcessInfo WaitResult = Wait(PI1, 0, true, &Error);
+ ProcessInfo WaitResult = llvm::sys::Wait(PI1, 0, true, &Error);
ASSERT_TRUE(Error.empty());
if (WaitResult.Pid == PI1.Pid)
break;
@@ -248,7 +248,7 @@
// cse, LoopCount should be greater than 1 (more than one increment occurs).
while (true) {
++LoopCount;
- ProcessInfo WaitResult = Wait(PI2, 0, false, &Error);
+ ProcessInfo WaitResult = llvm::sys::Wait(PI2, 0, false, &Error);
ASSERT_TRUE(Error.empty());
if (WaitResult.Pid == PI2.Pid)
break;

Event Timeline