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::hasFlag(OptSpecifier Pos
, OptSpecifier PosAlias
, OptSpecifier Neg
,
80 if (Arg
*A
= getLastArg(Pos
, PosAlias
, Neg
))
81 return A
->getOption().matches(Pos
) || A
->getOption().matches(PosAlias
);
85 StringRef
ArgList::getLastArgValue(OptSpecifier Id
, StringRef Default
) const {
86 if (Arg
*A
= getLastArg(Id
))
91 std::vector
<std::string
> ArgList::getAllArgValues(OptSpecifier Id
) const {
92 SmallVector
<const char *, 16> Values
;
93 AddAllArgValues(Values
, Id
);
94 return std::vector
<std::string
>(Values
.begin(), Values
.end());
97 void ArgList::addOptInFlag(ArgStringList
&Output
, OptSpecifier Pos
,
98 OptSpecifier Neg
) const {
99 if (Arg
*A
= getLastArg(Pos
, Neg
))
100 if (A
->getOption().matches(Pos
))
101 A
->render(*this, Output
);
104 void ArgList::AddAllArgsExcept(ArgStringList
&Output
,
105 ArrayRef
<OptSpecifier
> Ids
,
106 ArrayRef
<OptSpecifier
> ExcludeIds
) const {
107 for (const Arg
*Arg
: *this) {
108 bool Excluded
= false;
109 for (OptSpecifier Id
: ExcludeIds
) {
110 if (Arg
->getOption().matches(Id
)) {
116 for (OptSpecifier Id
: Ids
) {
117 if (Arg
->getOption().matches(Id
)) {
119 Arg
->render(*this, Output
);
127 /// This is a nicer interface when you don't have a list of Ids to exclude.
128 void ArgList::AddAllArgs(ArgStringList
&Output
,
129 ArrayRef
<OptSpecifier
> Ids
) const {
130 ArrayRef
<OptSpecifier
> Exclude
= std::nullopt
;
131 AddAllArgsExcept(Output
, Ids
, Exclude
);
134 /// This 3-opt variant of AddAllArgs could be eliminated in favor of one
135 /// that accepts a single specifier, given the above which accepts any number.
136 void ArgList::AddAllArgs(ArgStringList
&Output
, OptSpecifier Id0
,
137 OptSpecifier Id1
, OptSpecifier Id2
) const {
138 for (auto *Arg
: filtered(Id0
, Id1
, Id2
)) {
140 Arg
->render(*this, Output
);
144 void ArgList::AddAllArgValues(ArgStringList
&Output
, OptSpecifier Id0
,
145 OptSpecifier Id1
, OptSpecifier Id2
) const {
146 for (auto *Arg
: filtered(Id0
, Id1
, Id2
)) {
148 const auto &Values
= Arg
->getValues();
149 Output
.append(Values
.begin(), Values
.end());
153 void ArgList::AddAllArgsTranslated(ArgStringList
&Output
, OptSpecifier Id0
,
154 const char *Translation
,
156 for (auto *Arg
: filtered(Id0
)) {
160 Output
.push_back(MakeArgString(StringRef(Translation
) +
163 Output
.push_back(Translation
);
164 Output
.push_back(Arg
->getValue(0));
169 void ArgList::ClaimAllArgs(OptSpecifier Id0
) const {
170 for (auto *Arg
: filtered(Id0
))
174 void ArgList::ClaimAllArgs() const {
175 for (auto *Arg
: *this)
176 if (!Arg
->isClaimed())
180 const char *ArgList::GetOrMakeJoinedArgString(unsigned Index
,
182 StringRef RHS
) const {
183 StringRef Cur
= getArgString(Index
);
184 if (Cur
.size() == LHS
.size() + RHS
.size() &&
185 Cur
.startswith(LHS
) && Cur
.endswith(RHS
))
188 return MakeArgString(LHS
+ RHS
);
191 void ArgList::print(raw_ostream
&O
) const {
192 for (Arg
*A
: *this) {
198 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
199 LLVM_DUMP_METHOD
void ArgList::dump() const { print(dbgs()); }
202 void InputArgList::releaseMemory() {
203 // An InputArgList always owns its arguments.
208 InputArgList::InputArgList(const char* const *ArgBegin
,
209 const char* const *ArgEnd
)
210 : NumInputArgStrings(ArgEnd
- ArgBegin
) {
211 ArgStrings
.append(ArgBegin
, ArgEnd
);
214 unsigned InputArgList::MakeIndex(StringRef String0
) const {
215 unsigned Index
= ArgStrings
.size();
217 // Tuck away so we have a reliable const char *.
218 SynthesizedStrings
.push_back(std::string(String0
));
219 ArgStrings
.push_back(SynthesizedStrings
.back().c_str());
224 unsigned InputArgList::MakeIndex(StringRef String0
,
225 StringRef String1
) const {
226 unsigned Index0
= MakeIndex(String0
);
227 unsigned Index1
= MakeIndex(String1
);
228 assert(Index0
+ 1 == Index1
&& "Unexpected non-consecutive indices!");
233 const char *InputArgList::MakeArgStringRef(StringRef Str
) const {
234 return getArgString(MakeIndex(Str
));
237 DerivedArgList::DerivedArgList(const InputArgList
&BaseArgs
)
238 : BaseArgs(BaseArgs
) {}
240 const char *DerivedArgList::MakeArgStringRef(StringRef Str
) const {
241 return BaseArgs
.MakeArgString(Str
);
244 void DerivedArgList::AddSynthesizedArg(Arg
*A
) {
245 SynthesizedArgs
.push_back(std::unique_ptr
<Arg
>(A
));
248 Arg
*DerivedArgList::MakeFlagArg(const Arg
*BaseArg
, const Option Opt
) const {
249 SynthesizedArgs
.push_back(
250 std::make_unique
<Arg
>(Opt
, MakeArgString(Opt
.getPrefix() + Opt
.getName()),
251 BaseArgs
.MakeIndex(Opt
.getName()), BaseArg
));
252 return SynthesizedArgs
.back().get();
255 Arg
*DerivedArgList::MakePositionalArg(const Arg
*BaseArg
, const Option Opt
,
256 StringRef Value
) const {
257 unsigned Index
= BaseArgs
.MakeIndex(Value
);
258 SynthesizedArgs
.push_back(
259 std::make_unique
<Arg
>(Opt
, MakeArgString(Opt
.getPrefix() + Opt
.getName()),
260 Index
, BaseArgs
.getArgString(Index
), BaseArg
));
261 return SynthesizedArgs
.back().get();
264 Arg
*DerivedArgList::MakeSeparateArg(const Arg
*BaseArg
, const Option Opt
,
265 StringRef Value
) const {
266 unsigned Index
= BaseArgs
.MakeIndex(Opt
.getName(), Value
);
267 SynthesizedArgs
.push_back(
268 std::make_unique
<Arg
>(Opt
, MakeArgString(Opt
.getPrefix() + Opt
.getName()),
269 Index
, BaseArgs
.getArgString(Index
+ 1), BaseArg
));
270 return SynthesizedArgs
.back().get();
273 Arg
*DerivedArgList::MakeJoinedArg(const Arg
*BaseArg
, const Option Opt
,
274 StringRef Value
) const {
275 unsigned Index
= BaseArgs
.MakeIndex((Opt
.getName() + Value
).str());
276 SynthesizedArgs
.push_back(std::make_unique
<Arg
>(
277 Opt
, MakeArgString(Opt
.getPrefix() + Opt
.getName()), Index
,
278 BaseArgs
.getArgString(Index
) + Opt
.getName().size(), BaseArg
));
279 return SynthesizedArgs
.back().get();