Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Option/Option.cpp
35234 views
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/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"
20
#include <cassert>
21
#include <cstring>
22
23
using namespace llvm;
24
using namespace llvm::opt;
25
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.");
32
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.");
38
}
39
}
40
41
void 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->Prefixes.empty()) {
62
O << " Prefixes:[";
63
for (size_t I = 0, N = Info->Prefixes.size(); I != N; ++I)
64
O << '"' << Info->Prefixes[I] << (I == N - 1 ? "\"" : "\", ");
65
O << ']';
66
}
67
68
O << " Name:\"" << getName() << '"';
69
70
const Option Group = getGroup();
71
if (Group.isValid()) {
72
O << " Group:";
73
Group.print(O, /*AddNewLine=*/false);
74
}
75
76
const Option Alias = getAlias();
77
if (Alias.isValid()) {
78
O << " Alias:";
79
Alias.print(O, /*AddNewLine=*/false);
80
}
81
82
if (getKind() == MultiArgClass)
83
O << " NumArgs:" << getNumArgs();
84
85
O << ">";
86
if (AddNewLine)
87
O << "\n";
88
}
89
90
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
91
LLVM_DUMP_METHOD void Option::dump() const { print(dbgs()); }
92
#endif
93
94
bool Option::matches(OptSpecifier Opt) const {
95
// Aliases are never considered in matching, look through them.
96
const Option Alias = getAlias();
97
if (Alias.isValid())
98
return Alias.matches(Opt);
99
100
// Check exact match.
101
if (getID() == Opt.getID())
102
return true;
103
104
const Option Group = getGroup();
105
if (Group.isValid())
106
return Group.matches(Opt);
107
return false;
108
}
109
110
std::unique_ptr<Arg> Option::acceptInternal(const ArgList &Args,
111
StringRef Spelling,
112
unsigned &Index) const {
113
const size_t SpellingSize = Spelling.size();
114
const size_t ArgStringSize = StringRef(Args.getArgString(Index)).size();
115
switch (getKind()) {
116
case FlagClass: {
117
if (SpellingSize != ArgStringSize)
118
return nullptr;
119
return std::make_unique<Arg>(*this, Spelling, Index++);
120
}
121
case JoinedClass: {
122
const char *Value = Args.getArgString(Index) + SpellingSize;
123
return std::make_unique<Arg>(*this, Spelling, Index++, Value);
124
}
125
case CommaJoinedClass: {
126
// Always matches.
127
const char *Str = Args.getArgString(Index) + SpellingSize;
128
auto A = std::make_unique<Arg>(*this, Spelling, Index++);
129
130
// Parse out the comma separated values.
131
const char *Prev = Str;
132
for (;; ++Str) {
133
char c = *Str;
134
135
if (!c || c == ',') {
136
if (Prev != Str) {
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);
141
}
142
143
if (!c)
144
break;
145
146
Prev = Str + 1;
147
}
148
}
149
A->setOwnsValues(true);
150
151
return A;
152
}
153
case SeparateClass:
154
// Matches iff this is an exact match.
155
if (SpellingSize != ArgStringSize)
156
return nullptr;
157
158
Index += 2;
159
if (Index > Args.getNumInputArgStrings() ||
160
Args.getArgString(Index - 1) == nullptr)
161
return nullptr;
162
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)
168
return nullptr;
169
170
Index += 1 + getNumArgs();
171
if (Index > Args.getNumInputArgStrings())
172
return nullptr;
173
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));
178
return A;
179
}
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);
185
}
186
187
// Otherwise it must be separate.
188
Index += 2;
189
if (Index > Args.getNumInputArgStrings() ||
190
Args.getArgString(Index - 1) == nullptr)
191
return nullptr;
192
193
return std::make_unique<Arg>(*this, Spelling, Index - 2,
194
Args.getArgString(Index - 1));
195
}
196
case JoinedAndSeparateClass:
197
// Always matches.
198
Index += 2;
199
if (Index > Args.getNumInputArgStrings() ||
200
Args.getArgString(Index - 1) == nullptr)
201
return nullptr;
202
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)
209
return nullptr;
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++));
214
return A;
215
}
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);
221
}
222
Index++;
223
while (Index < Args.getNumInputArgStrings() &&
224
Args.getArgString(Index) != nullptr)
225
A->getValues().push_back(Args.getArgString(Index++));
226
return A;
227
}
228
229
default:
230
llvm_unreachable("Invalid option kind!");
231
}
232
}
233
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));
240
if (!A)
241
return nullptr;
242
243
const Option &UnaliasedOption = getUnaliasedOption();
244
if (getID() == UnaliasedOption.getID())
245
return A;
246
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
249
// returning.
250
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<>).
254
255
// Get the spelling from the unaliased option.
256
StringRef UnaliasedSpelling = Args.MakeArgString(
257
Twine(UnaliasedOption.getPrefix()) + Twine(UnaliasedOption.getName()));
258
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.
264
auto UnaliasedA =
265
std::make_unique<Arg>(UnaliasedOption, UnaliasedSpelling, A->getIndex());
266
Arg *RawA = A.get();
267
UnaliasedA->setAlias(std::move(A));
268
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);
278
return UnaliasedA;
279
}
280
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);
285
286
// Move past the '\0' to the next argument.
287
Val += strlen(Val) + 1;
288
}
289
}
290
if (UnaliasedOption.getKind() == JoinedClass && !getAliasArgs())
291
// A Flag alias for a Joined option must provide an argument.
292
UnaliasedA->getValues().push_back("");
293
return UnaliasedA;
294
}
295
296