1 | //===- Option.cpp - Abstract Driver Options -------------------------------===// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "llvm/Option/Option.h" |
10 | #include "llvm/ADT/StringRef.h" |
11 | #include "llvm/ADT/Twine.h" |
12 | #include "llvm/Config/llvm-config.h" |
13 | #include "llvm/Option/Arg.h" |
14 | #include "llvm/Option/ArgList.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" |
20 | #include <cassert> |
21 | |
22 | using namespace llvm; |
23 | using namespace llvm::opt; |
24 | |
25 | Option::Option(const OptTable::Info *info, const OptTable *owner) |
26 | : Info(info), Owner(owner) { |
27 | // Multi-level aliases are not supported. This just simplifies option |
28 | // tracking, it is not an inherent limitation. |
29 | assert((!Info || !getAlias().isValid() || !getAlias().getAlias().isValid()) && |
30 | "Multi-level aliases are not supported." ); |
31 | |
32 | if (Info && getAliasArgs()) { |
33 | assert(getAlias().isValid() && "Only alias options can have alias args." ); |
34 | assert(getKind() == FlagClass && "Only Flag aliases can have alias args." ); |
35 | assert(getAlias().getKind() != FlagClass && |
36 | "Cannot provide alias args to a flag option." ); |
37 | } |
38 | } |
39 | |
40 | void Option::print(raw_ostream &O, bool AddNewLine) const { |
41 | O << "<" ; |
42 | switch (getKind()) { |
43 | #define P(N) case N: O << #N; break |
44 | P(GroupClass); |
45 | P(InputClass); |
46 | P(UnknownClass); |
47 | P(FlagClass); |
48 | P(JoinedClass); |
49 | P(ValuesClass); |
50 | P(SeparateClass); |
51 | P(CommaJoinedClass); |
52 | P(MultiArgClass); |
53 | P(JoinedOrSeparateClass); |
54 | P(JoinedAndSeparateClass); |
55 | P(RemainingArgsClass); |
56 | P(RemainingArgsJoinedClass); |
57 | #undef P |
58 | } |
59 | |
60 | if (!Info->hasNoPrefix()) { |
61 | O << " Prefixes:[" ; |
62 | for (size_t I = 0, N = Info->getNumPrefixes(PrefixesTable: Owner->getPrefixesTable()); |
63 | I != N; ++I) |
64 | O << '"' |
65 | << Info->getPrefix(StrTable: Owner->getStrTable(), PrefixesTable: Owner->getPrefixesTable(), PrefixIndex: I) |
66 | << (I == N - 1 ? "\"" : "\", " ); |
67 | O << ']'; |
68 | } |
69 | |
70 | O << " Name:\"" << getName() << '"'; |
71 | |
72 | const Option Group = getGroup(); |
73 | if (Group.isValid()) { |
74 | O << " Group:" ; |
75 | Group.print(O, /*AddNewLine=*/false); |
76 | } |
77 | |
78 | const Option Alias = getAlias(); |
79 | if (Alias.isValid()) { |
80 | O << " Alias:" ; |
81 | Alias.print(O, /*AddNewLine=*/false); |
82 | } |
83 | |
84 | if (getKind() == MultiArgClass) |
85 | O << " NumArgs:" << getNumArgs(); |
86 | |
87 | O << ">" ; |
88 | if (AddNewLine) |
89 | O << "\n" ; |
90 | } |
91 | |
92 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
93 | LLVM_DUMP_METHOD void Option::dump() const { print(dbgs()); } |
94 | #endif |
95 | |
96 | bool Option::matches(OptSpecifier Opt) const { |
97 | // Aliases are never considered in matching, look through them. |
98 | const Option Alias = getAlias(); |
99 | if (Alias.isValid()) |
100 | return Alias.matches(Opt); |
101 | |
102 | // Check exact match. |
103 | if (getID() == Opt.getID()) |
104 | return true; |
105 | |
106 | const Option Group = getGroup(); |
107 | if (Group.isValid()) |
108 | return Group.matches(Opt); |
109 | return false; |
110 | } |
111 | |
112 | std::unique_ptr<Arg> Option::acceptInternal(const ArgList &Args, |
113 | StringRef Spelling, |
114 | unsigned &Index) const { |
115 | const size_t SpellingSize = Spelling.size(); |
116 | const size_t ArgStringSize = StringRef(Args.getArgString(Index)).size(); |
117 | switch (getKind()) { |
118 | case FlagClass: { |
119 | if (SpellingSize != ArgStringSize) |
120 | return nullptr; |
121 | return std::make_unique<Arg>(args: *this, args&: Spelling, args: Index++); |
122 | } |
123 | case JoinedClass: { |
124 | const char *Value = Args.getArgString(Index) + SpellingSize; |
125 | return std::make_unique<Arg>(args: *this, args&: Spelling, args: Index++, args&: Value); |
126 | } |
127 | case CommaJoinedClass: { |
128 | // Always matches. |
129 | const char *Str = Args.getArgString(Index) + SpellingSize; |
130 | auto A = std::make_unique<Arg>(args: *this, args&: Spelling, args: Index++); |
131 | |
132 | // Parse out the comma separated values. |
133 | const char *Prev = Str; |
134 | for (;; ++Str) { |
135 | char c = *Str; |
136 | |
137 | if (!c || c == ',') { |
138 | if (Prev != Str) { |
139 | char *Value = new char[Str - Prev + 1]; |
140 | memcpy(dest: Value, src: Prev, n: Str - Prev); |
141 | Value[Str - Prev] = '\0'; |
142 | A->getValues().push_back(Elt: Value); |
143 | } |
144 | |
145 | if (!c) |
146 | break; |
147 | |
148 | Prev = Str + 1; |
149 | } |
150 | } |
151 | A->setOwnsValues(true); |
152 | |
153 | return A; |
154 | } |
155 | case SeparateClass: |
156 | // Matches iff this is an exact match. |
157 | if (SpellingSize != ArgStringSize) |
158 | return nullptr; |
159 | |
160 | Index += 2; |
161 | if (Index > Args.getNumInputArgStrings() || |
162 | Args.getArgString(Index: Index - 1) == nullptr) |
163 | return nullptr; |
164 | |
165 | return std::make_unique<Arg>(args: *this, args&: Spelling, args: Index - 2, |
166 | args: Args.getArgString(Index: Index - 1)); |
167 | case MultiArgClass: { |
168 | // Matches iff this is an exact match. |
169 | if (SpellingSize != ArgStringSize) |
170 | return nullptr; |
171 | |
172 | Index += 1 + getNumArgs(); |
173 | if (Index > Args.getNumInputArgStrings()) |
174 | return nullptr; |
175 | |
176 | auto A = std::make_unique<Arg>(args: *this, args&: Spelling, args: Index - 1 - getNumArgs(), |
177 | args: Args.getArgString(Index: Index - getNumArgs())); |
178 | for (unsigned i = 1; i != getNumArgs(); ++i) |
179 | A->getValues().push_back(Elt: Args.getArgString(Index: Index - getNumArgs() + i)); |
180 | return A; |
181 | } |
182 | case JoinedOrSeparateClass: { |
183 | // If this is not an exact match, it is a joined arg. |
184 | if (SpellingSize != ArgStringSize) { |
185 | const char *Value = Args.getArgString(Index) + SpellingSize; |
186 | return std::make_unique<Arg>(args: *this, args&: Spelling, args: Index++, args&: Value); |
187 | } |
188 | |
189 | // Otherwise it must be separate. |
190 | Index += 2; |
191 | if (Index > Args.getNumInputArgStrings() || |
192 | Args.getArgString(Index: Index - 1) == nullptr) |
193 | return nullptr; |
194 | |
195 | return std::make_unique<Arg>(args: *this, args&: Spelling, args: Index - 2, |
196 | args: Args.getArgString(Index: Index - 1)); |
197 | } |
198 | case JoinedAndSeparateClass: |
199 | // Always matches. |
200 | Index += 2; |
201 | if (Index > Args.getNumInputArgStrings() || |
202 | Args.getArgString(Index: Index - 1) == nullptr) |
203 | return nullptr; |
204 | |
205 | return std::make_unique<Arg>(args: *this, args&: Spelling, args: Index - 2, |
206 | args: Args.getArgString(Index: Index - 2) + SpellingSize, |
207 | args: Args.getArgString(Index: Index - 1)); |
208 | case RemainingArgsClass: { |
209 | // Matches iff this is an exact match. |
210 | if (SpellingSize != ArgStringSize) |
211 | return nullptr; |
212 | auto A = std::make_unique<Arg>(args: *this, args&: Spelling, args: Index++); |
213 | while (Index < Args.getNumInputArgStrings() && |
214 | Args.getArgString(Index) != nullptr) |
215 | A->getValues().push_back(Elt: Args.getArgString(Index: Index++)); |
216 | return A; |
217 | } |
218 | case RemainingArgsJoinedClass: { |
219 | auto A = std::make_unique<Arg>(args: *this, args&: Spelling, args&: Index); |
220 | if (SpellingSize != ArgStringSize) { |
221 | // An inexact match means there is a joined arg. |
222 | A->getValues().push_back(Elt: Args.getArgString(Index) + SpellingSize); |
223 | } |
224 | Index++; |
225 | while (Index < Args.getNumInputArgStrings() && |
226 | Args.getArgString(Index) != nullptr) |
227 | A->getValues().push_back(Elt: Args.getArgString(Index: Index++)); |
228 | return A; |
229 | } |
230 | |
231 | default: |
232 | llvm_unreachable("Invalid option kind!" ); |
233 | } |
234 | } |
235 | |
236 | std::unique_ptr<Arg> Option::accept(const ArgList &Args, StringRef CurArg, |
237 | bool GroupedShortOption, |
238 | unsigned &Index) const { |
239 | auto A(GroupedShortOption && getKind() == FlagClass |
240 | ? std::make_unique<Arg>(args: *this, args&: CurArg, args&: Index) |
241 | : acceptInternal(Args, Spelling: CurArg, Index)); |
242 | if (!A) |
243 | return nullptr; |
244 | |
245 | const Option &UnaliasedOption = getUnaliasedOption(); |
246 | if (getID() == UnaliasedOption.getID()) |
247 | return A; |
248 | |
249 | // "A" is an alias for a different flag. For most clients it's more convenient |
250 | // if this function returns unaliased Args, so create an unaliased arg for |
251 | // returning. |
252 | |
253 | // This creates a completely new Arg object for the unaliased Arg because |
254 | // the alias and the unaliased arg can have different Kinds and different |
255 | // Values (due to AliasArgs<>). |
256 | |
257 | // Get the spelling from the unaliased option. |
258 | StringRef UnaliasedSpelling = Args.MakeArgString( |
259 | Str: Twine(UnaliasedOption.getPrefix()) + Twine(UnaliasedOption.getName())); |
260 | |
261 | // It's a bit weird that aliased and unaliased arg share one index, but |
262 | // the index is mostly use as a memory optimization in render(). |
263 | // Due to this, ArgList::getArgString(A->getIndex()) will return the spelling |
264 | // of the aliased arg always, while A->getSpelling() returns either the |
265 | // unaliased or the aliased arg, depending on which Arg object it's called on. |
266 | auto UnaliasedA = |
267 | std::make_unique<Arg>(args: UnaliasedOption, args&: UnaliasedSpelling, args: A->getIndex()); |
268 | Arg *RawA = A.get(); |
269 | UnaliasedA->setAlias(std::move(A)); |
270 | |
271 | if (getKind() != FlagClass) { |
272 | // Values are usually owned by the ArgList. The exception are |
273 | // CommaJoined flags, where the Arg owns the values. For aliased flags, |
274 | // make the unaliased Arg the owner of the values. |
275 | // FIXME: There aren't many uses of CommaJoined -- try removing |
276 | // CommaJoined in favor of just calling StringRef::split(',') instead. |
277 | UnaliasedA->getValues() = RawA->getValues(); |
278 | UnaliasedA->setOwnsValues(RawA->getOwnsValues()); |
279 | RawA->setOwnsValues(false); |
280 | return UnaliasedA; |
281 | } |
282 | |
283 | // FlagClass aliases can have AliasArgs<>; add those to the unaliased arg. |
284 | if (const char *Val = getAliasArgs()) { |
285 | while (*Val != '\0') { |
286 | UnaliasedA->getValues().push_back(Elt: Val); |
287 | |
288 | // Move past the '\0' to the next argument. |
289 | Val += strlen(s: Val) + 1; |
290 | } |
291 | } |
292 | if (UnaliasedOption.getKind() == JoinedClass && !getAliasArgs()) |
293 | // A Flag alias for a Joined option must provide an argument. |
294 | UnaliasedA->getValues().push_back(Elt: "" ); |
295 | return UnaliasedA; |
296 | } |
297 | |