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
, bool AddNewLine
) const {
44 #define P(N) case N: O << #N; break
54 P(JoinedOrSeparateClass
);
55 P(JoinedAndSeparateClass
);
56 P(RemainingArgsClass
);
57 P(RemainingArgsJoinedClass
);
61 if (!Info
->Prefixes
.empty()) {
63 for (size_t I
= 0, N
= Info
->Prefixes
.size(); I
!= N
; ++I
)
64 O
<< '"' << Info
->Prefixes
[I
] << (I
== N
- 1 ? "\"" : "\", ");
68 O
<< " Name:\"" << getName() << '"';
70 const Option Group
= getGroup();
71 if (Group
.isValid()) {
73 Group
.print(O
, /*AddNewLine=*/false);
76 const Option Alias
= getAlias();
77 if (Alias
.isValid()) {
79 Alias
.print(O
, /*AddNewLine=*/false);
82 if (getKind() == MultiArgClass
)
83 O
<< " NumArgs:" << getNumArgs();
90 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
91 LLVM_DUMP_METHOD
void Option::dump() const { print(dbgs()); }
94 bool Option::matches(OptSpecifier Opt
) const {
95 // Aliases are never considered in matching, look through them.
96 const Option Alias
= getAlias();
98 return Alias
.matches(Opt
);
100 // Check exact match.
101 if (getID() == Opt
.getID())
104 const Option Group
= getGroup();
106 return Group
.matches(Opt
);
110 std::unique_ptr
<Arg
> Option::acceptInternal(const ArgList
&Args
,
112 unsigned &Index
) const {
113 const size_t SpellingSize
= Spelling
.size();
114 const size_t ArgStringSize
= StringRef(Args
.getArgString(Index
)).size();
117 if (SpellingSize
!= ArgStringSize
)
119 return std::make_unique
<Arg
>(*this, Spelling
, Index
++);
122 const char *Value
= Args
.getArgString(Index
) + SpellingSize
;
123 return std::make_unique
<Arg
>(*this, Spelling
, Index
++, Value
);
125 case CommaJoinedClass
: {
127 const char *Str
= Args
.getArgString(Index
) + SpellingSize
;
128 auto A
= std::make_unique
<Arg
>(*this, Spelling
, Index
++);
130 // Parse out the comma separated values.
131 const char *Prev
= Str
;
135 if (!c
|| c
== ',') {
137 char *Value
= new char[Str
- Prev
+ 1];
138 memcpy(Value
, Prev
, Str
- Prev
);
139 Value
[Str
- Prev
] = '\0';
140 A
->getValues().push_back(Value
);
149 A
->setOwnsValues(true);
154 // Matches iff this is an exact match.
155 if (SpellingSize
!= ArgStringSize
)
159 if (Index
> Args
.getNumInputArgStrings() ||
160 Args
.getArgString(Index
- 1) == nullptr)
163 return std::make_unique
<Arg
>(*this, Spelling
, Index
- 2,
164 Args
.getArgString(Index
- 1));
165 case MultiArgClass
: {
166 // Matches iff this is an exact match.
167 if (SpellingSize
!= ArgStringSize
)
170 Index
+= 1 + getNumArgs();
171 if (Index
> Args
.getNumInputArgStrings())
174 auto A
= std::make_unique
<Arg
>(*this, Spelling
, Index
- 1 - getNumArgs(),
175 Args
.getArgString(Index
- getNumArgs()));
176 for (unsigned i
= 1; i
!= getNumArgs(); ++i
)
177 A
->getValues().push_back(Args
.getArgString(Index
- getNumArgs() + i
));
180 case JoinedOrSeparateClass
: {
181 // If this is not an exact match, it is a joined arg.
182 if (SpellingSize
!= ArgStringSize
) {
183 const char *Value
= Args
.getArgString(Index
) + SpellingSize
;
184 return std::make_unique
<Arg
>(*this, Spelling
, Index
++, Value
);
187 // Otherwise it must be separate.
189 if (Index
> Args
.getNumInputArgStrings() ||
190 Args
.getArgString(Index
- 1) == nullptr)
193 return std::make_unique
<Arg
>(*this, Spelling
, Index
- 2,
194 Args
.getArgString(Index
- 1));
196 case JoinedAndSeparateClass
:
199 if (Index
> Args
.getNumInputArgStrings() ||
200 Args
.getArgString(Index
- 1) == nullptr)
203 return std::make_unique
<Arg
>(*this, Spelling
, Index
- 2,
204 Args
.getArgString(Index
- 2) + SpellingSize
,
205 Args
.getArgString(Index
- 1));
206 case RemainingArgsClass
: {
207 // Matches iff this is an exact match.
208 if (SpellingSize
!= ArgStringSize
)
210 auto A
= std::make_unique
<Arg
>(*this, Spelling
, Index
++);
211 while (Index
< Args
.getNumInputArgStrings() &&
212 Args
.getArgString(Index
) != nullptr)
213 A
->getValues().push_back(Args
.getArgString(Index
++));
216 case RemainingArgsJoinedClass
: {
217 auto A
= std::make_unique
<Arg
>(*this, Spelling
, Index
);
218 if (SpellingSize
!= ArgStringSize
) {
219 // An inexact match means there is a joined arg.
220 A
->getValues().push_back(Args
.getArgString(Index
) + SpellingSize
);
223 while (Index
< Args
.getNumInputArgStrings() &&
224 Args
.getArgString(Index
) != nullptr)
225 A
->getValues().push_back(Args
.getArgString(Index
++));
230 llvm_unreachable("Invalid option kind!");
234 std::unique_ptr
<Arg
> Option::accept(const ArgList
&Args
, StringRef CurArg
,
235 bool GroupedShortOption
,
236 unsigned &Index
) const {
237 auto A(GroupedShortOption
&& getKind() == FlagClass
238 ? std::make_unique
<Arg
>(*this, CurArg
, Index
)
239 : acceptInternal(Args
, CurArg
, Index
));
243 const Option
&UnaliasedOption
= getUnaliasedOption();
244 if (getID() == UnaliasedOption
.getID())
247 // "A" is an alias for a different flag. For most clients it's more convenient
248 // if this function returns unaliased Args, so create an unaliased arg for
251 // This creates a completely new Arg object for the unaliased Arg because
252 // the alias and the unaliased arg can have different Kinds and different
253 // Values (due to AliasArgs<>).
255 // Get the spelling from the unaliased option.
256 StringRef UnaliasedSpelling
= Args
.MakeArgString(
257 Twine(UnaliasedOption
.getPrefix()) + Twine(UnaliasedOption
.getName()));
259 // It's a bit weird that aliased and unaliased arg share one index, but
260 // the index is mostly use as a memory optimization in render().
261 // Due to this, ArgList::getArgString(A->getIndex()) will return the spelling
262 // of the aliased arg always, while A->getSpelling() returns either the
263 // unaliased or the aliased arg, depending on which Arg object it's called on.
265 std::make_unique
<Arg
>(UnaliasedOption
, UnaliasedSpelling
, A
->getIndex());
267 UnaliasedA
->setAlias(std::move(A
));
269 if (getKind() != FlagClass
) {
270 // Values are usually owned by the ArgList. The exception are
271 // CommaJoined flags, where the Arg owns the values. For aliased flags,
272 // make the unaliased Arg the owner of the values.
273 // FIXME: There aren't many uses of CommaJoined -- try removing
274 // CommaJoined in favor of just calling StringRef::split(',') instead.
275 UnaliasedA
->getValues() = RawA
->getValues();
276 UnaliasedA
->setOwnsValues(RawA
->getOwnsValues());
277 RawA
->setOwnsValues(false);
281 // FlagClass aliases can have AliasArgs<>; add those to the unaliased arg.
282 if (const char *Val
= getAliasArgs()) {
283 while (*Val
!= '\0') {
284 UnaliasedA
->getValues().push_back(Val
);
286 // Move past the '\0' to the next argument.
287 Val
+= strlen(Val
) + 1;
290 if (UnaliasedOption
.getKind() == JoinedClass
&& !getAliasArgs())
291 // A Flag alias for a Joined option must provide an argument.
292 UnaliasedA
->getValues().push_back("");