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