1 //===- ArgList.cpp - Argument List Management -----------------------------===//
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/ArrayRef.h"
10 #include "llvm/ADT/None.h"
11 #include "llvm/ADT/SmallVector.h"
12 #include "llvm/ADT/STLExtras.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/ADT/Twine.h"
15 #include "llvm/Config/llvm-config.h"
16 #include "llvm/Option/Arg.h"
17 #include "llvm/Option/ArgList.h"
18 #include "llvm/Option/Option.h"
19 #include "llvm/Option/OptSpecifier.h"
20 #include "llvm/Support/Compiler.h"
21 #include "llvm/Support/Debug.h"
22 #include "llvm/Support/raw_ostream.h"
31 using namespace llvm::opt
;
33 void ArgList::append(Arg
*A
) {
36 // Update ranges for the option and all of its groups.
37 for (Option O
= A
->getOption().getUnaliasedOption(); O
.isValid();
40 OptRanges
.insert(std::make_pair(O
.getID(), emptyRange())).first
->second
;
41 R
.first
= std::min
<unsigned>(R
.first
, Args
.size() - 1);
42 R
.second
= Args
.size();
46 void ArgList::eraseArg(OptSpecifier Id
) {
47 // Zero out the removed entries but keep them around so that we don't
48 // need to invalidate OptRanges.
49 for (Arg
*const &A
: filtered(Id
)) {
50 // Avoid the need for a non-const filtered iterator variant.
51 Arg
**ArgsBegin
= Args
.data();
52 ArgsBegin
[&A
- ArgsBegin
] = nullptr;
54 OptRanges
.erase(Id
.getID());
58 ArgList::getRange(std::initializer_list
<OptSpecifier
> Ids
) const {
59 OptRange R
= emptyRange();
61 auto I
= OptRanges
.find(Id
.getID());
62 if (I
!= OptRanges
.end()) {
63 R
.first
= std::min(R
.first
, I
->second
.first
);
64 R
.second
= std::max(R
.second
, I
->second
.second
);
67 // Map an empty {-1, 0} range to {0, 0} so it can be used to form iterators.
73 bool ArgList::hasFlag(OptSpecifier Pos
, OptSpecifier Neg
, bool Default
) const {
74 if (Arg
*A
= getLastArg(Pos
, Neg
))
75 return A
->getOption().matches(Pos
);
79 bool ArgList::hasFlag(OptSpecifier Pos
, OptSpecifier PosAlias
, OptSpecifier Neg
,
81 if (Arg
*A
= getLastArg(Pos
, PosAlias
, Neg
))
82 return A
->getOption().matches(Pos
) || A
->getOption().matches(PosAlias
);
86 StringRef
ArgList::getLastArgValue(OptSpecifier Id
, StringRef Default
) const {
87 if (Arg
*A
= getLastArg(Id
))
92 std::vector
<std::string
> ArgList::getAllArgValues(OptSpecifier Id
) const {
93 SmallVector
<const char *, 16> Values
;
94 AddAllArgValues(Values
, Id
);
95 return std::vector
<std::string
>(Values
.begin(), Values
.end());
98 void ArgList::AddAllArgsExcept(ArgStringList
&Output
,
99 ArrayRef
<OptSpecifier
> Ids
,
100 ArrayRef
<OptSpecifier
> ExcludeIds
) const {
101 for (const Arg
*Arg
: *this) {
102 bool Excluded
= false;
103 for (OptSpecifier Id
: ExcludeIds
) {
104 if (Arg
->getOption().matches(Id
)) {
110 for (OptSpecifier Id
: Ids
) {
111 if (Arg
->getOption().matches(Id
)) {
113 Arg
->render(*this, Output
);
121 /// This is a nicer interface when you don't have a list of Ids to exclude.
122 void ArgList::AddAllArgs(ArgStringList
&Output
,
123 ArrayRef
<OptSpecifier
> Ids
) const {
124 ArrayRef
<OptSpecifier
> Exclude
= None
;
125 AddAllArgsExcept(Output
, Ids
, Exclude
);
128 /// This 3-opt variant of AddAllArgs could be eliminated in favor of one
129 /// that accepts a single specifier, given the above which accepts any number.
130 void ArgList::AddAllArgs(ArgStringList
&Output
, OptSpecifier Id0
,
131 OptSpecifier Id1
, OptSpecifier Id2
) const {
132 for (auto Arg
: filtered(Id0
, Id1
, Id2
)) {
134 Arg
->render(*this, Output
);
138 void ArgList::AddAllArgValues(ArgStringList
&Output
, OptSpecifier Id0
,
139 OptSpecifier Id1
, OptSpecifier Id2
) const {
140 for (auto Arg
: filtered(Id0
, Id1
, Id2
)) {
142 const auto &Values
= Arg
->getValues();
143 Output
.append(Values
.begin(), Values
.end());
147 void ArgList::AddAllArgsTranslated(ArgStringList
&Output
, OptSpecifier Id0
,
148 const char *Translation
,
150 for (auto Arg
: filtered(Id0
)) {
154 Output
.push_back(MakeArgString(StringRef(Translation
) +
157 Output
.push_back(Translation
);
158 Output
.push_back(Arg
->getValue(0));
163 void ArgList::ClaimAllArgs(OptSpecifier Id0
) const {
164 for (auto *Arg
: filtered(Id0
))
168 void ArgList::ClaimAllArgs() const {
169 for (auto *Arg
: *this)
170 if (!Arg
->isClaimed())
174 const char *ArgList::GetOrMakeJoinedArgString(unsigned Index
,
176 StringRef RHS
) const {
177 StringRef Cur
= getArgString(Index
);
178 if (Cur
.size() == LHS
.size() + RHS
.size() &&
179 Cur
.startswith(LHS
) && Cur
.endswith(RHS
))
182 return MakeArgString(LHS
+ RHS
);
185 void ArgList::print(raw_ostream
&O
) const {
186 for (Arg
*A
: *this) {
192 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
193 LLVM_DUMP_METHOD
void ArgList::dump() const { print(dbgs()); }
196 void InputArgList::releaseMemory() {
197 // An InputArgList always owns its arguments.
202 InputArgList::InputArgList(const char* const *ArgBegin
,
203 const char* const *ArgEnd
)
204 : NumInputArgStrings(ArgEnd
- ArgBegin
) {
205 ArgStrings
.append(ArgBegin
, ArgEnd
);
208 unsigned InputArgList::MakeIndex(StringRef String0
) const {
209 unsigned Index
= ArgStrings
.size();
211 // Tuck away so we have a reliable const char *.
212 SynthesizedStrings
.push_back(String0
);
213 ArgStrings
.push_back(SynthesizedStrings
.back().c_str());
218 unsigned InputArgList::MakeIndex(StringRef String0
,
219 StringRef String1
) const {
220 unsigned Index0
= MakeIndex(String0
);
221 unsigned Index1
= MakeIndex(String1
);
222 assert(Index0
+ 1 == Index1
&& "Unexpected non-consecutive indices!");
227 const char *InputArgList::MakeArgStringRef(StringRef Str
) const {
228 return getArgString(MakeIndex(Str
));
231 DerivedArgList::DerivedArgList(const InputArgList
&BaseArgs
)
232 : BaseArgs(BaseArgs
) {}
234 const char *DerivedArgList::MakeArgStringRef(StringRef Str
) const {
235 return BaseArgs
.MakeArgString(Str
);
238 void DerivedArgList::AddSynthesizedArg(Arg
*A
) {
239 SynthesizedArgs
.push_back(std::unique_ptr
<Arg
>(A
));
242 Arg
*DerivedArgList::MakeFlagArg(const Arg
*BaseArg
, const Option Opt
) const {
243 SynthesizedArgs
.push_back(
244 std::make_unique
<Arg
>(Opt
, MakeArgString(Opt
.getPrefix() + Opt
.getName()),
245 BaseArgs
.MakeIndex(Opt
.getName()), BaseArg
));
246 return SynthesizedArgs
.back().get();
249 Arg
*DerivedArgList::MakePositionalArg(const Arg
*BaseArg
, const Option Opt
,
250 StringRef Value
) const {
251 unsigned Index
= BaseArgs
.MakeIndex(Value
);
252 SynthesizedArgs
.push_back(
253 std::make_unique
<Arg
>(Opt
, MakeArgString(Opt
.getPrefix() + Opt
.getName()),
254 Index
, BaseArgs
.getArgString(Index
), BaseArg
));
255 return SynthesizedArgs
.back().get();
258 Arg
*DerivedArgList::MakeSeparateArg(const Arg
*BaseArg
, const Option Opt
,
259 StringRef Value
) const {
260 unsigned Index
= BaseArgs
.MakeIndex(Opt
.getName(), Value
);
261 SynthesizedArgs
.push_back(
262 std::make_unique
<Arg
>(Opt
, MakeArgString(Opt
.getPrefix() + Opt
.getName()),
263 Index
, BaseArgs
.getArgString(Index
+ 1), BaseArg
));
264 return SynthesizedArgs
.back().get();
267 Arg
*DerivedArgList::MakeJoinedArg(const Arg
*BaseArg
, const Option Opt
,
268 StringRef Value
) const {
269 unsigned Index
= BaseArgs
.MakeIndex((Opt
.getName() + Value
).str());
270 SynthesizedArgs
.push_back(std::make_unique
<Arg
>(
271 Opt
, MakeArgString(Opt
.getPrefix() + Opt
.getName()), Index
,
272 BaseArgs
.getArgString(Index
) + Opt
.getName().size(), BaseArg
));
273 return SynthesizedArgs
.back().get();