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::addOptInFlag(ArgStringList
&Output
, OptSpecifier Pos
,
99 OptSpecifier Neg
) const {
100 if (Arg
*A
= getLastArg(Pos
, Neg
))
101 if (A
->getOption().matches(Pos
))
102 A
->render(*this, Output
);
105 void ArgList::AddAllArgsExcept(ArgStringList
&Output
,
106 ArrayRef
<OptSpecifier
> Ids
,
107 ArrayRef
<OptSpecifier
> ExcludeIds
) const {
108 for (const Arg
*Arg
: *this) {
109 bool Excluded
= false;
110 for (OptSpecifier Id
: ExcludeIds
) {
111 if (Arg
->getOption().matches(Id
)) {
117 for (OptSpecifier Id
: Ids
) {
118 if (Arg
->getOption().matches(Id
)) {
120 Arg
->render(*this, Output
);
128 /// This is a nicer interface when you don't have a list of Ids to exclude.
129 void ArgList::AddAllArgs(ArgStringList
&Output
,
130 ArrayRef
<OptSpecifier
> Ids
) const {
131 ArrayRef
<OptSpecifier
> Exclude
= None
;
132 AddAllArgsExcept(Output
, Ids
, Exclude
);
135 /// This 3-opt variant of AddAllArgs could be eliminated in favor of one
136 /// that accepts a single specifier, given the above which accepts any number.
137 void ArgList::AddAllArgs(ArgStringList
&Output
, OptSpecifier Id0
,
138 OptSpecifier Id1
, OptSpecifier Id2
) const {
139 for (auto Arg
: filtered(Id0
, Id1
, Id2
)) {
141 Arg
->render(*this, Output
);
145 void ArgList::AddAllArgValues(ArgStringList
&Output
, OptSpecifier Id0
,
146 OptSpecifier Id1
, OptSpecifier Id2
) const {
147 for (auto Arg
: filtered(Id0
, Id1
, Id2
)) {
149 const auto &Values
= Arg
->getValues();
150 Output
.append(Values
.begin(), Values
.end());
154 void ArgList::AddAllArgsTranslated(ArgStringList
&Output
, OptSpecifier Id0
,
155 const char *Translation
,
157 for (auto Arg
: filtered(Id0
)) {
161 Output
.push_back(MakeArgString(StringRef(Translation
) +
164 Output
.push_back(Translation
);
165 Output
.push_back(Arg
->getValue(0));
170 void ArgList::ClaimAllArgs(OptSpecifier Id0
) const {
171 for (auto *Arg
: filtered(Id0
))
175 void ArgList::ClaimAllArgs() const {
176 for (auto *Arg
: *this)
177 if (!Arg
->isClaimed())
181 const char *ArgList::GetOrMakeJoinedArgString(unsigned Index
,
183 StringRef RHS
) const {
184 StringRef Cur
= getArgString(Index
);
185 if (Cur
.size() == LHS
.size() + RHS
.size() &&
186 Cur
.startswith(LHS
) && Cur
.endswith(RHS
))
189 return MakeArgString(LHS
+ RHS
);
192 void ArgList::print(raw_ostream
&O
) const {
193 for (Arg
*A
: *this) {
199 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
200 LLVM_DUMP_METHOD
void ArgList::dump() const { print(dbgs()); }
203 void InputArgList::releaseMemory() {
204 // An InputArgList always owns its arguments.
209 InputArgList::InputArgList(const char* const *ArgBegin
,
210 const char* const *ArgEnd
)
211 : NumInputArgStrings(ArgEnd
- ArgBegin
) {
212 ArgStrings
.append(ArgBegin
, ArgEnd
);
215 unsigned InputArgList::MakeIndex(StringRef String0
) const {
216 unsigned Index
= ArgStrings
.size();
218 // Tuck away so we have a reliable const char *.
219 SynthesizedStrings
.push_back(std::string(String0
));
220 ArgStrings
.push_back(SynthesizedStrings
.back().c_str());
225 unsigned InputArgList::MakeIndex(StringRef String0
,
226 StringRef String1
) const {
227 unsigned Index0
= MakeIndex(String0
);
228 unsigned Index1
= MakeIndex(String1
);
229 assert(Index0
+ 1 == Index1
&& "Unexpected non-consecutive indices!");
234 const char *InputArgList::MakeArgStringRef(StringRef Str
) const {
235 return getArgString(MakeIndex(Str
));
238 DerivedArgList::DerivedArgList(const InputArgList
&BaseArgs
)
239 : BaseArgs(BaseArgs
) {}
241 const char *DerivedArgList::MakeArgStringRef(StringRef Str
) const {
242 return BaseArgs
.MakeArgString(Str
);
245 void DerivedArgList::AddSynthesizedArg(Arg
*A
) {
246 SynthesizedArgs
.push_back(std::unique_ptr
<Arg
>(A
));
249 Arg
*DerivedArgList::MakeFlagArg(const Arg
*BaseArg
, const Option Opt
) const {
250 SynthesizedArgs
.push_back(
251 std::make_unique
<Arg
>(Opt
, MakeArgString(Opt
.getPrefix() + Opt
.getName()),
252 BaseArgs
.MakeIndex(Opt
.getName()), BaseArg
));
253 return SynthesizedArgs
.back().get();
256 Arg
*DerivedArgList::MakePositionalArg(const Arg
*BaseArg
, const Option Opt
,
257 StringRef Value
) const {
258 unsigned Index
= BaseArgs
.MakeIndex(Value
);
259 SynthesizedArgs
.push_back(
260 std::make_unique
<Arg
>(Opt
, MakeArgString(Opt
.getPrefix() + Opt
.getName()),
261 Index
, BaseArgs
.getArgString(Index
), BaseArg
));
262 return SynthesizedArgs
.back().get();
265 Arg
*DerivedArgList::MakeSeparateArg(const Arg
*BaseArg
, const Option Opt
,
266 StringRef Value
) const {
267 unsigned Index
= BaseArgs
.MakeIndex(Opt
.getName(), Value
);
268 SynthesizedArgs
.push_back(
269 std::make_unique
<Arg
>(Opt
, MakeArgString(Opt
.getPrefix() + Opt
.getName()),
270 Index
, BaseArgs
.getArgString(Index
+ 1), BaseArg
));
271 return SynthesizedArgs
.back().get();
274 Arg
*DerivedArgList::MakeJoinedArg(const Arg
*BaseArg
, const Option Opt
,
275 StringRef Value
) const {
276 unsigned Index
= BaseArgs
.MakeIndex((Opt
.getName() + Value
).str());
277 SynthesizedArgs
.push_back(std::make_unique
<Arg
>(
278 Opt
, MakeArgString(Opt
.getPrefix() + Opt
.getName()), Index
,
279 BaseArgs
.getArgString(Index
) + Opt
.getName().size(), BaseArg
));
280 return SynthesizedArgs
.back().get();