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