aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Support/CommandLine.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:04 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-11 12:38:11 +0000
commite3b557809604d036af6e00c60f012c2025b59a5e (patch)
tree8a11ba2269a3b669601e2fd41145b174008f4da8 /llvm/lib/Support/CommandLine.cpp
parent08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff)
Diffstat (limited to 'llvm/lib/Support/CommandLine.cpp')
-rw-r--r--llvm/lib/Support/CommandLine.cpp386
1 files changed, 226 insertions, 160 deletions
diff --git a/llvm/lib/Support/CommandLine.cpp b/llvm/lib/Support/CommandLine.cpp
index 5e7d63165130..66632504d6fb 100644
--- a/llvm/lib/Support/CommandLine.cpp
+++ b/llvm/lib/Support/CommandLine.cpp
@@ -21,14 +21,12 @@
#include "llvm-c/Support.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/STLFunctionalExtras.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Config/config.h"
#include "llvm/Support/ConvertUTF.h"
@@ -36,7 +34,6 @@
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/Host.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
@@ -45,6 +42,7 @@
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/raw_ostream.h"
#include <cstdlib>
+#include <optional>
#include <string>
using namespace llvm;
using namespace cl;
@@ -167,8 +165,8 @@ public:
SmallPtrSet<SubCommand *, 4> RegisteredSubCommands;
CommandLineParser() {
- registerSubCommand(&*TopLevelSubCommand);
- registerSubCommand(&*AllSubCommands);
+ registerSubCommand(&SubCommand::getTopLevel());
+ registerSubCommand(&SubCommand::getAll());
}
void ResetAllOptionOccurrences();
@@ -188,7 +186,7 @@ public:
// If we're adding this to all sub-commands, add it to the ones that have
// already been registered.
- if (SC == &*AllSubCommands) {
+ if (SC == &SubCommand::getAll()) {
for (auto *Sub : RegisteredSubCommands) {
if (SC == Sub)
continue;
@@ -199,7 +197,7 @@ public:
void addLiteralOption(Option &Opt, StringRef Name) {
if (Opt.Subs.empty())
- addLiteralOption(Opt, &*TopLevelSubCommand, Name);
+ addLiteralOption(Opt, &SubCommand::getTopLevel(), Name);
else {
for (auto *SC : Opt.Subs)
addLiteralOption(Opt, SC, Name);
@@ -244,7 +242,7 @@ public:
// If we're adding this to all sub-commands, add it to the ones that have
// already been registered.
- if (SC == &*AllSubCommands) {
+ if (SC == &SubCommand::getAll()) {
for (auto *Sub : RegisteredSubCommands) {
if (SC == Sub)
continue;
@@ -260,7 +258,7 @@ public:
}
if (O->Subs.empty()) {
- addOption(O, &*TopLevelSubCommand);
+ addOption(O, &SubCommand::getTopLevel());
} else {
for (auto *SC : O->Subs)
addOption(O, SC);
@@ -302,7 +300,7 @@ public:
void removeOption(Option *O) {
if (O->Subs.empty())
- removeOption(O, &*TopLevelSubCommand);
+ removeOption(O, &SubCommand::getTopLevel());
else {
if (O->isInAllSubCommands()) {
for (auto *SC : RegisteredSubCommands)
@@ -341,7 +339,7 @@ public:
void updateArgStr(Option *O, StringRef NewName) {
if (O->Subs.empty())
- updateArgStr(O, NewName, &*TopLevelSubCommand);
+ updateArgStr(O, NewName, &SubCommand::getTopLevel());
else {
if (O->isInAllSubCommands()) {
for (auto *SC : RegisteredSubCommands)
@@ -376,8 +374,8 @@ public:
// 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) {
+ if (sub != &SubCommand::getAll()) {
+ for (auto &E : SubCommand::getAll().OptionsMap) {
Option *O = E.second;
if ((O->isPositional() || O->isSink() || O->isConsumeAfter()) ||
O->hasArgStr())
@@ -409,10 +407,10 @@ public:
ResetAllOptionOccurrences();
RegisteredSubCommands.clear();
- TopLevelSubCommand->reset();
- AllSubCommands->reset();
- registerSubCommand(&*TopLevelSubCommand);
- registerSubCommand(&*AllSubCommands);
+ SubCommand::getTopLevel().reset();
+ SubCommand::getAll().reset();
+ registerSubCommand(&SubCommand::getTopLevel());
+ registerSubCommand(&SubCommand::getAll());
DefaultOptions.clear();
}
@@ -491,6 +489,10 @@ ManagedStatic<SubCommand> llvm::cl::TopLevelSubCommand;
// A special subcommand that can be used to put an option into all subcommands.
ManagedStatic<SubCommand> llvm::cl::AllSubCommands;
+SubCommand &SubCommand::getTopLevel() { return *TopLevelSubCommand; }
+
+SubCommand &SubCommand::getAll() { return *AllSubCommands; }
+
void SubCommand::registerSubCommand() {
GlobalParser->registerSubCommand(this);
}
@@ -523,7 +525,7 @@ Option *CommandLineParser::LookupOption(SubCommand &Sub, StringRef &Arg,
// Reject all dashes.
if (Arg.empty())
return nullptr;
- assert(&Sub != &*AllSubCommands);
+ assert(&Sub != &SubCommand::getAll());
size_t EqualPos = Arg.find('=');
@@ -551,9 +553,9 @@ Option *CommandLineParser::LookupOption(SubCommand &Sub, StringRef &Arg,
SubCommand *CommandLineParser::LookupSubCommand(StringRef Name) {
if (Name.empty())
- return &*TopLevelSubCommand;
+ return &SubCommand::getTopLevel();
for (auto *S : RegisteredSubCommands) {
- if (S == &*AllSubCommands)
+ if (S == &SubCommand::getAll())
continue;
if (S->getName().empty())
continue;
@@ -561,7 +563,7 @@ SubCommand *CommandLineParser::LookupSubCommand(StringRef Name) {
if (StringRef(S->getName()) == StringRef(Name))
return S;
}
- return &*TopLevelSubCommand;
+ return &SubCommand::getTopLevel();
}
/// LookupNearestOption - Lookup the closest match to the option specified by
@@ -1149,17 +1151,16 @@ static void ExpandBasePaths(StringRef BasePath, StringSaver &Saver,
}
// FName must be an absolute path.
-static llvm::Error ExpandResponseFile(StringRef FName, StringSaver &Saver,
- TokenizerCallback Tokenizer,
- SmallVectorImpl<const char *> &NewArgv,
- bool MarkEOLs, bool RelativeNames,
- bool ExpandBasePath,
- llvm::vfs::FileSystem &FS) {
+Error ExpansionContext::expandResponseFile(
+ StringRef FName, SmallVectorImpl<const char *> &NewArgv) {
assert(sys::path::is_absolute(FName));
llvm::ErrorOr<std::unique_ptr<MemoryBuffer>> MemBufOrErr =
- FS.getBufferForFile(FName);
- if (!MemBufOrErr)
- return llvm::errorCodeToError(MemBufOrErr.getError());
+ FS->getBufferForFile(FName);
+ if (!MemBufOrErr) {
+ std::error_code EC = MemBufOrErr.getError();
+ return llvm::createStringError(EC, Twine("cannot not open file '") + FName +
+ "': " + EC.message());
+ }
MemoryBuffer &MemBuf = *MemBufOrErr.get();
StringRef Str(MemBuf.getBufferStart(), MemBuf.getBufferSize());
@@ -1181,33 +1182,51 @@ static llvm::Error ExpandResponseFile(StringRef FName, StringSaver &Saver,
// Tokenize the contents into NewArgv.
Tokenizer(Str, Saver, NewArgv, MarkEOLs);
- if (!RelativeNames)
+ // Expanded file content may require additional transformations, like using
+ // absolute paths instead of relative in '@file' constructs or expanding
+ // macros.
+ if (!RelativeNames && !InConfigFile)
return Error::success();
- llvm::StringRef BasePath = llvm::sys::path::parent_path(FName);
- // If names of nested response files should be resolved relative to including
- // file, replace the included response file names with their full paths
- // obtained by required resolution.
- for (auto &Arg : NewArgv) {
+
+ StringRef BasePath = llvm::sys::path::parent_path(FName);
+ for (const char *&Arg : NewArgv) {
if (!Arg)
continue;
// Substitute <CFGDIR> with the file's base path.
- if (ExpandBasePath)
+ if (InConfigFile)
ExpandBasePaths(BasePath, Saver, Arg);
- // Skip non-rsp file arguments.
- if (Arg[0] != '@')
- continue;
-
- StringRef FileName(Arg + 1);
- // Skip if non-relative.
- if (!llvm::sys::path::is_relative(FileName))
+ // Discover the case, when argument should be transformed into '@file' and
+ // evaluate 'file' for it.
+ StringRef ArgStr(Arg);
+ StringRef FileName;
+ bool ConfigInclusion = false;
+ if (ArgStr.consume_front("@")) {
+ FileName = ArgStr;
+ if (!llvm::sys::path::is_relative(FileName))
+ continue;
+ } else if (ArgStr.consume_front("--config=")) {
+ FileName = ArgStr;
+ ConfigInclusion = true;
+ } else {
continue;
+ }
+ // Update expansion construct.
SmallString<128> ResponseFile;
ResponseFile.push_back('@');
- ResponseFile.append(BasePath);
- llvm::sys::path::append(ResponseFile, FileName);
+ if (ConfigInclusion && !llvm::sys::path::has_parent_path(FileName)) {
+ SmallString<128> FilePath;
+ if (!findConfigFile(FileName, FilePath))
+ return createStringError(
+ std::make_error_code(std::errc::no_such_file_or_directory),
+ "cannot not find configuration file: " + FileName);
+ ResponseFile.append(FilePath);
+ } else {
+ ResponseFile.append(BasePath);
+ llvm::sys::path::append(ResponseFile, FileName);
+ }
Arg = Saver.save(ResponseFile.str()).data();
}
return Error::success();
@@ -1215,12 +1234,8 @@ static llvm::Error ExpandResponseFile(StringRef FName, StringSaver &Saver,
/// Expand response files on a command line recursively using the given
/// StringSaver and tokenization strategy.
-bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
- SmallVectorImpl<const char *> &Argv, bool MarkEOLs,
- bool RelativeNames, bool ExpandBasePath,
- llvm::Optional<llvm::StringRef> CurrentDir,
- llvm::vfs::FileSystem &FS) {
- bool AllExpanded = true;
+Error ExpansionContext::expandResponseFiles(
+ SmallVectorImpl<const char *> &Argv) {
struct ResponseFileRecord {
std::string File;
size_t End;
@@ -1260,52 +1275,63 @@ bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
// always have an absolute path deduced from the containing file.
SmallString<128> CurrDir;
if (llvm::sys::path::is_relative(FName)) {
- if (!CurrentDir)
- llvm::sys::fs::current_path(CurrDir);
- else
- CurrDir = *CurrentDir;
+ if (CurrentDir.empty()) {
+ if (auto CWD = FS->getCurrentWorkingDirectory()) {
+ CurrDir = *CWD;
+ } else {
+ return createStringError(
+ CWD.getError(), Twine("cannot get absolute path for: ") + FName);
+ }
+ } else {
+ CurrDir = CurrentDir;
+ }
llvm::sys::path::append(CurrDir, FName);
FName = CurrDir.c_str();
}
- auto IsEquivalent = [FName, &FS](const ResponseFileRecord &RFile) {
- llvm::ErrorOr<llvm::vfs::Status> LHS = FS.status(FName);
- if (!LHS) {
- // TODO: The error should be propagated up the stack.
- llvm::consumeError(llvm::errorCodeToError(LHS.getError()));
- return false;
- }
- llvm::ErrorOr<llvm::vfs::Status> RHS = FS.status(RFile.File);
- if (!RHS) {
- // TODO: The error should be propagated up the stack.
- llvm::consumeError(llvm::errorCodeToError(RHS.getError()));
- return false;
+
+ ErrorOr<llvm::vfs::Status> Res = FS->status(FName);
+ if (!Res || !Res->exists()) {
+ std::error_code EC = Res.getError();
+ if (!InConfigFile) {
+ // If the specified file does not exist, leave '@file' unexpanded, as
+ // libiberty does.
+ if (!EC || EC == llvm::errc::no_such_file_or_directory) {
+ ++I;
+ continue;
+ }
}
- return LHS->equivalent(*RHS);
+ if (!EC)
+ EC = llvm::errc::no_such_file_or_directory;
+ return createStringError(EC, Twine("cannot not open file '") + FName +
+ "': " + EC.message());
+ }
+ const llvm::vfs::Status &FileStatus = Res.get();
+
+ auto IsEquivalent =
+ [FileStatus, this](const ResponseFileRecord &RFile) -> ErrorOr<bool> {
+ ErrorOr<llvm::vfs::Status> RHS = FS->status(RFile.File);
+ if (!RHS)
+ return RHS.getError();
+ return FileStatus.equivalent(*RHS);
};
// Check for recursive response files.
- if (any_of(drop_begin(FileStack), IsEquivalent)) {
- // This file is recursive, so we leave it in the argument stream and
- // move on.
- AllExpanded = false;
- ++I;
- continue;
+ for (const auto &F : drop_begin(FileStack)) {
+ if (ErrorOr<bool> R = IsEquivalent(F)) {
+ if (R.get())
+ return createStringError(
+ R.getError(), Twine("recursive expansion of: '") + F.File + "'");
+ } else {
+ return createStringError(R.getError(),
+ Twine("cannot open file: ") + F.File);
+ }
}
// Replace this response file argument with the tokenization of its
// contents. Nested response files are expanded in subsequent iterations.
SmallVector<const char *, 0> ExpandedArgv;
- if (llvm::Error Err =
- ExpandResponseFile(FName, Saver, Tokenizer, ExpandedArgv, MarkEOLs,
- RelativeNames, ExpandBasePath, FS)) {
- // We couldn't read this file, so we leave it in the argument stream and
- // move on.
- // TODO: The error should be propagated up the stack.
- llvm::consumeError(std::move(Err));
- AllExpanded = false;
- ++I;
- continue;
- }
+ if (Error Err = expandResponseFile(FName, ExpandedArgv))
+ return Err;
for (ResponseFileRecord &Record : FileStack) {
// Increase the end of all active records by the number of newly expanded
@@ -1324,53 +1350,97 @@ bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
// don't have a chance to pop the stack when encountering recursive files at
// the end of the stream, so seeing that doesn't indicate a bug.
assert(FileStack.size() > 0 && Argv.size() == FileStack.back().End);
- return AllExpanded;
-}
-
-bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
- SmallVectorImpl<const char *> &Argv, bool MarkEOLs,
- bool RelativeNames, bool ExpandBasePath,
- llvm::Optional<StringRef> CurrentDir) {
- return ExpandResponseFiles(Saver, std::move(Tokenizer), Argv, MarkEOLs,
- RelativeNames, ExpandBasePath,
- std::move(CurrentDir), *vfs::getRealFileSystem());
+ return Error::success();
}
bool cl::expandResponseFiles(int Argc, const char *const *Argv,
const char *EnvVar, StringSaver &Saver,
SmallVectorImpl<const char *> &NewArgv) {
- auto Tokenize = Triple(sys::getProcessTriple()).isOSWindows()
- ? cl::TokenizeWindowsCommandLine
- : cl::TokenizeGNUCommandLine;
+#ifdef _WIN32
+ auto Tokenize = cl::TokenizeWindowsCommandLine;
+#else
+ auto Tokenize = cl::TokenizeGNUCommandLine;
+#endif
// The environment variable specifies initial options.
if (EnvVar)
- if (llvm::Optional<std::string> EnvValue = sys::Process::GetEnv(EnvVar))
+ if (std::optional<std::string> EnvValue = sys::Process::GetEnv(EnvVar))
Tokenize(*EnvValue, Saver, NewArgv, /*MarkEOLs=*/false);
// Command line options can override the environment variable.
NewArgv.append(Argv + 1, Argv + Argc);
- return ExpandResponseFiles(Saver, Tokenize, NewArgv);
+ ExpansionContext ECtx(Saver.getAllocator(), Tokenize);
+ if (Error Err = ECtx.expandResponseFiles(NewArgv)) {
+ errs() << toString(std::move(Err)) << '\n';
+ return false;
+ }
+ return true;
+}
+
+bool cl::ExpandResponseFiles(StringSaver &Saver, TokenizerCallback Tokenizer,
+ SmallVectorImpl<const char *> &Argv) {
+ ExpansionContext ECtx(Saver.getAllocator(), Tokenizer);
+ if (Error Err = ECtx.expandResponseFiles(Argv)) {
+ errs() << toString(std::move(Err)) << '\n';
+ return false;
+ }
+ return true;
}
-bool cl::readConfigFile(StringRef CfgFile, StringSaver &Saver,
- SmallVectorImpl<const char *> &Argv) {
+ExpansionContext::ExpansionContext(BumpPtrAllocator &A, TokenizerCallback T)
+ : Saver(A), Tokenizer(T), FS(vfs::getRealFileSystem().get()) {}
+
+bool ExpansionContext::findConfigFile(StringRef FileName,
+ SmallVectorImpl<char> &FilePath) {
+ SmallString<128> CfgFilePath;
+ const auto FileExists = [this](SmallString<128> Path) -> bool {
+ auto Status = FS->status(Path);
+ return Status &&
+ Status->getType() == llvm::sys::fs::file_type::regular_file;
+ };
+
+ // If file name contains directory separator, treat it as a path to
+ // configuration file.
+ if (llvm::sys::path::has_parent_path(FileName)) {
+ CfgFilePath = FileName;
+ if (llvm::sys::path::is_relative(FileName) && FS->makeAbsolute(CfgFilePath))
+ return false;
+ if (!FileExists(CfgFilePath))
+ return false;
+ FilePath.assign(CfgFilePath.begin(), CfgFilePath.end());
+ return true;
+ }
+
+ // Look for the file in search directories.
+ for (const StringRef &Dir : SearchDirs) {
+ if (Dir.empty())
+ continue;
+ CfgFilePath.assign(Dir);
+ llvm::sys::path::append(CfgFilePath, FileName);
+ llvm::sys::path::native(CfgFilePath);
+ if (FileExists(CfgFilePath)) {
+ FilePath.assign(CfgFilePath.begin(), CfgFilePath.end());
+ return true;
+ }
+ }
+
+ return false;
+}
+
+Error ExpansionContext::readConfigFile(StringRef CfgFile,
+ SmallVectorImpl<const char *> &Argv) {
SmallString<128> AbsPath;
if (sys::path::is_relative(CfgFile)) {
- llvm::sys::fs::current_path(AbsPath);
- llvm::sys::path::append(AbsPath, CfgFile);
+ AbsPath.assign(CfgFile);
+ if (std::error_code EC = FS->makeAbsolute(AbsPath))
+ return make_error<StringError>(
+ EC, Twine("cannot get absolute path for " + CfgFile));
CfgFile = AbsPath.str();
}
- if (llvm::Error Err = ExpandResponseFile(
- CfgFile, Saver, cl::tokenizeConfigFile, Argv,
- /*MarkEOLs=*/false, /*RelativeNames=*/true, /*ExpandBasePath=*/true,
- *llvm::vfs::getRealFileSystem())) {
- // TODO: The error should be propagated up the stack.
- llvm::consumeError(std::move(Err));
- return false;
- }
- return ExpandResponseFiles(Saver, cl::tokenizeConfigFile, Argv,
- /*MarkEOLs=*/false, /*RelativeNames=*/true,
- /*ExpandBasePath=*/true, llvm::None);
+ InConfigFile = true;
+ RelativeNames = true;
+ if (Error Err = expandResponseFile(CfgFile, Argv))
+ return Err;
+ return expandResponseFiles(Argv);
}
static void initCommonOptions();
@@ -1386,7 +1456,7 @@ bool cl::ParseCommandLineOptions(int argc, const char *const *argv,
// Parse options from environment variable.
if (EnvVar) {
- if (llvm::Optional<std::string> EnvValue =
+ if (std::optional<std::string> EnvValue =
sys::Process::GetEnv(StringRef(EnvVar)))
TokenizeGNUCommandLine(*EnvValue, Saver, NewArgv);
}
@@ -1425,26 +1495,31 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
bool LongOptionsUseDoubleDash) {
assert(hasOptions() && "No options specified!");
+ ProgramOverview = Overview;
+ bool IgnoreErrors = Errs;
+ if (!Errs)
+ Errs = &errs();
+ bool ErrorParsing = false;
+
// Expand response files.
SmallVector<const char *, 20> newArgv(argv, argv + argc);
BumpPtrAllocator A;
- StringSaver Saver(A);
- ExpandResponseFiles(Saver,
- Triple(sys::getProcessTriple()).isOSWindows() ?
- cl::TokenizeWindowsCommandLine : cl::TokenizeGNUCommandLine,
- newArgv);
+#ifdef _WIN32
+ auto Tokenize = cl::TokenizeWindowsCommandLine;
+#else
+ auto Tokenize = cl::TokenizeGNUCommandLine;
+#endif
+ ExpansionContext ECtx(A, Tokenize);
+ if (Error Err = ECtx.expandResponseFiles(newArgv)) {
+ *Errs << toString(std::move(Err)) << '\n';
+ return false;
+ }
argv = &newArgv[0];
argc = static_cast<int>(newArgv.size());
// Copy the program name into ProgName, making sure not to overflow it.
ProgramName = std::string(sys::path::filename(StringRef(argv[0])));
- ProgramOverview = Overview;
- bool IgnoreErrors = Errs;
- if (!Errs)
- Errs = &errs();
- bool ErrorParsing = false;
-
// Check out the positional arguments to collect information about them.
unsigned NumPositionalRequired = 0;
@@ -1452,12 +1527,12 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
bool HasUnlimitedPositionals = false;
int FirstArg = 1;
- SubCommand *ChosenSubCommand = &*TopLevelSubCommand;
+ SubCommand *ChosenSubCommand = &SubCommand::getTopLevel();
if (argc >= 2 && argv[FirstArg][0] != '-') {
// If the first argument specifies a valid subcommand, start processing
// options from the second argument.
ChosenSubCommand = LookupSubCommand(StringRef(argv[FirstArg]));
- if (ChosenSubCommand != &*TopLevelSubCommand)
+ if (ChosenSubCommand != &SubCommand::getTopLevel())
FirstArg = 2;
}
GlobalParser->ActiveSubCommand = ChosenSubCommand;
@@ -1675,7 +1750,7 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
switch (PositionalOpts[i]->getNumOccurrencesFlag()) {
case cl::Optional:
Done = true; // Optional arguments want _at most_ one value
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case cl::ZeroOrMore: // Zero or more will take all they can get...
case cl::OneOrMore: // One or more will take all they can get...
ProvidePositionalOption(PositionalOpts[i],
@@ -1729,7 +1804,7 @@ bool CommandLineParser::ParseCommandLineOptions(int argc,
Opt.second->error("must be specified at least once!");
ErrorParsing = true;
}
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
default:
break;
}
@@ -2289,7 +2364,7 @@ public:
if (!GlobalParser->ProgramOverview.empty())
outs() << "OVERVIEW: " << GlobalParser->ProgramOverview << "\n";
- if (Sub == &*TopLevelSubCommand) {
+ if (Sub == &SubCommand::getTopLevel()) {
outs() << "USAGE: " << GlobalParser->ProgramName;
if (Subs.size() > 2)
outs() << " [subcommand]";
@@ -2313,7 +2388,7 @@ public:
if (ConsumeAfterOpt)
outs() << " " << ConsumeAfterOpt->HelpStr;
- if (Sub == &*TopLevelSubCommand && !Subs.empty()) {
+ if (Sub == &SubCommand::getTopLevel() && !Subs.empty()) {
// Compute the maximum subcommand length...
size_t MaxSubLen = 0;
for (size_t i = 0, e = Subs.size(); i != e; ++i)
@@ -2463,7 +2538,7 @@ public:
namespace {
class VersionPrinter {
public:
- void print() {
+ void print(std::vector<VersionPrinterTy> ExtraPrinters = {}) {
raw_ostream &OS = outs();
#ifdef PACKAGE_VENDOR
OS << PACKAGE_VENDOR << " ";
@@ -2479,15 +2554,14 @@ public:
#ifndef NDEBUG
OS << " with assertions";
#endif
-#if LLVM_VERSION_PRINTER_SHOW_HOST_TARGET_INFO
- std::string CPU = std::string(sys::getHostCPUName());
- if (CPU == "generic")
- CPU = "(unknown)";
- OS << ".\n"
- << " Default target: " << sys::getDefaultTargetTriple() << '\n'
- << " Host CPU: " << CPU;
-#endif
- OS << '\n';
+ OS << ".\n";
+
+ // Iterate over any registered extra printers and call them to add further
+ // information.
+ if (!ExtraPrinters.empty()) {
+ for (const auto &I : ExtraPrinters)
+ I(outs());
+ }
}
void operator=(bool OptionWasSpecified);
};
@@ -2519,7 +2593,7 @@ struct CommandLineCommonOptions {
cl::Hidden,
cl::ValueDisallowed,
cl::cat(GenericCategory),
- cl::sub(*AllSubCommands)};
+ cl::sub(SubCommand::getAll())};
cl::opt<HelpPrinter, true, parser<bool>> HLHOp{
"help-list-hidden",
@@ -2528,7 +2602,7 @@ struct CommandLineCommonOptions {
cl::Hidden,
cl::ValueDisallowed,
cl::cat(GenericCategory),
- cl::sub(*AllSubCommands)};
+ cl::sub(SubCommand::getAll())};
// Define uncategorized/categorized help printers. These printers change their
// behaviour at runtime depending on whether one or more Option categories
@@ -2539,7 +2613,7 @@ struct CommandLineCommonOptions {
cl::location(WrappedNormalPrinter),
cl::ValueDisallowed,
cl::cat(GenericCategory),
- cl::sub(*AllSubCommands)};
+ cl::sub(SubCommand::getAll())};
cl::alias HOpA{"h", cl::desc("Alias for --help"), cl::aliasopt(HOp),
cl::DefaultOption};
@@ -2551,7 +2625,7 @@ struct CommandLineCommonOptions {
cl::Hidden,
cl::ValueDisallowed,
cl::cat(GenericCategory),
- cl::sub(*AllSubCommands)};
+ cl::sub(SubCommand::getAll())};
cl::opt<bool> PrintOptions{
"print-options",
@@ -2559,7 +2633,7 @@ struct CommandLineCommonOptions {
cl::Hidden,
cl::init(false),
cl::cat(GenericCategory),
- cl::sub(*AllSubCommands)};
+ cl::sub(SubCommand::getAll())};
cl::opt<bool> PrintAllOptions{
"print-all-options",
@@ -2567,7 +2641,7 @@ struct CommandLineCommonOptions {
cl::Hidden,
cl::init(false),
cl::cat(GenericCategory),
- cl::sub(*AllSubCommands)};
+ cl::sub(SubCommand::getAll())};
VersionPrinterTy OverrideVersionPrinter = nullptr;
@@ -2614,15 +2688,7 @@ void VersionPrinter::operator=(bool OptionWasSpecified) {
CommonOptions->OverrideVersionPrinter(outs());
exit(0);
}
- print();
-
- // Iterate over any registered extra printers and call them to add further
- // information.
- if (!CommonOptions->ExtraVersionPrinters.empty()) {
- outs() << '\n';
- for (const auto &I : CommonOptions->ExtraVersionPrinters)
- I(outs());
- }
+ print(CommonOptions->ExtraVersionPrinters);
exit(0);
}
@@ -2677,7 +2743,7 @@ void cl::PrintHelpMessage(bool Hidden, bool Categorized) {
/// Utility function for printing version number.
void cl::PrintVersionMessage() {
- CommonOptions->VersionPrinterInstance.print();
+ CommonOptions->VersionPrinterInstance.print(CommonOptions->ExtraVersionPrinters);
}
void cl::SetVersionPrinter(VersionPrinterTy func) {