summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/OptTable.cpp')
-rw-r--r--contrib/llvm/tools/clang/lib/Driver/OptTable.cpp158
1 files changed, 80 insertions, 78 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp b/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp
index a3e38b2..6e7b695 100644
--- a/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp
+++ b/contrib/llvm/tools/clang/lib/Driver/OptTable.cpp
@@ -11,6 +11,7 @@
#include "clang/Driver/Arg.h"
#include "clang/Driver/ArgList.h"
#include "clang/Driver/Option.h"
+#include "clang/Driver/Options.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/ErrorHandling.h"
#include <algorithm>
@@ -54,6 +55,13 @@ static inline bool operator<(const OptTable::Info &A, const OptTable::Info &B) {
if (int N = StrCmpOptionName(A.Name, B.Name))
return N == -1;
+ for (const char * const *APre = A.Prefixes,
+ * const *BPre = B.Prefixes;
+ *APre != 0 && *BPre != 0; ++APre, ++BPre) {
+ if (int N = StrCmpOptionName(*APre, *BPre))
+ return N == -1;
+ }
+
// Names are the same, check that classes are in order; exactly one
// should be joined, and it should succeed the other.
assert(((A.Kind == Option::JoinedClass) ^ (B.Kind == Option::JoinedClass)) &&
@@ -78,23 +86,24 @@ OptSpecifier::OptSpecifier(const Option *Opt) : ID(Opt->getID()) {}
//
OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos)
- : OptionInfos(_OptionInfos), NumOptionInfos(_NumOptionInfos),
- Options(new Option*[NumOptionInfos]),
- TheInputOption(0), TheUnknownOption(0), FirstSearchableIndex(0)
+ : OptionInfos(_OptionInfos),
+ NumOptionInfos(_NumOptionInfos),
+ TheInputOptionID(0),
+ TheUnknownOptionID(0),
+ FirstSearchableIndex(0)
{
// Explicitly zero initialize the error to work around a bug in array
// value-initialization on MinGW with gcc 4.3.5.
- memset(Options, 0, sizeof(*Options) * NumOptionInfos);
// Find start of normal options.
for (unsigned i = 0, e = getNumOptions(); i != e; ++i) {
unsigned Kind = getInfo(i + 1).Kind;
if (Kind == Option::InputClass) {
- assert(!TheInputOption && "Cannot have multiple input options!");
- TheInputOption = getOption(i + 1);
+ assert(!TheInputOptionID && "Cannot have multiple input options!");
+ TheInputOptionID = getInfo(i + 1).ID;
} else if (Kind == Option::UnknownClass) {
- assert(!TheUnknownOption && "Cannot have multiple input options!");
- TheUnknownOption = getOption(i + 1);
+ assert(!TheUnknownOptionID && "Cannot have multiple unknown options!");
+ TheUnknownOptionID = getInfo(i + 1).ID;
} else if (Kind != Option::GroupClass) {
FirstSearchableIndex = i;
break;
@@ -115,91 +124,80 @@ OptTable::OptTable(const Info *_OptionInfos, unsigned _NumOptionInfos)
// Check that options are in order.
for (unsigned i = FirstSearchableIndex+1, e = getNumOptions(); i != e; ++i) {
if (!(getInfo(i) < getInfo(i + 1))) {
- getOption(i)->dump();
- getOption(i + 1)->dump();
+ getOption(i).dump();
+ getOption(i + 1).dump();
llvm_unreachable("Options are not in order!");
}
}
#endif
+
+ // Build prefixes.
+ for (unsigned i = FirstSearchableIndex+1, e = getNumOptions(); i != e; ++i) {
+ if (const char *const *P = getInfo(i).Prefixes) {
+ for (; *P != 0; ++P) {
+ PrefixesUnion.insert(*P);
+ }
+ }
+ }
+
+ // Build prefix chars.
+ for (llvm::StringSet<>::const_iterator I = PrefixesUnion.begin(),
+ E = PrefixesUnion.end(); I != E; ++I) {
+ StringRef Prefix = I->getKey();
+ for (StringRef::const_iterator C = Prefix.begin(), CE = Prefix.end();
+ C != CE; ++C)
+ if (std::find(PrefixChars.begin(), PrefixChars.end(), *C)
+ == PrefixChars.end())
+ PrefixChars.push_back(*C);
+ }
}
OptTable::~OptTable() {
- for (unsigned i = 0, e = getNumOptions(); i != e; ++i)
- delete Options[i];
- delete[] Options;
}
-Option *OptTable::CreateOption(unsigned id) const {
- const Info &info = getInfo(id);
- const OptionGroup *Group =
- cast_or_null<OptionGroup>(getOption(info.GroupID));
- const Option *Alias = getOption(info.AliasID);
-
- Option *Opt = 0;
- switch (info.Kind) {
- case Option::InputClass:
- Opt = new InputOption(id); break;
- case Option::UnknownClass:
- Opt = new UnknownOption(id); break;
- case Option::GroupClass:
- Opt = new OptionGroup(id, info.Name, Group); break;
- case Option::FlagClass:
- Opt = new FlagOption(id, info.Name, Group, Alias); break;
- case Option::JoinedClass:
- Opt = new JoinedOption(id, info.Name, Group, Alias); break;
- case Option::SeparateClass:
- Opt = new SeparateOption(id, info.Name, Group, Alias); break;
- case Option::CommaJoinedClass:
- Opt = new CommaJoinedOption(id, info.Name, Group, Alias); break;
- case Option::MultiArgClass:
- Opt = new MultiArgOption(id, info.Name, Group, Alias, info.Param); break;
- case Option::JoinedOrSeparateClass:
- Opt = new JoinedOrSeparateOption(id, info.Name, Group, Alias); break;
- case Option::JoinedAndSeparateClass:
- Opt = new JoinedAndSeparateOption(id, info.Name, Group, Alias); break;
- }
+const Option OptTable::getOption(OptSpecifier Opt) const {
+ unsigned id = Opt.getID();
+ if (id == 0)
+ return Option(0, 0);
+ assert((unsigned) (id - 1) < getNumOptions() && "Invalid ID.");
+ return Option(&getInfo(id), this);
+}
- if (info.Flags & DriverOption)
- Opt->setDriverOption(true);
- if (info.Flags & LinkerInput)
- Opt->setLinkerInput(true);
- if (info.Flags & NoArgumentUnused)
- Opt->setNoArgumentUnused(true);
- if (info.Flags & NoForward)
- Opt->setNoForward(true);
- if (info.Flags & RenderAsInput)
- Opt->setNoOptAsInput(true);
- if (info.Flags & RenderJoined) {
- assert((info.Kind == Option::JoinedOrSeparateClass ||
- info.Kind == Option::SeparateClass) && "Invalid option.");
- Opt->setRenderStyle(Option::RenderJoinedStyle);
- }
- if (info.Flags & RenderSeparate) {
- assert((info.Kind == Option::JoinedOrSeparateClass ||
- info.Kind == Option::JoinedClass) && "Invalid option.");
- Opt->setRenderStyle(Option::RenderSeparateStyle);
- }
- if (info.Flags & Unsupported)
- Opt->setUnsupported(true);
- if (info.Flags & CC1Option)
- Opt->setIsCC1Option(true);
+static bool isInput(const llvm::StringSet<> &Prefixes, StringRef Arg) {
+ if (Arg == "-")
+ return true;
+ for (llvm::StringSet<>::const_iterator I = Prefixes.begin(),
+ E = Prefixes.end(); I != E; ++I)
+ if (Arg.startswith(I->getKey()))
+ return false;
+ return true;
+}
- return Opt;
+/// \returns Matched size. 0 means no match.
+static unsigned matchOption(const OptTable::Info *I, StringRef Str) {
+ for (const char * const *Pre = I->Prefixes; *Pre != 0; ++Pre) {
+ StringRef Prefix(*Pre);
+ if (Str.startswith(Prefix) && Str.substr(Prefix.size()).startswith(I->Name))
+ return Prefix.size() + StringRef(I->Name).size();
+ }
+ return 0;
}
Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index) const {
unsigned Prev = Index;
const char *Str = Args.getArgString(Index);
- // Anything that doesn't start with '-' is an input, as is '-' itself.
- if (Str[0] != '-' || Str[1] == '\0')
- return new Arg(TheInputOption, Index++, Str);
+ // Anything that doesn't start with PrefixesUnion is an input, as is '-'
+ // itself.
+ if (isInput(PrefixesUnion, Str))
+ return new Arg(getOption(TheInputOptionID), Str, Index++, Str);
const Info *Start = OptionInfos + FirstSearchableIndex;
const Info *End = OptionInfos + getNumOptions();
+ StringRef Name = StringRef(Str).ltrim(PrefixChars);
// Search for the first next option which could be a prefix.
- Start = std::lower_bound(Start, End, Str);
+ Start = std::lower_bound(Start, End, Name.data());
// Options are stored in sorted order, with '\0' at the end of the
// alphabet. Since the only options which can accept a string must
@@ -210,15 +208,16 @@ Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index) const {
// blanking on the simplest way to make it fast. We can solve this
// problem when we move to TableGen.
for (; Start != End; ++Start) {
+ unsigned ArgSize = 0;
// Scan for first option which is a proper prefix.
for (; Start != End; ++Start)
- if (memcmp(Str, Start->Name, strlen(Start->Name)) == 0)
+ if ((ArgSize = matchOption(Start, Str)))
break;
if (Start == End)
break;
// See if this option matches.
- if (Arg *A = getOption(Start - OptionInfos + 1)->accept(Args, Index))
+ if (Arg *A = Option(Start, this).accept(Args, Index, ArgSize))
return A;
// Otherwise, see if this argument was missing values.
@@ -226,7 +225,7 @@ Arg *OptTable::ParseOneArg(const ArgList &Args, unsigned &Index) const {
return 0;
}
- return new Arg(TheUnknownOption, Index++, Str);
+ return new Arg(getOption(TheUnknownOptionID), Str, Index++, Str);
}
InputArgList *OptTable::ParseArgs(const char* const *ArgBegin,
@@ -266,10 +265,11 @@ InputArgList *OptTable::ParseArgs(const char* const *ArgBegin,
}
static std::string getOptionHelpName(const OptTable &Opts, OptSpecifier Id) {
- std::string Name = Opts.getOptionName(Id);
+ const Option O = Opts.getOption(Id);
+ std::string Name = O.getPrefixedName();
// Add metavar, if used.
- switch (Opts.getOptionKind(Id)) {
+ switch (O.getKind()) {
case Option::GroupClass: case Option::InputClass: case Option::UnknownClass:
llvm_unreachable("Invalid option with help text.");
@@ -346,7 +346,8 @@ static const char *getOptionHelpGroup(const OptTable &Opts, OptSpecifier Id) {
}
void OptTable::PrintHelp(raw_ostream &OS, const char *Name,
- const char *Title, bool ShowHidden) const {
+ const char *Title, unsigned short FlagsToInclude,
+ unsigned short FlagsToExclude) const {
OS << "OVERVIEW: " << Title << "\n";
OS << '\n';
OS << "USAGE: " << Name << " [options] <inputs>\n";
@@ -365,7 +366,8 @@ void OptTable::PrintHelp(raw_ostream &OS, const char *Name,
if (getOptionKind(Id) == Option::GroupClass)
continue;
- if (!ShowHidden && isOptionHelpHidden(Id))
+ if ((FlagsToInclude && !(getInfo(Id).Flags & FlagsToInclude)) ||
+ getInfo(Id).Flags & FlagsToExclude)
continue;
if (const char *Text = getOptionHelpText(Id)) {
OpenPOWER on IntegriCloud