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/SmallVector.h"
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/ADT/StringRef.h"
13 #include "llvm/ADT/Twine.h"
14 #include "llvm/Config/llvm-config.h"
15 #include "llvm/Option/Arg.h"
16 #include "llvm/Option/ArgList.h"
17 #include "llvm/Option/Option.h"
18 #include "llvm/Option/OptSpecifier.h"
19 #include "llvm/Support/Compiler.h"
20 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/raw_ostream.h"
30 using namespace llvm::opt
;
32 void ArgList::append(Arg
*A
) {
35 // Update ranges for the option and all of its groups.
36 for (Option O
= A
->getOption().getUnaliasedOption(); O
.isValid();
39 OptRanges
.insert(std::make_pair(O
.getID(), emptyRange())).first
->second
;
40 R
.first
= std::min
<unsigned>(R
.first
, Args
.size() - 1);
41 R
.second
= Args
.size();
45 void ArgList::eraseArg(OptSpecifier Id
) {
46 // Zero out the removed entries but keep them around so that we don't
47 // need to invalidate OptRanges.
48 for (Arg
*const &A
: filtered(Id
)) {
49 // Avoid the need for a non-const filtered iterator variant.
50 Arg
**ArgsBegin
= Args
.data();
51 ArgsBegin
[&A
- ArgsBegin
] = nullptr;
53 OptRanges
.erase(Id
.getID());
57 ArgList::getRange(std::initializer_list
<OptSpecifier
> Ids
) const {
58 OptRange R
= emptyRange();
60 auto I
= OptRanges
.find(Id
.getID());
61 if (I
!= OptRanges
.end()) {
62 R
.first
= std::min(R
.first
, I
->second
.first
);
63 R
.second
= std::max(R
.second
, I
->second
.second
);
66 // Map an empty {-1, 0} range to {0, 0} so it can be used to form iterators.
72 bool ArgList::hasFlag(OptSpecifier Pos
, OptSpecifier Neg
, bool Default
) const {
73 if (Arg
*A
= getLastArg(Pos
, Neg
))
74 return A
->getOption().matches(Pos
);
78 bool ArgList::hasFlagNoClaim(OptSpecifier Pos
, OptSpecifier Neg
,
80 if (Arg
*A
= getLastArgNoClaim(Pos
, Neg
))
81 return A
->getOption().matches(Pos
);
85 bool ArgList::hasFlag(OptSpecifier Pos
, OptSpecifier PosAlias
, OptSpecifier Neg
,
87 if (Arg
*A
= getLastArg(Pos
, PosAlias
, Neg
))
88 return A
->getOption().matches(Pos
) || A
->getOption().matches(PosAlias
);
92 StringRef
ArgList::getLastArgValue(OptSpecifier Id
, StringRef Default
) const {
93 if (Arg
*A
= getLastArg(Id
))
98 std::vector
<std::string
> ArgList::getAllArgValues(OptSpecifier Id
) const {
99 SmallVector
<const char *, 16> Values
;
100 AddAllArgValues(Values
, Id
);
101 return std::vector
<std::string
>(Values
.begin(), Values
.end());
104 void ArgList::addOptInFlag(ArgStringList
&Output
, OptSpecifier Pos
,
105 OptSpecifier Neg
) const {
106 if (Arg
*A
= getLastArg(Pos
, Neg
))
107 if (A
->getOption().matches(Pos
))
108 A
->render(*this, Output
);
111 void ArgList::AddAllArgsExcept(ArgStringList
&Output
,
112 ArrayRef
<OptSpecifier
> Ids
,
113 ArrayRef
<OptSpecifier
> ExcludeIds
) const {
114 for (const Arg
*Arg
: *this) {
115 bool Excluded
= false;
116 for (OptSpecifier Id
: ExcludeIds
) {
117 if (Arg
->getOption().matches(Id
)) {
123 for (OptSpecifier Id
: Ids
) {
124 if (Arg
->getOption().matches(Id
)) {
126 Arg
->render(*this, Output
);
134 /// This is a nicer interface when you don't have a list of Ids to exclude.
135 void ArgList::addAllArgs(ArgStringList
&Output
,
136 ArrayRef
<OptSpecifier
> Ids
) const {
137 ArrayRef
<OptSpecifier
> Exclude
= {};
138 AddAllArgsExcept(Output
, Ids
, Exclude
);
141 void ArgList::AddAllArgs(ArgStringList
&Output
, OptSpecifier Id0
) const {
142 for (auto *Arg
: filtered(Id0
)) {
144 Arg
->render(*this, Output
);
148 void ArgList::AddAllArgValues(ArgStringList
&Output
, OptSpecifier Id0
,
149 OptSpecifier Id1
, OptSpecifier Id2
) const {
150 for (auto *Arg
: filtered(Id0
, Id1
, Id2
)) {
152 const auto &Values
= Arg
->getValues();
153 Output
.append(Values
.begin(), Values
.end());
157 void ArgList::AddAllArgsTranslated(ArgStringList
&Output
, OptSpecifier Id0
,
158 const char *Translation
,
160 for (auto *Arg
: filtered(Id0
)) {
164 Output
.push_back(MakeArgString(StringRef(Translation
) +
167 Output
.push_back(Translation
);
168 Output
.push_back(Arg
->getValue(0));
173 void ArgList::ClaimAllArgs(OptSpecifier Id0
) const {
174 for (auto *Arg
: filtered(Id0
))
178 void ArgList::ClaimAllArgs() const {
179 for (auto *Arg
: *this)
180 if (!Arg
->isClaimed())
184 const char *ArgList::GetOrMakeJoinedArgString(unsigned Index
,
186 StringRef RHS
) const {
187 StringRef Cur
= getArgString(Index
);
188 if (Cur
.size() == LHS
.size() + RHS
.size() && Cur
.starts_with(LHS
) &&
192 return MakeArgString(LHS
+ RHS
);
195 void ArgList::print(raw_ostream
&O
) const {
196 for (Arg
*A
: *this) {
202 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
203 LLVM_DUMP_METHOD
void ArgList::dump() const { print(dbgs()); }
206 void InputArgList::releaseMemory() {
207 // An InputArgList always owns its arguments.
212 InputArgList::InputArgList(const char* const *ArgBegin
,
213 const char* const *ArgEnd
)
214 : NumInputArgStrings(ArgEnd
- ArgBegin
) {
215 ArgStrings
.append(ArgBegin
, ArgEnd
);
218 unsigned InputArgList::MakeIndex(StringRef String0
) const {
219 unsigned Index
= ArgStrings
.size();
221 // Tuck away so we have a reliable const char *.
222 SynthesizedStrings
.push_back(std::string(String0
));
223 ArgStrings
.push_back(SynthesizedStrings
.back().c_str());
228 unsigned InputArgList::MakeIndex(StringRef String0
,
229 StringRef String1
) const {
230 unsigned Index0
= MakeIndex(String0
);
231 unsigned Index1
= MakeIndex(String1
);
232 assert(Index0
+ 1 == Index1
&& "Unexpected non-consecutive indices!");
237 const char *InputArgList::MakeArgStringRef(StringRef Str
) const {
238 return getArgString(MakeIndex(Str
));
241 DerivedArgList::DerivedArgList(const InputArgList
&BaseArgs
)
242 : BaseArgs(BaseArgs
) {}
244 const char *DerivedArgList::MakeArgStringRef(StringRef Str
) const {
245 return BaseArgs
.MakeArgString(Str
);
248 void DerivedArgList::AddSynthesizedArg(Arg
*A
) {
249 SynthesizedArgs
.push_back(std::unique_ptr
<Arg
>(A
));
252 Arg
*DerivedArgList::MakeFlagArg(const Arg
*BaseArg
, const Option Opt
) const {
253 SynthesizedArgs
.push_back(
254 std::make_unique
<Arg
>(Opt
, MakeArgString(Opt
.getPrefix() + Opt
.getName()),
255 BaseArgs
.MakeIndex(Opt
.getName()), BaseArg
));
256 return SynthesizedArgs
.back().get();
259 Arg
*DerivedArgList::MakePositionalArg(const Arg
*BaseArg
, const Option Opt
,
260 StringRef Value
) const {
261 unsigned Index
= BaseArgs
.MakeIndex(Value
);
262 SynthesizedArgs
.push_back(
263 std::make_unique
<Arg
>(Opt
, MakeArgString(Opt
.getPrefix() + Opt
.getName()),
264 Index
, BaseArgs
.getArgString(Index
), BaseArg
));
265 return SynthesizedArgs
.back().get();
268 Arg
*DerivedArgList::MakeSeparateArg(const Arg
*BaseArg
, const Option Opt
,
269 StringRef Value
) const {
270 unsigned Index
= BaseArgs
.MakeIndex(Opt
.getName(), Value
);
271 SynthesizedArgs
.push_back(
272 std::make_unique
<Arg
>(Opt
, MakeArgString(Opt
.getPrefix() + Opt
.getName()),
273 Index
, BaseArgs
.getArgString(Index
+ 1), BaseArg
));
274 return SynthesizedArgs
.back().get();
277 Arg
*DerivedArgList::MakeJoinedArg(const Arg
*BaseArg
, const Option Opt
,
278 StringRef Value
) const {
279 unsigned Index
= BaseArgs
.MakeIndex((Opt
.getName() + Value
).str());
280 SynthesizedArgs
.push_back(std::make_unique
<Arg
>(
281 Opt
, MakeArgString(Opt
.getPrefix() + Opt
.getName()), Index
,
282 BaseArgs
.getArgString(Index
) + Opt
.getName().size(), BaseArg
));
283 return SynthesizedArgs
.back().get();