[StrTable] Switch the option parser to llvm::StringTable (#123308)
Now that we have a dedicated abstraction for string tables, switch the option parser library's string table over to it rather than using a raw `const char*`. Also try to use the `StringTable::Offset` type rather than a raw `unsigned` where we can to avoid accidental increments or other issues. This is based on review feedback for the initial switch of options to a string table. Happy to tweak or adjust if desired here.
This commit is contained in:
@@ -282,7 +282,7 @@ using ArgumentConsumer = CompilerInvocation::ArgumentConsumer;
|
|||||||
#undef OPTTABLE_STR_TABLE_CODE
|
#undef OPTTABLE_STR_TABLE_CODE
|
||||||
|
|
||||||
static llvm::StringRef lookupStrInTable(unsigned Offset) {
|
static llvm::StringRef lookupStrInTable(unsigned Offset) {
|
||||||
return &OptionStrTable[Offset];
|
return OptionStrTable[Offset];
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SIMPLE_ENUM_VALUE_TABLE
|
#define SIMPLE_ENUM_VALUE_TABLE
|
||||||
|
|||||||
@@ -42,6 +42,7 @@
|
|||||||
#include "lldb/Utility/Status.h"
|
#include "lldb/Utility/Status.h"
|
||||||
#include "lldb/Utility/Timer.h"
|
#include "lldb/Utility/Timer.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
|
#include "llvm/ADT/StringTable.h"
|
||||||
#include "llvm/Support/Error.h"
|
#include "llvm/Support/Error.h"
|
||||||
#include "llvm/Support/FileSystem.h"
|
#include "llvm/Support/FileSystem.h"
|
||||||
#include "llvm/Support/Threading.h"
|
#include "llvm/Support/Threading.h"
|
||||||
@@ -1083,7 +1084,7 @@ void PlatformDarwin::AddClangModuleCompilationOptionsForSDKType(
|
|||||||
if (!version.empty() && sdk_type != XcodeSDK::Type::Linux &&
|
if (!version.empty() && sdk_type != XcodeSDK::Type::Linux &&
|
||||||
sdk_type != XcodeSDK::Type::XROS) {
|
sdk_type != XcodeSDK::Type::XROS) {
|
||||||
#define OPTION(PREFIX_OFFSET, NAME_OFFSET, VAR, ...) \
|
#define OPTION(PREFIX_OFFSET, NAME_OFFSET, VAR, ...) \
|
||||||
llvm::StringRef opt_##VAR = &OptionStrTable[NAME_OFFSET]; \
|
llvm::StringRef opt_##VAR = OptionStrTable[NAME_OFFSET]; \
|
||||||
(void)opt_##VAR;
|
(void)opt_##VAR;
|
||||||
#include "clang/Driver/Options.inc"
|
#include "clang/Driver/Options.inc"
|
||||||
#undef OPTION
|
#undef OPTION
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "llvm/ADT/ArrayRef.h"
|
#include "llvm/ADT/ArrayRef.h"
|
||||||
#include "llvm/ADT/SmallString.h"
|
#include "llvm/ADT/SmallString.h"
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
#include "llvm/ADT/StringTable.h"
|
||||||
#include "llvm/Option/OptSpecifier.h"
|
#include "llvm/Option/OptSpecifier.h"
|
||||||
#include "llvm/Support/StringSaver.h"
|
#include "llvm/Support/StringSaver.h"
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@@ -54,7 +55,7 @@ public:
|
|||||||
/// Entry for a single option instance in the option data table.
|
/// Entry for a single option instance in the option data table.
|
||||||
struct Info {
|
struct Info {
|
||||||
unsigned PrefixesOffset;
|
unsigned PrefixesOffset;
|
||||||
unsigned PrefixedNameOffset;
|
StringTable::Offset PrefixedNameOffset;
|
||||||
const char *HelpText;
|
const char *HelpText;
|
||||||
// Help text for specific visibilities. A list of pairs, where each pair
|
// Help text for specific visibilities. A list of pairs, where each pair
|
||||||
// is a list of visibilities and a specific help string for those
|
// is a list of visibilities and a specific help string for those
|
||||||
@@ -80,34 +81,37 @@ public:
|
|||||||
|
|
||||||
bool hasNoPrefix() const { return PrefixesOffset == 0; }
|
bool hasNoPrefix() const { return PrefixesOffset == 0; }
|
||||||
|
|
||||||
unsigned getNumPrefixes(ArrayRef<unsigned> PrefixesTable) const {
|
unsigned getNumPrefixes(ArrayRef<StringTable::Offset> PrefixesTable) const {
|
||||||
return PrefixesTable[PrefixesOffset];
|
// We embed the number of prefixes in the value of the first offset.
|
||||||
|
return PrefixesTable[PrefixesOffset].value();
|
||||||
}
|
}
|
||||||
|
|
||||||
ArrayRef<unsigned>
|
ArrayRef<StringTable::Offset>
|
||||||
getPrefixOffsets(ArrayRef<unsigned> PrefixesTable) const {
|
getPrefixOffsets(ArrayRef<StringTable::Offset> PrefixesTable) const {
|
||||||
return hasNoPrefix() ? ArrayRef<unsigned>()
|
return hasNoPrefix() ? ArrayRef<StringTable::Offset>()
|
||||||
: PrefixesTable.slice(PrefixesOffset + 1,
|
: PrefixesTable.slice(PrefixesOffset + 1,
|
||||||
getNumPrefixes(PrefixesTable));
|
getNumPrefixes(PrefixesTable));
|
||||||
}
|
}
|
||||||
|
|
||||||
void appendPrefixes(const char *StrTable, ArrayRef<unsigned> PrefixesTable,
|
void appendPrefixes(const StringTable &StrTable,
|
||||||
|
ArrayRef<StringTable::Offset> PrefixesTable,
|
||||||
SmallVectorImpl<StringRef> &Prefixes) const {
|
SmallVectorImpl<StringRef> &Prefixes) const {
|
||||||
for (unsigned PrefixOffset : getPrefixOffsets(PrefixesTable))
|
for (auto PrefixOffset : getPrefixOffsets(PrefixesTable))
|
||||||
Prefixes.push_back(&StrTable[PrefixOffset]);
|
Prefixes.push_back(StrTable[PrefixOffset]);
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef getPrefix(const char *StrTable, ArrayRef<unsigned> PrefixesTable,
|
StringRef getPrefix(const StringTable &StrTable,
|
||||||
|
ArrayRef<StringTable::Offset> PrefixesTable,
|
||||||
unsigned PrefixIndex) const {
|
unsigned PrefixIndex) const {
|
||||||
return &StrTable[getPrefixOffsets(PrefixesTable)[PrefixIndex]];
|
return StrTable[getPrefixOffsets(PrefixesTable)[PrefixIndex]];
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef getPrefixedName(const char *StrTable) const {
|
StringRef getPrefixedName(const StringTable &StrTable) const {
|
||||||
return &StrTable[PrefixedNameOffset];
|
return StrTable[PrefixedNameOffset];
|
||||||
}
|
}
|
||||||
|
|
||||||
StringRef getName(const char *StrTable,
|
StringRef getName(const StringTable &StrTable,
|
||||||
ArrayRef<unsigned> PrefixesTable) const {
|
ArrayRef<StringTable::Offset> PrefixesTable) const {
|
||||||
unsigned PrefixLength =
|
unsigned PrefixLength =
|
||||||
hasNoPrefix() ? 0 : getPrefix(StrTable, PrefixesTable, 0).size();
|
hasNoPrefix() ? 0 : getPrefix(StrTable, PrefixesTable, 0).size();
|
||||||
return getPrefixedName(StrTable).drop_front(PrefixLength);
|
return getPrefixedName(StrTable).drop_front(PrefixLength);
|
||||||
@@ -117,13 +121,13 @@ public:
|
|||||||
private:
|
private:
|
||||||
// A unified string table for these options. Individual strings are stored as
|
// A unified string table for these options. Individual strings are stored as
|
||||||
// null terminated C-strings at offsets within this table.
|
// null terminated C-strings at offsets within this table.
|
||||||
const char *StrTable;
|
const StringTable *StrTable;
|
||||||
|
|
||||||
// A table of different sets of prefixes. Each set starts with the number of
|
// A table of different sets of prefixes. Each set starts with the number of
|
||||||
// prefixes in that set followed by that many offsets into the string table
|
// prefixes in that set followed by that many offsets into the string table
|
||||||
// for each of the prefix strings. This is essentially a Pascal-string style
|
// for each of the prefix strings. This is essentially a Pascal-string style
|
||||||
// encoding.
|
// encoding.
|
||||||
ArrayRef<unsigned> PrefixesTable;
|
ArrayRef<StringTable::Offset> PrefixesTable;
|
||||||
|
|
||||||
/// The option information table.
|
/// The option information table.
|
||||||
ArrayRef<Info> OptionInfos;
|
ArrayRef<Info> OptionInfos;
|
||||||
@@ -161,7 +165,8 @@ private:
|
|||||||
protected:
|
protected:
|
||||||
/// Initialize OptTable using Tablegen'ed OptionInfos. Child class must
|
/// Initialize OptTable using Tablegen'ed OptionInfos. Child class must
|
||||||
/// manually call \c buildPrefixChars once they are fully constructed.
|
/// manually call \c buildPrefixChars once they are fully constructed.
|
||||||
OptTable(const char *StrTable, ArrayRef<unsigned> PrefixesTable,
|
OptTable(const StringTable &StrTable,
|
||||||
|
ArrayRef<StringTable::Offset> PrefixesTable,
|
||||||
ArrayRef<Info> OptionInfos, bool IgnoreCase = false);
|
ArrayRef<Info> OptionInfos, bool IgnoreCase = false);
|
||||||
|
|
||||||
/// Build (or rebuild) the PrefixChars member.
|
/// Build (or rebuild) the PrefixChars member.
|
||||||
@@ -171,10 +176,12 @@ public:
|
|||||||
virtual ~OptTable();
|
virtual ~OptTable();
|
||||||
|
|
||||||
/// Return the string table used for option names.
|
/// Return the string table used for option names.
|
||||||
const char *getStrTable() const { return StrTable; }
|
const StringTable &getStrTable() const { return *StrTable; }
|
||||||
|
|
||||||
/// Return the prefixes table used for option names.
|
/// Return the prefixes table used for option names.
|
||||||
ArrayRef<unsigned> getPrefixesTable() const { return PrefixesTable; }
|
ArrayRef<StringTable::Offset> getPrefixesTable() const {
|
||||||
|
return PrefixesTable;
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the total number of option classes.
|
/// Return the total number of option classes.
|
||||||
unsigned getNumOptions() const { return OptionInfos.size(); }
|
unsigned getNumOptions() const { return OptionInfos.size(); }
|
||||||
@@ -187,25 +194,25 @@ public:
|
|||||||
|
|
||||||
/// Lookup the name of the given option.
|
/// Lookup the name of the given option.
|
||||||
StringRef getOptionName(OptSpecifier id) const {
|
StringRef getOptionName(OptSpecifier id) const {
|
||||||
return getInfo(id).getName(StrTable, PrefixesTable);
|
return getInfo(id).getName(*StrTable, PrefixesTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup the prefix of the given option.
|
/// Lookup the prefix of the given option.
|
||||||
StringRef getOptionPrefix(OptSpecifier id) const {
|
StringRef getOptionPrefix(OptSpecifier id) const {
|
||||||
const Info &I = getInfo(id);
|
const Info &I = getInfo(id);
|
||||||
return I.hasNoPrefix() ? StringRef()
|
return I.hasNoPrefix() ? StringRef()
|
||||||
: I.getPrefix(StrTable, PrefixesTable, 0);
|
: I.getPrefix(*StrTable, PrefixesTable, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void appendOptionPrefixes(OptSpecifier id,
|
void appendOptionPrefixes(OptSpecifier id,
|
||||||
SmallVectorImpl<StringRef> &Prefixes) const {
|
SmallVectorImpl<StringRef> &Prefixes) const {
|
||||||
const Info &I = getInfo(id);
|
const Info &I = getInfo(id);
|
||||||
I.appendPrefixes(StrTable, PrefixesTable, Prefixes);
|
I.appendPrefixes(*StrTable, PrefixesTable, Prefixes);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lookup the prefixed name of the given option.
|
/// Lookup the prefixed name of the given option.
|
||||||
StringRef getOptionPrefixedName(OptSpecifier id) const {
|
StringRef getOptionPrefixedName(OptSpecifier id) const {
|
||||||
return getInfo(id).getPrefixedName(StrTable);
|
return getInfo(id).getPrefixedName(*StrTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the kind of the given option.
|
/// Get the kind of the given option.
|
||||||
@@ -418,19 +425,21 @@ private:
|
|||||||
/// Specialization of OptTable
|
/// Specialization of OptTable
|
||||||
class GenericOptTable : public OptTable {
|
class GenericOptTable : public OptTable {
|
||||||
protected:
|
protected:
|
||||||
GenericOptTable(const char *StrTable, ArrayRef<unsigned> PrefixesTable,
|
GenericOptTable(const StringTable &StrTable,
|
||||||
|
ArrayRef<StringTable::Offset> PrefixesTable,
|
||||||
ArrayRef<Info> OptionInfos, bool IgnoreCase = false);
|
ArrayRef<Info> OptionInfos, bool IgnoreCase = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
class PrecomputedOptTable : public OptTable {
|
class PrecomputedOptTable : public OptTable {
|
||||||
protected:
|
protected:
|
||||||
PrecomputedOptTable(const char *StrTable, ArrayRef<unsigned> PrefixesTable,
|
PrecomputedOptTable(const StringTable &StrTable,
|
||||||
|
ArrayRef<StringTable::Offset> PrefixesTable,
|
||||||
ArrayRef<Info> OptionInfos,
|
ArrayRef<Info> OptionInfos,
|
||||||
ArrayRef<unsigned> PrefixesUnionOffsets,
|
ArrayRef<StringTable::Offset> PrefixesUnionOffsets,
|
||||||
bool IgnoreCase = false)
|
bool IgnoreCase = false)
|
||||||
: OptTable(StrTable, PrefixesTable, OptionInfos, IgnoreCase) {
|
: OptTable(StrTable, PrefixesTable, OptionInfos, IgnoreCase) {
|
||||||
for (unsigned PrefixOffset : PrefixesUnionOffsets)
|
for (auto PrefixOffset : PrefixesUnionOffsets)
|
||||||
PrefixesUnion.push_back(&StrTable[PrefixOffset]);
|
PrefixesUnion.push_back(StrTable[PrefixOffset]);
|
||||||
buildPrefixChars();
|
buildPrefixChars();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,11 +33,12 @@ using namespace llvm::opt;
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
struct OptNameLess {
|
struct OptNameLess {
|
||||||
const char *StrTable;
|
const StringTable *StrTable;
|
||||||
ArrayRef<unsigned> PrefixesTable;
|
ArrayRef<StringTable::Offset> PrefixesTable;
|
||||||
|
|
||||||
explicit OptNameLess(const char *StrTable, ArrayRef<unsigned> PrefixesTable)
|
explicit OptNameLess(const StringTable &StrTable,
|
||||||
: StrTable(StrTable), PrefixesTable(PrefixesTable) {}
|
ArrayRef<StringTable::Offset> PrefixesTable)
|
||||||
|
: StrTable(&StrTable), PrefixesTable(PrefixesTable) {}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
inline bool operator()(const OptTable::Info &A,
|
inline bool operator()(const OptTable::Info &A,
|
||||||
@@ -45,13 +46,13 @@ struct OptNameLess {
|
|||||||
if (&A == &B)
|
if (&A == &B)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (int Cmp = StrCmpOptionName(A.getName(StrTable, PrefixesTable),
|
if (int Cmp = StrCmpOptionName(A.getName(*StrTable, PrefixesTable),
|
||||||
B.getName(StrTable, PrefixesTable)))
|
B.getName(*StrTable, PrefixesTable)))
|
||||||
return Cmp < 0;
|
return Cmp < 0;
|
||||||
|
|
||||||
SmallVector<StringRef, 8> APrefixes, BPrefixes;
|
SmallVector<StringRef, 8> APrefixes, BPrefixes;
|
||||||
A.appendPrefixes(StrTable, PrefixesTable, APrefixes);
|
A.appendPrefixes(*StrTable, PrefixesTable, APrefixes);
|
||||||
B.appendPrefixes(StrTable, PrefixesTable, BPrefixes);
|
B.appendPrefixes(*StrTable, PrefixesTable, BPrefixes);
|
||||||
|
|
||||||
if (int Cmp = StrCmpOptionPrefixes(APrefixes, BPrefixes))
|
if (int Cmp = StrCmpOptionPrefixes(APrefixes, BPrefixes))
|
||||||
return Cmp < 0;
|
return Cmp < 0;
|
||||||
@@ -68,7 +69,7 @@ struct OptNameLess {
|
|||||||
// Support lower_bound between info and an option name.
|
// Support lower_bound between info and an option name.
|
||||||
inline bool operator()(const OptTable::Info &I, StringRef Name) const {
|
inline bool operator()(const OptTable::Info &I, StringRef Name) const {
|
||||||
// Do not fallback to case sensitive comparison.
|
// Do not fallback to case sensitive comparison.
|
||||||
return StrCmpOptionName(I.getName(StrTable, PrefixesTable), Name, false) <
|
return StrCmpOptionName(I.getName(*StrTable, PrefixesTable), Name, false) <
|
||||||
0;
|
0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -76,9 +77,10 @@ struct OptNameLess {
|
|||||||
|
|
||||||
OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
|
OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
|
||||||
|
|
||||||
OptTable::OptTable(const char *StrTable, ArrayRef<unsigned> PrefixesTable,
|
OptTable::OptTable(const StringTable &StrTable,
|
||||||
|
ArrayRef<StringTable::Offset> PrefixesTable,
|
||||||
ArrayRef<Info> OptionInfos, bool IgnoreCase)
|
ArrayRef<Info> OptionInfos, bool IgnoreCase)
|
||||||
: StrTable(StrTable), PrefixesTable(PrefixesTable),
|
: StrTable(&StrTable), PrefixesTable(PrefixesTable),
|
||||||
OptionInfos(OptionInfos), IgnoreCase(IgnoreCase) {
|
OptionInfos(OptionInfos), IgnoreCase(IgnoreCase) {
|
||||||
// Explicitly zero initialize the error to work around a bug in array
|
// Explicitly zero initialize the error to work around a bug in array
|
||||||
// value-initialization on MinGW with gcc 4.3.5.
|
// value-initialization on MinGW with gcc 4.3.5.
|
||||||
@@ -151,13 +153,13 @@ static bool isInput(const ArrayRef<StringRef> &Prefixes, StringRef Arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// \returns Matched size. 0 means no match.
|
/// \returns Matched size. 0 means no match.
|
||||||
static unsigned matchOption(const char *StrTable,
|
static unsigned matchOption(const StringTable &StrTable,
|
||||||
ArrayRef<unsigned> PrefixesTable,
|
ArrayRef<StringTable::Offset> PrefixesTable,
|
||||||
const OptTable::Info *I, StringRef Str,
|
const OptTable::Info *I, StringRef Str,
|
||||||
bool IgnoreCase) {
|
bool IgnoreCase) {
|
||||||
StringRef Name = I->getName(StrTable, PrefixesTable);
|
StringRef Name = I->getName(StrTable, PrefixesTable);
|
||||||
for (unsigned PrefixOffset : I->getPrefixOffsets(PrefixesTable)) {
|
for (auto PrefixOffset : I->getPrefixOffsets(PrefixesTable)) {
|
||||||
StringRef Prefix = &StrTable[PrefixOffset];
|
StringRef Prefix = StrTable[PrefixOffset];
|
||||||
if (Str.starts_with(Prefix)) {
|
if (Str.starts_with(Prefix)) {
|
||||||
StringRef Rest = Str.substr(Prefix.size());
|
StringRef Rest = Str.substr(Prefix.size());
|
||||||
bool Matched = IgnoreCase ? Rest.starts_with_insensitive(Name)
|
bool Matched = IgnoreCase ? Rest.starts_with_insensitive(Name)
|
||||||
@@ -170,13 +172,13 @@ static unsigned matchOption(const char *StrTable,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Returns true if one of the Prefixes + In.Names matches Option
|
// Returns true if one of the Prefixes + In.Names matches Option
|
||||||
static bool optionMatches(const char *StrTable,
|
static bool optionMatches(const StringTable &StrTable,
|
||||||
ArrayRef<unsigned> PrefixesTable,
|
ArrayRef<StringTable::Offset> PrefixesTable,
|
||||||
const OptTable::Info &In, StringRef Option) {
|
const OptTable::Info &In, StringRef Option) {
|
||||||
StringRef Name = In.getName(StrTable, PrefixesTable);
|
StringRef Name = In.getName(StrTable, PrefixesTable);
|
||||||
if (Option.consume_back(Name))
|
if (Option.consume_back(Name))
|
||||||
for (unsigned PrefixOffset : In.getPrefixOffsets(PrefixesTable))
|
for (auto PrefixOffset : In.getPrefixOffsets(PrefixesTable))
|
||||||
if (Option == &StrTable[PrefixOffset])
|
if (Option == StrTable[PrefixOffset])
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -189,7 +191,7 @@ OptTable::suggestValueCompletions(StringRef Option, StringRef Arg) const {
|
|||||||
// Search all options and return possible values.
|
// Search all options and return possible values.
|
||||||
for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; I++) {
|
for (size_t I = FirstSearchableIndex, E = OptionInfos.size(); I < E; I++) {
|
||||||
const Info &In = OptionInfos[I];
|
const Info &In = OptionInfos[I];
|
||||||
if (!In.Values || !optionMatches(StrTable, PrefixesTable, In, Option))
|
if (!In.Values || !optionMatches(*StrTable, PrefixesTable, In, Option))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
SmallVector<StringRef, 8> Candidates;
|
SmallVector<StringRef, 8> Candidates;
|
||||||
@@ -217,9 +219,9 @@ OptTable::findByPrefix(StringRef Cur, Visibility VisibilityMask,
|
|||||||
if (In.Flags & DisableFlags)
|
if (In.Flags & DisableFlags)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
StringRef Name = In.getName(StrTable, PrefixesTable);
|
StringRef Name = In.getName(*StrTable, PrefixesTable);
|
||||||
for (unsigned PrefixOffset : In.getPrefixOffsets(PrefixesTable)) {
|
for (auto PrefixOffset : In.getPrefixOffsets(PrefixesTable)) {
|
||||||
StringRef Prefix = &StrTable[PrefixOffset];
|
StringRef Prefix = (*StrTable)[PrefixOffset];
|
||||||
std::string S = (Twine(Prefix) + Name + "\t").str();
|
std::string S = (Twine(Prefix) + Name + "\t").str();
|
||||||
if (In.HelpText)
|
if (In.HelpText)
|
||||||
S += In.HelpText;
|
S += In.HelpText;
|
||||||
@@ -271,7 +273,7 @@ unsigned OptTable::internalFindNearest(
|
|||||||
|
|
||||||
for (const Info &CandidateInfo :
|
for (const Info &CandidateInfo :
|
||||||
ArrayRef<Info>(OptionInfos).drop_front(FirstSearchableIndex)) {
|
ArrayRef<Info>(OptionInfos).drop_front(FirstSearchableIndex)) {
|
||||||
StringRef CandidateName = CandidateInfo.getName(StrTable, PrefixesTable);
|
StringRef CandidateName = CandidateInfo.getName(*StrTable, PrefixesTable);
|
||||||
|
|
||||||
// We can eliminate some option prefix/name pairs as candidates right away:
|
// We can eliminate some option prefix/name pairs as candidates right away:
|
||||||
// * Ignore option candidates with empty names, such as "--", or names
|
// * Ignore option candidates with empty names, such as "--", or names
|
||||||
@@ -304,9 +306,9 @@ unsigned OptTable::internalFindNearest(
|
|||||||
// Consider each possible prefix for each candidate to find the most
|
// Consider each possible prefix for each candidate to find the most
|
||||||
// appropriate one. For example, if a user asks for "--helm", suggest
|
// appropriate one. For example, if a user asks for "--helm", suggest
|
||||||
// "--help" over "-help".
|
// "--help" over "-help".
|
||||||
for (unsigned CandidatePrefixOffset :
|
for (auto CandidatePrefixOffset :
|
||||||
CandidateInfo.getPrefixOffsets(PrefixesTable)) {
|
CandidateInfo.getPrefixOffsets(PrefixesTable)) {
|
||||||
StringRef CandidatePrefix = &StrTable[CandidatePrefixOffset];
|
StringRef CandidatePrefix = (*StrTable)[CandidatePrefixOffset];
|
||||||
// If Candidate and NormalizedName have more than 'BestDistance'
|
// If Candidate and NormalizedName have more than 'BestDistance'
|
||||||
// characters of difference, no need to compute the edit distance, it's
|
// characters of difference, no need to compute the edit distance, it's
|
||||||
// going to be greater than BestDistance. Don't bother computing Candidate
|
// going to be greater than BestDistance. Don't bother computing Candidate
|
||||||
@@ -359,14 +361,14 @@ std::unique_ptr<Arg> OptTable::parseOneArgGrouped(InputArgList &Args,
|
|||||||
StringRef Name = Str.ltrim(PrefixChars);
|
StringRef Name = Str.ltrim(PrefixChars);
|
||||||
const Info *Start =
|
const Info *Start =
|
||||||
std::lower_bound(OptionInfos.data() + FirstSearchableIndex, End, Name,
|
std::lower_bound(OptionInfos.data() + FirstSearchableIndex, End, Name,
|
||||||
OptNameLess(StrTable, PrefixesTable));
|
OptNameLess(*StrTable, PrefixesTable));
|
||||||
const Info *Fallback = nullptr;
|
const Info *Fallback = nullptr;
|
||||||
unsigned Prev = Index;
|
unsigned Prev = Index;
|
||||||
|
|
||||||
// Search for the option which matches Str.
|
// Search for the option which matches Str.
|
||||||
for (; Start != End; ++Start) {
|
for (; Start != End; ++Start) {
|
||||||
unsigned ArgSize =
|
unsigned ArgSize =
|
||||||
matchOption(StrTable, PrefixesTable, Start, Str, IgnoreCase);
|
matchOption(*StrTable, PrefixesTable, Start, Str, IgnoreCase);
|
||||||
if (!ArgSize)
|
if (!ArgSize)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -449,7 +451,7 @@ std::unique_ptr<Arg> OptTable::internalParseOneArg(
|
|||||||
|
|
||||||
// Search for the first next option which could be a prefix.
|
// Search for the first next option which could be a prefix.
|
||||||
Start =
|
Start =
|
||||||
std::lower_bound(Start, End, Name, OptNameLess(StrTable, PrefixesTable));
|
std::lower_bound(Start, End, Name, OptNameLess(*StrTable, PrefixesTable));
|
||||||
|
|
||||||
// Options are stored in sorted order, with '\0' at the end of the
|
// Options are stored in sorted order, with '\0' at the end of the
|
||||||
// alphabet. Since the only options which can accept a string must
|
// alphabet. Since the only options which can accept a string must
|
||||||
@@ -464,7 +466,7 @@ std::unique_ptr<Arg> OptTable::internalParseOneArg(
|
|||||||
// Scan for first option which is a proper prefix.
|
// Scan for first option which is a proper prefix.
|
||||||
for (; Start != End; ++Start)
|
for (; Start != End; ++Start)
|
||||||
if ((ArgSize =
|
if ((ArgSize =
|
||||||
matchOption(StrTable, PrefixesTable, Start, Str, IgnoreCase)))
|
matchOption(*StrTable, PrefixesTable, Start, Str, IgnoreCase)))
|
||||||
break;
|
break;
|
||||||
if (Start == End)
|
if (Start == End)
|
||||||
break;
|
break;
|
||||||
@@ -787,15 +789,15 @@ void OptTable::internalPrintHelp(
|
|||||||
OS.flush();
|
OS.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericOptTable::GenericOptTable(const char *StrTable,
|
GenericOptTable::GenericOptTable(const StringTable &StrTable,
|
||||||
ArrayRef<unsigned> PrefixesTable,
|
ArrayRef<StringTable::Offset> PrefixesTable,
|
||||||
ArrayRef<Info> OptionInfos, bool IgnoreCase)
|
ArrayRef<Info> OptionInfos, bool IgnoreCase)
|
||||||
: OptTable(StrTable, PrefixesTable, OptionInfos, IgnoreCase) {
|
: OptTable(StrTable, PrefixesTable, OptionInfos, IgnoreCase) {
|
||||||
|
|
||||||
std::set<StringRef> TmpPrefixesUnion;
|
std::set<StringRef> TmpPrefixesUnion;
|
||||||
for (auto const &Info : OptionInfos.drop_front(FirstSearchableIndex))
|
for (auto const &Info : OptionInfos.drop_front(FirstSearchableIndex))
|
||||||
for (unsigned PrefixOffset : Info.getPrefixOffsets(PrefixesTable))
|
for (auto PrefixOffset : Info.getPrefixOffsets(PrefixesTable))
|
||||||
TmpPrefixesUnion.insert(StringRef(&StrTable[PrefixOffset]));
|
TmpPrefixesUnion.insert(StrTable[PrefixOffset]);
|
||||||
PrefixesUnion.append(TmpPrefixesUnion.begin(), TmpPrefixesUnion.end());
|
PrefixesUnion.append(TmpPrefixesUnion.begin(), TmpPrefixesUnion.end());
|
||||||
buildPrefixChars();
|
buildPrefixChars();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,8 @@ namespace {
|
|||||||
|
|
||||||
class CommonOptTable : public opt::GenericOptTable {
|
class CommonOptTable : public opt::GenericOptTable {
|
||||||
public:
|
public:
|
||||||
CommonOptTable(const char *StrTable, ArrayRef<unsigned> PrefixesTable,
|
CommonOptTable(const StringTable &StrTable,
|
||||||
|
ArrayRef<StringTable::Offset> PrefixesTable,
|
||||||
ArrayRef<Info> OptionInfos, const char *Usage,
|
ArrayRef<Info> OptionInfos, const char *Usage,
|
||||||
const char *Description)
|
const char *Description)
|
||||||
: opt::GenericOptTable(StrTable, PrefixesTable, OptionInfos),
|
: opt::GenericOptTable(StrTable, PrefixesTable, OptionInfos),
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
#include "llvm/ADT/StringRef.h"
|
#include "llvm/ADT/StringRef.h"
|
||||||
|
#include "llvm/ADT/StringTable.h"
|
||||||
#include "gtest/gtest.h"
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
#define OPTTABLE_STR_TABLE_CODE
|
#define OPTTABLE_STR_TABLE_CODE
|
||||||
@@ -20,7 +21,7 @@ struct OptionWithMarshallingInfo {
|
|||||||
const char *ImpliedValue;
|
const char *ImpliedValue;
|
||||||
|
|
||||||
llvm::StringRef getPrefixedName() const {
|
llvm::StringRef getPrefixedName() const {
|
||||||
return &OptionStrTable[PrefixedNameOffset];
|
return OptionStrTable[PrefixedNameOffset];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -303,15 +303,17 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) {
|
|||||||
OS << "/////////\n";
|
OS << "/////////\n";
|
||||||
OS << "// String table\n\n";
|
OS << "// String table\n\n";
|
||||||
OS << "#ifdef OPTTABLE_STR_TABLE_CODE\n";
|
OS << "#ifdef OPTTABLE_STR_TABLE_CODE\n";
|
||||||
Table.EmitStringLiteralDef(OS, "static constexpr char OptionStrTable[]",
|
Table.EmitStringLiteralDef(
|
||||||
/*Indent=*/"");
|
OS, "static constexpr llvm::StringTable OptionStrTable",
|
||||||
|
/*Indent=*/"");
|
||||||
OS << "#endif // OPTTABLE_STR_TABLE_CODE\n\n";
|
OS << "#endif // OPTTABLE_STR_TABLE_CODE\n\n";
|
||||||
|
|
||||||
// Dump prefixes.
|
// Dump prefixes.
|
||||||
OS << "/////////\n";
|
OS << "/////////\n";
|
||||||
OS << "// Prefixes\n\n";
|
OS << "// Prefixes\n\n";
|
||||||
OS << "#ifdef OPTTABLE_PREFIXES_TABLE_CODE\n";
|
OS << "#ifdef OPTTABLE_PREFIXES_TABLE_CODE\n";
|
||||||
OS << "static constexpr unsigned OptionPrefixesTable[] = {\n";
|
OS << "static constexpr llvm::StringTable::Offset OptionPrefixesTable[] = "
|
||||||
|
"{\n";
|
||||||
{
|
{
|
||||||
// Ensure the first prefix set is always empty.
|
// Ensure the first prefix set is always empty.
|
||||||
assert(!Prefixes.empty() &&
|
assert(!Prefixes.empty() &&
|
||||||
@@ -339,7 +341,8 @@ static void emitOptionParser(const RecordKeeper &Records, raw_ostream &OS) {
|
|||||||
OS << "/////////\n";
|
OS << "/////////\n";
|
||||||
OS << "// Prefix Union\n\n";
|
OS << "// Prefix Union\n\n";
|
||||||
OS << "#ifdef OPTTABLE_PREFIXES_UNION_CODE\n";
|
OS << "#ifdef OPTTABLE_PREFIXES_UNION_CODE\n";
|
||||||
OS << "static constexpr unsigned OptionPrefixesUnion[] = {\n";
|
OS << "static constexpr llvm::StringTable::Offset OptionPrefixesUnion[] = "
|
||||||
|
"{\n";
|
||||||
{
|
{
|
||||||
llvm::ListSeparator Sep(", ");
|
llvm::ListSeparator Sep(", ");
|
||||||
for (auto Prefix : PrefixesUnion)
|
for (auto Prefix : PrefixesUnion)
|
||||||
|
|||||||
Reference in New Issue
Block a user