1 //===- Option.cpp - Abstract Driver Options -------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/StringRef.h"
10 #include "llvm/ADT/Twine.h"
11 #include "llvm/Config/llvm-config.h"
12 #include "llvm/Option/Arg.h"
13 #include "llvm/Option/ArgList.h"
14 #include "llvm/Option/Option.h"
15 #include "llvm/Option/OptTable.h"
16 #include "llvm/Support/Compiler.h"
17 #include "llvm/Support/Debug.h"
18 #include "llvm/Support/ErrorHandling.h"
19 #include "llvm/Support/raw_ostream.h"
24 using namespace llvm::opt
;
26 Option::Option(const OptTable::Info
*info
, const OptTable
*owner
)
27 : Info(info
), Owner(owner
) {
28 // Multi-level aliases are not supported. This just simplifies option
29 // tracking, it is not an inherent limitation.
30 assert((!Info
|| !getAlias().isValid() || !getAlias().getAlias().isValid()) &&
31 "Multi-level aliases are not supported.");
33 if (Info
&& getAliasArgs()) {
34 assert(getAlias().isValid() && "Only alias options can have alias args.");
35 assert(getKind() == FlagClass
&& "Only Flag aliases can have alias args.");
36 assert(getAlias().getKind() != FlagClass
&&
37 "Cannot provide alias args to a flag option.");
41 void Option::print(raw_ostream
&O
) const {
44 #define P(N) case N: O << #N; break
54 P(JoinedOrSeparateClass
);
55 P(JoinedAndSeparateClass
);
56 P(RemainingArgsClass
);
57 P(RemainingArgsJoinedClass
);
63 for (const char *const *Pre
= Info
->Prefixes
; *Pre
!= nullptr; ++Pre
) {
64 O
<< '"' << *Pre
<< (*(Pre
+ 1) == nullptr ? "\"" : "\", ");
69 O
<< " Name:\"" << getName() << '"';
71 const Option Group
= getGroup();
72 if (Group
.isValid()) {
77 const Option Alias
= getAlias();
78 if (Alias
.isValid()) {
83 if (getKind() == MultiArgClass
)
84 O
<< " NumArgs:" << getNumArgs();
89 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
90 LLVM_DUMP_METHOD
void Option::dump() const { print(dbgs()); }
93 bool Option::matches(OptSpecifier Opt
) const {
94 // Aliases are never considered in matching, look through them.
95 const Option Alias
= getAlias();
97 return Alias
.matches(Opt
);
100 if (getID() == Opt
.getID())
103 const Option Group
= getGroup();
105 return Group
.matches(Opt
);
109 Arg
*Option::acceptInternal(const ArgList
&Args
, unsigned &Index
,
110 unsigned ArgSize
) const {
111 StringRef Spelling
= StringRef(Args
.getArgString(Index
), ArgSize
);
114 if (ArgSize
!= strlen(Args
.getArgString(Index
)))
116 return new Arg(*this, Spelling
, Index
++);
119 const char *Value
= Args
.getArgString(Index
) + ArgSize
;
120 return new Arg(*this, Spelling
, Index
++, Value
);
122 case CommaJoinedClass
: {
124 const char *Str
= Args
.getArgString(Index
) + ArgSize
;
125 Arg
*A
= new Arg(*this, Spelling
, Index
++);
127 // Parse out the comma separated values.
128 const char *Prev
= Str
;
132 if (!c
|| c
== ',') {
134 char *Value
= new char[Str
- Prev
+ 1];
135 memcpy(Value
, Prev
, Str
- Prev
);
136 Value
[Str
- Prev
] = '\0';
137 A
->getValues().push_back(Value
);
146 A
->setOwnsValues(true);
151 // Matches iff this is an exact match.
152 // FIXME: Avoid strlen.
153 if (ArgSize
!= strlen(Args
.getArgString(Index
)))
157 if (Index
> Args
.getNumInputArgStrings() ||
158 Args
.getArgString(Index
- 1) == nullptr)
161 return new Arg(*this, Spelling
, Index
- 2, Args
.getArgString(Index
- 1));
162 case MultiArgClass
: {
163 // Matches iff this is an exact match.
164 // FIXME: Avoid strlen.
165 if (ArgSize
!= strlen(Args
.getArgString(Index
)))
168 Index
+= 1 + getNumArgs();
169 if (Index
> Args
.getNumInputArgStrings())
172 Arg
*A
= new Arg(*this, Spelling
, Index
- 1 - getNumArgs(),
173 Args
.getArgString(Index
- getNumArgs()));
174 for (unsigned i
= 1; i
!= getNumArgs(); ++i
)
175 A
->getValues().push_back(Args
.getArgString(Index
- getNumArgs() + i
));
178 case JoinedOrSeparateClass
: {
179 // If this is not an exact match, it is a joined arg.
180 // FIXME: Avoid strlen.
181 if (ArgSize
!= strlen(Args
.getArgString(Index
))) {
182 const char *Value
= Args
.getArgString(Index
) + ArgSize
;
183 return new Arg(*this, Spelling
, Index
++, Value
);
186 // Otherwise it must be separate.
188 if (Index
> Args
.getNumInputArgStrings() ||
189 Args
.getArgString(Index
- 1) == nullptr)
192 return new Arg(*this, Spelling
, Index
- 2, Args
.getArgString(Index
- 1));
194 case JoinedAndSeparateClass
:
197 if (Index
> Args
.getNumInputArgStrings() ||
198 Args
.getArgString(Index
- 1) == nullptr)
201 return new Arg(*this, Spelling
, Index
- 2,
202 Args
.getArgString(Index
- 2) + ArgSize
,
203 Args
.getArgString(Index
- 1));
204 case RemainingArgsClass
: {
205 // Matches iff this is an exact match.
206 // FIXME: Avoid strlen.
207 if (ArgSize
!= strlen(Args
.getArgString(Index
)))
209 Arg
*A
= new Arg(*this, Spelling
, Index
++);
210 while (Index
< Args
.getNumInputArgStrings() &&
211 Args
.getArgString(Index
) != nullptr)
212 A
->getValues().push_back(Args
.getArgString(Index
++));
215 case RemainingArgsJoinedClass
: {
216 Arg
*A
= new Arg(*this, Spelling
, Index
);
217 if (ArgSize
!= strlen(Args
.getArgString(Index
))) {
218 // An inexact match means there is a joined arg.
219 A
->getValues().push_back(Args
.getArgString(Index
) + ArgSize
);
222 while (Index
< Args
.getNumInputArgStrings() &&
223 Args
.getArgString(Index
) != nullptr)
224 A
->getValues().push_back(Args
.getArgString(Index
++));
229 llvm_unreachable("Invalid option kind!");
233 Arg
*Option::accept(const ArgList
&Args
,
235 unsigned ArgSize
) const {
236 std::unique_ptr
<Arg
> A(acceptInternal(Args
, Index
, ArgSize
));
240 const Option
&UnaliasedOption
= getUnaliasedOption();
241 if (getID() == UnaliasedOption
.getID())
244 // "A" is an alias for a different flag. For most clients it's more convenient
245 // if this function returns unaliased Args, so create an unaliased arg for
248 // This creates a completely new Arg object for the unaliased Arg because
249 // the alias and the unaliased arg can have different Kinds and different
250 // Values (due to AliasArgs<>).
252 // Get the spelling from the unaliased option.
253 StringRef UnaliasedSpelling
= Args
.MakeArgString(
254 Twine(UnaliasedOption
.getPrefix()) + Twine(UnaliasedOption
.getName()));
256 // It's a bit weird that aliased and unaliased arg share one index, but
257 // the index is mostly use as a memory optimization in render().
258 // Due to this, ArgList::getArgString(A->getIndex()) will return the spelling
259 // of the aliased arg always, while A->getSpelling() returns either the
260 // unaliased or the aliased arg, depending on which Arg object it's called on.
261 Arg
*UnaliasedA
= new Arg(UnaliasedOption
, UnaliasedSpelling
, A
->getIndex());
263 UnaliasedA
->setAlias(std::move(A
));
265 if (getKind() != FlagClass
) {
266 // Values are usually owned by the ArgList. The exception are
267 // CommaJoined flags, where the Arg owns the values. For aliased flags,
268 // make the unaliased Arg the owner of the values.
269 // FIXME: There aren't many uses of CommaJoined -- try removing
270 // CommaJoined in favor of just calling StringRef::split(',') instead.
271 UnaliasedA
->getValues() = RawA
->getValues();
272 UnaliasedA
->setOwnsValues(RawA
->getOwnsValues());
273 RawA
->setOwnsValues(false);
277 // FlagClass aliases can have AliasArgs<>; add those to the unaliased arg.
278 if (const char *Val
= getAliasArgs()) {
279 while (*Val
!= '\0') {
280 UnaliasedA
->getValues().push_back(Val
);
282 // Move past the '\0' to the next argument.
283 Val
+= strlen(Val
) + 1;
286 if (UnaliasedOption
.getKind() == JoinedClass
&& !getAliasArgs())
287 // A Flag alias for a Joined option must provide an argument.
288 UnaliasedA
->getValues().push_back("");