aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Option/OptTable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Option/OptTable.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Option/OptTable.cpp186
1 files changed, 90 insertions, 96 deletions
diff --git a/contrib/llvm-project/llvm/lib/Option/OptTable.cpp b/contrib/llvm-project/llvm/lib/Option/OptTable.cpp
index c93b7ad7f5fa..2e289c58b45a 100644
--- a/contrib/llvm-project/llvm/lib/Option/OptTable.cpp
+++ b/contrib/llvm-project/llvm/lib/Option/OptTable.cpp
@@ -9,7 +9,6 @@
#include "llvm/Option/OptTable.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSet.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/OptSpecifier.h"
@@ -23,6 +22,7 @@
#include <cctype>
#include <cstring>
#include <map>
+#include <set>
#include <string>
#include <utility>
#include <vector>
@@ -36,31 +36,23 @@ namespace opt {
// Ordering on Info. The ordering is *almost* case-insensitive lexicographic,
// with an exception. '\0' comes at the end of the alphabet instead of the
// beginning (thus options precede any other options which prefix them).
-static int StrCmpOptionNameIgnoreCase(const char *A, const char *B) {
- const char *X = A, *Y = B;
- char a = tolower(*A), b = tolower(*B);
- while (a == b) {
- if (a == '\0')
- return 0;
-
- a = tolower(*++X);
- b = tolower(*++Y);
- }
+static int StrCmpOptionNameIgnoreCase(StringRef A, StringRef B) {
+ size_t MinSize = std::min(A.size(), B.size());
+ if (int Res = A.substr(0, MinSize).compare_insensitive(B.substr(0, MinSize)))
+ return Res;
- if (a == '\0') // A is a prefix of B.
- return 1;
- if (b == '\0') // B is a prefix of A.
- return -1;
+ if (A.size() == B.size())
+ return 0;
- // Otherwise lexicographic.
- return (a < b) ? -1 : 1;
+ return (A.size() == MinSize) ? 1 /* A is a prefix of B. */
+ : -1 /* B is a prefix of A */;
}
#ifndef NDEBUG
-static int StrCmpOptionName(const char *A, const char *B) {
+static int StrCmpOptionName(StringRef A, StringRef B) {
if (int N = StrCmpOptionNameIgnoreCase(A, B))
return N;
- return strcmp(A, B);
+ return A.compare(B);
}
static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
@@ -70,12 +62,10 @@ static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
if (int N = StrCmpOptionName(A.Name, B.Name))
return N < 0;
- for (const char * const *APre = A.Prefixes,
- * const *BPre = B.Prefixes;
- *APre != nullptr && *BPre != nullptr; ++APre, ++BPre){
- if (int N = StrCmpOptionName(*APre, *BPre))
+ for (size_t I = 0, K = std::min(A.Prefixes.size(), B.Prefixes.size()); I != K;
+ ++I)
+ if (int N = StrCmpOptionName(A.Prefixes[I], B.Prefixes[I]))
return N < 0;
- }
// Names are the same, check that classes are in order; exactly one
// should be joined, and it should succeed the other.
@@ -86,7 +76,7 @@ static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
#endif
// Support lower_bound between info and an option name.
-static inline bool operator<(const OptTable::Info &I, const char *Name) {
+static inline bool operator<(const OptTable::Info &I, StringRef Name) {
return StrCmpOptionNameIgnoreCase(I.Name, Name) < 0;
}
@@ -135,21 +125,13 @@ OptTable::OptTable(ArrayRef<Info> OptionInfos, bool IgnoreCase)
}
}
#endif
+}
- // Build prefixes.
- for (unsigned i = FirstSearchableIndex + 1, e = getNumOptions() + 1;
- i != e; ++i) {
- if (const char *const *P = getInfo(i).Prefixes) {
- for (; *P != nullptr; ++P) {
- PrefixesUnion.insert(*P);
- }
- }
- }
+void OptTable::buildPrefixChars() {
+ assert(PrefixChars.empty() && "rebuilding a non-empty prefix char");
// Build prefix chars.
- for (StringSet<>::const_iterator I = PrefixesUnion.begin(),
- E = PrefixesUnion.end(); I != E; ++I) {
- StringRef Prefix = I->getKey();
+ for (const StringLiteral &Prefix : getPrefixesUnion()) {
for (char C : Prefix)
if (!is_contained(PrefixChars, C))
PrefixChars.push_back(C);
@@ -166,12 +148,11 @@ const Option OptTable::getOption(OptSpecifier Opt) const {
return Option(&getInfo(id), this);
}
-static bool isInput(const StringSet<> &Prefixes, StringRef Arg) {
+static bool isInput(const ArrayRef<StringLiteral> &Prefixes, StringRef Arg) {
if (Arg == "-")
return true;
- for (StringSet<>::const_iterator I = Prefixes.begin(),
- E = Prefixes.end(); I != E; ++I)
- if (Arg.startswith(I->getKey()))
+ for (const StringRef &Prefix : Prefixes)
+ if (Arg.startswith(Prefix))
return false;
return true;
}
@@ -179,8 +160,7 @@ static bool isInput(const StringSet<> &Prefixes, StringRef Arg) {
/// \returns Matched size. 0 means no match.
static unsigned matchOption(const OptTable::Info *I, StringRef Str,
bool IgnoreCase) {
- for (const char * const *Pre = I->Prefixes; *Pre != nullptr; ++Pre) {
- StringRef Prefix(*Pre);
+ for (auto Prefix : I->Prefixes) {
if (Str.startswith(Prefix)) {
StringRef Rest = Str.substr(Prefix.size());
bool Matched = IgnoreCase ? Rest.startswith_insensitive(I->Name)
@@ -194,13 +174,10 @@ static unsigned matchOption(const OptTable::Info *I, StringRef Str,
// Returns true if one of the Prefixes + In.Names matches Option
static bool optionMatches(const OptTable::Info &In, StringRef Option) {
- if (In.Prefixes) {
- StringRef InName(In.Name);
- for (size_t I = 0; In.Prefixes[I]; I++)
- if (Option.endswith(InName))
- if (Option.slice(0, Option.size() - InName.size()) == In.Prefixes[I])
- return true;
- }
+ for (auto Prefix : In.Prefixes)
+ if (Option.endswith(In.Name))
+ if (Option.slice(0, Option.size() - In.Name.size()) == Prefix)
+ return true;
return false;
}
@@ -232,13 +209,13 @@ OptTable::findByPrefix(StringRef Cur, unsigned int DisableFlags) const {
std::vector<std::string> Ret;
for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; I++) {
const Info &In = OptionInfos[I];
- if (!In.Prefixes || (!In.HelpText && !In.GroupID))
+ if (In.Prefixes.empty() || (!In.HelpText && !In.GroupID))
continue;
if (In.Flags & DisableFlags)
continue;
- for (int I = 0; In.Prefixes[I]; I++) {
- std::string S = std::string(In.Prefixes[I]) + std::string(In.Name) + "\t";
+ for (auto Prefix : In.Prefixes) {
+ std::string S = (Prefix + In.Name + "\t").str();
if (In.HelpText)
S += In.HelpText;
if (StringRef(S).startswith(Cur) && S != std::string(Cur) + "\t")
@@ -250,12 +227,17 @@ OptTable::findByPrefix(StringRef Cur, unsigned int DisableFlags) const {
unsigned OptTable::findNearest(StringRef Option, std::string &NearestString,
unsigned FlagsToInclude, unsigned FlagsToExclude,
- unsigned MinimumLength) const {
+ unsigned MinimumLength,
+ unsigned MaximumDistance) const {
assert(!Option.empty());
// Consider each [option prefix + option name] pair as a candidate, finding
// the closest match.
- unsigned BestDistance = UINT_MAX;
+ unsigned BestDistance =
+ MaximumDistance == UINT_MAX ? UINT_MAX : MaximumDistance + 1;
+ SmallString<16> Candidate;
+ SmallString<16> NormalizedName;
+
for (const Info &CandidateInfo :
ArrayRef<Info>(OptionInfos).drop_front(FirstSearchableIndex)) {
StringRef CandidateName = CandidateInfo.Name;
@@ -263,7 +245,7 @@ unsigned OptTable::findNearest(StringRef Option, std::string &NearestString,
// We can eliminate some option prefix/name pairs as candidates right away:
// * Ignore option candidates with empty names, such as "--", or names
// that do not meet the minimum length.
- if (CandidateName.empty() || CandidateName.size() < MinimumLength)
+ if (CandidateName.size() < MinimumLength)
continue;
// * If FlagsToInclude were specified, ignore options that don't include
@@ -276,33 +258,43 @@ unsigned OptTable::findNearest(StringRef Option, std::string &NearestString,
// * Ignore positional argument option candidates (which do not
// have prefixes).
- if (!CandidateInfo.Prefixes)
+ if (CandidateInfo.Prefixes.empty())
continue;
// Now check if the candidate ends with a character commonly used when
// delimiting an option from its value, such as '=' or ':'. If it does,
// attempt to split the given option based on that delimiter.
- StringRef LHS, RHS;
char Last = CandidateName.back();
bool CandidateHasDelimiter = Last == '=' || Last == ':';
- std::string NormalizedName = std::string(Option);
+ StringRef RHS;
if (CandidateHasDelimiter) {
- std::tie(LHS, RHS) = Option.split(Last);
- NormalizedName = std::string(LHS);
- if (Option.find(Last) == LHS.size())
+ std::tie(NormalizedName, RHS) = Option.split(Last);
+ if (Option.find(Last) == NormalizedName.size())
NormalizedName += Last;
- }
+ } else
+ NormalizedName = Option;
// Consider each possible prefix for each candidate to find the most
// appropriate one. For example, if a user asks for "--helm", suggest
// "--help" over "-help".
- for (int P = 0;
- const char *const CandidatePrefix = CandidateInfo.Prefixes[P]; P++) {
- std::string Candidate = (CandidatePrefix + CandidateName).str();
- StringRef CandidateRef = Candidate;
- unsigned Distance =
- CandidateRef.edit_distance(NormalizedName, /*AllowReplacements=*/true,
- /*MaxEditDistance=*/BestDistance);
+ for (auto CandidatePrefix : CandidateInfo.Prefixes) {
+ // If Candidate and NormalizedName have more than 'BestDistance'
+ // characters of difference, no need to compute the edit distance, it's
+ // going to be greater than BestDistance. Don't bother computing Candidate
+ // at all.
+ size_t CandidateSize = CandidatePrefix.size() + CandidateName.size(),
+ NormalizedSize = NormalizedName.size();
+ size_t AbsDiff = CandidateSize > NormalizedSize
+ ? CandidateSize - NormalizedSize
+ : NormalizedSize - CandidateSize;
+ if (AbsDiff > BestDistance) {
+ continue;
+ }
+ Candidate = CandidatePrefix;
+ Candidate += CandidateName;
+ unsigned Distance = StringRef(Candidate).edit_distance(
+ NormalizedName, /*AllowReplacements=*/true,
+ /*MaxEditDistance=*/BestDistance);
if (RHS.empty() && CandidateHasDelimiter) {
// The Candidate ends with a = or : delimiter, but the option passed in
// didn't contain the delimiter (or doesn't have anything after it).
@@ -321,17 +313,6 @@ unsigned OptTable::findNearest(StringRef Option, std::string &NearestString,
return BestDistance;
}
-bool OptTable::addValues(const char *Option, const char *Values) {
- for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; I++) {
- Info &In = OptionInfos[I];
- if (optionMatches(In, Option)) {
- In.Values = Values;
- return true;
- }
- }
- return false;
-}
-
// Parse a single argument, return the new argument, and update Index. If
// GroupedShortOptions is true, -a matches "-abc" and the argument in Args will
// be updated to "-bc". This overload does not support
@@ -342,13 +323,13 @@ std::unique_ptr<Arg> OptTable::parseOneArgGrouped(InputArgList &Args,
// itself.
const char *CStr = Args.getArgString(Index);
StringRef Str(CStr);
- if (isInput(PrefixesUnion, Str))
+ if (isInput(getPrefixesUnion(), Str))
return std::make_unique<Arg>(getOption(InputOptionID), Str, Index++, CStr);
const Info *End = OptionInfos.data() + OptionInfos.size();
StringRef Name = Str.ltrim(PrefixChars);
- const Info *Start = std::lower_bound(
- OptionInfos.data() + FirstSearchableIndex, End, Name.data());
+ const Info *Start =
+ std::lower_bound(OptionInfos.data() + FirstSearchableIndex, End, Name);
const Info *Fallback = nullptr;
unsigned Prev = Index;
@@ -403,19 +384,20 @@ std::unique_ptr<Arg> OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
unsigned FlagsToInclude,
unsigned FlagsToExclude) const {
unsigned Prev = Index;
- const char *Str = Args.getArgString(Index);
+ StringRef Str = Args.getArgString(Index);
// Anything that doesn't start with PrefixesUnion is an input, as is '-'
// itself.
- if (isInput(PrefixesUnion, Str))
- return std::make_unique<Arg>(getOption(InputOptionID), Str, Index++, Str);
+ if (isInput(getPrefixesUnion(), Str))
+ return std::make_unique<Arg>(getOption(InputOptionID), Str, Index++,
+ Str.data());
const Info *Start = OptionInfos.data() + FirstSearchableIndex;
const Info *End = OptionInfos.data() + OptionInfos.size();
- StringRef Name = StringRef(Str).ltrim(PrefixChars);
+ StringRef Name = Str.ltrim(PrefixChars);
// Search for the first next option which could be a prefix.
- Start = std::lower_bound(Start, End, Name.data());
+ Start = std::lower_bound(Start, End, Name);
// Options are stored in sorted order, with '\0' at the end of the
// alphabet. Since the only options which can accept a string must
@@ -455,9 +437,11 @@ std::unique_ptr<Arg> OptTable::ParseOneArg(const ArgList &Args, unsigned &Index,
// If we failed to find an option and this arg started with /, then it's
// probably an input path.
if (Str[0] == '/')
- return std::make_unique<Arg>(getOption(InputOptionID), Str, Index++, Str);
+ return std::make_unique<Arg>(getOption(InputOptionID), Str, Index++,
+ Str.data());
- return std::make_unique<Arg>(getOption(UnknownOptionID), Str, Index++, Str);
+ return std::make_unique<Arg>(getOption(UnknownOptionID), Str, Index++,
+ Str.data());
}
InputArgList OptTable::ParseArgs(ArrayRef<const char *> ArgArr,
@@ -515,7 +499,7 @@ InputArgList OptTable::parseArgs(int Argc, char *const *Argv,
cl::expandResponseFiles(Argc, Argv, EnvVar, Saver, NewArgv);
unsigned MAI, MAC;
- opt::InputArgList Args = ParseArgs(makeArrayRef(NewArgv), MAI, MAC);
+ opt::InputArgList Args = ParseArgs(ArrayRef(NewArgv), MAI, MAC);
if (MAC)
ErrorFn((Twine(Args.getArgString(MAI)) + ": missing argument").str());
@@ -525,10 +509,10 @@ InputArgList OptTable::parseArgs(int Argc, char *const *Argv,
for (const opt::Arg *A : Args.filtered(Unknown)) {
std::string Spelling = A->getAsString(Args);
if (findNearest(Spelling, Nearest) > 1)
- ErrorFn("unknown argument '" + A->getAsString(Args) + "'");
+ ErrorFn("unknown argument '" + Spelling + "'");
else
- ErrorFn("unknown argument '" + A->getAsString(Args) +
- "', did you mean '" + Nearest + "'?");
+ ErrorFn("unknown argument '" + Spelling + "', did you mean '" + Nearest +
+ "'?");
}
return Args;
}
@@ -565,7 +549,7 @@ static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) {
case Option::SeparateClass: case Option::JoinedOrSeparateClass:
case Option::RemainingArgsClass: case Option::RemainingArgsJoinedClass:
Name += ' ';
- LLVM_FALLTHROUGH;
+ [[fallthrough]];
case Option::JoinedClass: case Option::CommaJoinedClass:
case Option::JoinedAndSeparateClass:
if (const char *MetaVarName = Opts.getOptionMetaVar(Id))
@@ -682,3 +666,13 @@ void OptTable::printHelp(raw_ostream &OS, const char *Usage, const char *Title,
OS.flush();
}
+
+GenericOptTable::GenericOptTable(ArrayRef<Info> OptionInfos, bool IgnoreCase)
+ : OptTable(OptionInfos, IgnoreCase) {
+
+ std::set<StringLiteral> TmpPrefixesUnion;
+ for (auto const &Info : OptionInfos.drop_front(FirstSearchableIndex))
+ TmpPrefixesUnion.insert(Info.Prefixes.begin(), Info.Prefixes.end());
+ PrefixesUnionBuffer.append(TmpPrefixesUnion.begin(), TmpPrefixesUnion.end());
+ buildPrefixChars();
+}