LLVM  3.7.0
Option.cpp
Go to the documentation of this file.
1 //===--- Option.cpp - Abstract Driver Options -----------------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "llvm/Option/Option.h"
11 #include "llvm/ADT/Twine.h"
12 #include "llvm/Option/Arg.h"
13 #include "llvm/Option/ArgList.h"
16 #include <algorithm>
17 #include <cassert>
18 
19 using namespace llvm;
20 using namespace llvm::opt;
21 
23  : Info(info), Owner(owner) {
24 
25  // Multi-level aliases are not supported. This just simplifies option
26  // tracking, it is not an inherent limitation.
27  assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) &&
28  "Multi-level aliases are not supported.");
29 
30  if (Info && getAliasArgs()) {
31  assert(getAlias().isValid() && "Only alias options can have alias args.");
32  assert(getKind() == FlagClass && "Only Flag aliases can have alias args.");
33  assert(getAlias().getKind() != FlagClass &&
34  "Cannot provide alias args to a flag option.");
35  }
36 }
37 
38 void Option::dump() const {
39  llvm::errs() << "<";
40  switch (getKind()) {
41 #define P(N) case N: llvm::errs() << #N; break
42  P(GroupClass);
43  P(InputClass);
44  P(UnknownClass);
45  P(FlagClass);
46  P(JoinedClass);
53 #undef P
54  }
55 
56  if (Info->Prefixes) {
57  llvm::errs() << " Prefixes:[";
58  for (const char * const *Pre = Info->Prefixes; *Pre != nullptr; ++Pre) {
59  llvm::errs() << '"' << *Pre << (*(Pre + 1) == nullptr ? "\"" : "\", ");
60  }
61  llvm::errs() << ']';
62  }
63 
64  llvm::errs() << " Name:\"" << getName() << '"';
65 
66  const Option Group = getGroup();
67  if (Group.isValid()) {
68  llvm::errs() << " Group:";
69  Group.dump();
70  }
71 
72  const Option Alias = getAlias();
73  if (Alias.isValid()) {
74  llvm::errs() << " Alias:";
75  Alias.dump();
76  }
77 
78  if (getKind() == MultiArgClass)
79  llvm::errs() << " NumArgs:" << getNumArgs();
80 
81  llvm::errs() << ">\n";
82 }
83 
84 bool Option::matches(OptSpecifier Opt) const {
85  // Aliases are never considered in matching, look through them.
86  const Option Alias = getAlias();
87  if (Alias.isValid())
88  return Alias.matches(Opt);
89 
90  // Check exact match.
91  if (getID() == Opt.getID())
92  return true;
93 
94  const Option Group = getGroup();
95  if (Group.isValid())
96  return Group.matches(Opt);
97  return false;
98 }
99 
101  unsigned &Index,
102  unsigned ArgSize) const {
103  const Option &UnaliasedOption = getUnaliasedOption();
104  StringRef Spelling;
105  // If the option was an alias, get the spelling from the unaliased one.
106  if (getID() == UnaliasedOption.getID()) {
107  Spelling = StringRef(Args.getArgString(Index), ArgSize);
108  } else {
109  Spelling = Args.MakeArgString(Twine(UnaliasedOption.getPrefix()) +
110  Twine(UnaliasedOption.getName()));
111  }
112 
113  switch (getKind()) {
114  case FlagClass: {
115  if (ArgSize != strlen(Args.getArgString(Index)))
116  return nullptr;
117 
118  Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
119  if (getAliasArgs()) {
120  const char *Val = getAliasArgs();
121  while (*Val != '\0') {
122  A->getValues().push_back(Val);
123 
124  // Move past the '\0' to the next argument.
125  Val += strlen(Val) + 1;
126  }
127  }
128 
129  if (UnaliasedOption.getKind() == JoinedClass && !getAliasArgs())
130  // A Flag alias for a Joined option must provide an argument.
131  A->getValues().push_back("");
132 
133  return A;
134  }
135  case JoinedClass: {
136  const char *Value = Args.getArgString(Index) + ArgSize;
137  return new Arg(UnaliasedOption, Spelling, Index++, Value);
138  }
139  case CommaJoinedClass: {
140  // Always matches.
141  const char *Str = Args.getArgString(Index) + ArgSize;
142  Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
143 
144  // Parse out the comma separated values.
145  const char *Prev = Str;
146  for (;; ++Str) {
147  char c = *Str;
148 
149  if (!c || c == ',') {
150  if (Prev != Str) {
151  char *Value = new char[Str - Prev + 1];
152  memcpy(Value, Prev, Str - Prev);
153  Value[Str - Prev] = '\0';
154  A->getValues().push_back(Value);
155  }
156 
157  if (!c)
158  break;
159 
160  Prev = Str + 1;
161  }
162  }
163  A->setOwnsValues(true);
164 
165  return A;
166  }
167  case SeparateClass:
168  // Matches iff this is an exact match.
169  // FIXME: Avoid strlen.
170  if (ArgSize != strlen(Args.getArgString(Index)))
171  return nullptr;
172 
173  Index += 2;
174  if (Index > Args.getNumInputArgStrings() ||
175  Args.getArgString(Index - 1) == nullptr)
176  return nullptr;
177 
178  return new Arg(UnaliasedOption, Spelling,
179  Index - 2, Args.getArgString(Index - 1));
180  case MultiArgClass: {
181  // Matches iff this is an exact match.
182  // FIXME: Avoid strlen.
183  if (ArgSize != strlen(Args.getArgString(Index)))
184  return nullptr;
185 
186  Index += 1 + getNumArgs();
187  if (Index > Args.getNumInputArgStrings())
188  return nullptr;
189 
190  Arg *A = new Arg(UnaliasedOption, Spelling, Index - 1 - getNumArgs(),
191  Args.getArgString(Index - getNumArgs()));
192  for (unsigned i = 1; i != getNumArgs(); ++i)
193  A->getValues().push_back(Args.getArgString(Index - getNumArgs() + i));
194  return A;
195  }
196  case JoinedOrSeparateClass: {
197  // If this is not an exact match, it is a joined arg.
198  // FIXME: Avoid strlen.
199  if (ArgSize != strlen(Args.getArgString(Index))) {
200  const char *Value = Args.getArgString(Index) + ArgSize;
201  return new Arg(*this, Spelling, Index++, Value);
202  }
203 
204  // Otherwise it must be separate.
205  Index += 2;
206  if (Index > Args.getNumInputArgStrings() ||
207  Args.getArgString(Index - 1) == nullptr)
208  return nullptr;
209 
210  return new Arg(UnaliasedOption, Spelling,
211  Index - 2, Args.getArgString(Index - 1));
212  }
214  // Always matches.
215  Index += 2;
216  if (Index > Args.getNumInputArgStrings() ||
217  Args.getArgString(Index - 1) == nullptr)
218  return nullptr;
219 
220  return new Arg(UnaliasedOption, Spelling, Index - 2,
221  Args.getArgString(Index - 2) + ArgSize,
222  Args.getArgString(Index - 1));
223  case RemainingArgsClass: {
224  // Matches iff this is an exact match.
225  // FIXME: Avoid strlen.
226  if (ArgSize != strlen(Args.getArgString(Index)))
227  return nullptr;
228  Arg *A = new Arg(UnaliasedOption, Spelling, Index++);
229  while (Index < Args.getNumInputArgStrings() &&
230  Args.getArgString(Index) != nullptr)
231  A->getValues().push_back(Args.getArgString(Index++));
232  return A;
233  }
234  default:
235  llvm_unreachable("Invalid option kind!");
236  }
237 }
void push_back(const T &Elt)
Definition: SmallVector.h:222
void dump() const
Definition: Option.cpp:38
bool matches(OptSpecifier ID) const
matches - Predicate for whether this option is part of the given option (which may be a group)...
Definition: Option.cpp:84
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
StringRef getName() const
Get the name of this option without any prefix.
Definition: Option.h:89
const OptTable::Info * Info
Definition: Option.h:68
const Option getAlias() const
Definition: Option.h:100
OptionClass getKind() const
Definition: Option.h:83
unsigned getID() const
Definition: Option.h:78
lazy value info
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:79
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:98
const Option getGroup() const
Definition: Option.h:94
SmallVectorImpl< const char * > & getValues()
Definition: Arg.h:96
virtual unsigned getNumInputArgStrings() const =0
getNumInputArgStrings - Return the number of original argument strings, which are guaranteed to be th...
unsigned getNumArgs() const
Definition: Option.h:129
#define P(N)
Option - Abstract representation for a single form of driver argument.
Definition: Option.h:44
A concrete instance of a particular driver option.
Definition: Arg.h:31
Provide access to the Option info table.
Definition: OptTable.h:32
const char *const * Prefixes
A null terminated array of prefix strings to apply to name while matching.
Definition: OptTable.h:38
const char * MakeArgString(const Twine &Str) const
Definition: ArgList.h:296
StringRef getPrefix() const
Get the default prefix for this option.
Definition: Option.h:117
unsigned getID() const
Definition: OptSpecifier.h:33
virtual const char * getArgString(unsigned Index) const =0
getArgString - Return the input argument string at Index.
bool isValid() const
Definition: Option.h:74
Option(const OptTable::Info *Info, const OptTable *Owner)
Definition: Option.cpp:22
Defines the llvm::Arg class for parsed arguments.
void setOwnsValues(bool Value) const
Definition: Arg.h:84
const Option getUnaliasedOption() const
getUnaliasedOption - Return the final option this option aliases (itself, if the option has no alias)...
Definition: Option.h:165
OptSpecifier - Wrapper class for abstracting references to option IDs.
Definition: OptSpecifier.h:20
Entry for a single option instance in the option data table.
Definition: OptTable.h:35
const char * getAliasArgs() const
Get the alias arguments as a \0 separated list.
Definition: Option.h:108
LLVM Value Representation.
Definition: Value.h:69
Arg * accept(const ArgList &Args, unsigned &Index, unsigned ArgSize) const
accept - Potentially accept the current argument, returning a new Arg instance, or 0 if the option do...
Definition: Option.cpp:100
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:40
ArgList - Ordered collection of driver arguments.
Definition: ArgList.h:94