File indexing completed on 2026-05-10 08:44:22
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef LLVM_OPTION_ARGLIST_H
0010 #define LLVM_OPTION_ARGLIST_H
0011
0012 #include "llvm/ADT/ArrayRef.h"
0013 #include "llvm/ADT/DenseMap.h"
0014 #include "llvm/ADT/iterator_range.h"
0015 #include "llvm/ADT/SmallString.h"
0016 #include "llvm/ADT/SmallVector.h"
0017 #include "llvm/ADT/StringRef.h"
0018 #include "llvm/ADT/Twine.h"
0019 #include "llvm/Option/Arg.h"
0020 #include "llvm/Option/OptSpecifier.h"
0021 #include "llvm/Option/Option.h"
0022 #include <algorithm>
0023 #include <cstddef>
0024 #include <initializer_list>
0025 #include <iterator>
0026 #include <list>
0027 #include <memory>
0028 #include <string>
0029 #include <utility>
0030 #include <vector>
0031
0032 namespace llvm {
0033
0034 class raw_ostream;
0035
0036 namespace opt {
0037
0038
0039 template<typename BaseIter, unsigned NumOptSpecifiers = 0>
0040 class arg_iterator {
0041
0042 BaseIter Current, End;
0043
0044
0045
0046 OptSpecifier Ids[NumOptSpecifiers ? NumOptSpecifiers : 1];
0047
0048 void SkipToNextArg() {
0049 for (; Current != End; ++Current) {
0050
0051 if (!*Current)
0052 continue;
0053
0054
0055 if (!NumOptSpecifiers)
0056 return;
0057
0058
0059 const Option &O = (*Current)->getOption();
0060 for (auto Id : Ids) {
0061 if (!Id.isValid())
0062 break;
0063 if (O.matches(Id))
0064 return;
0065 }
0066 }
0067 }
0068
0069 using Traits = std::iterator_traits<BaseIter>;
0070
0071 public:
0072 using value_type = typename Traits::value_type;
0073 using reference = typename Traits::reference;
0074 using pointer = typename Traits::pointer;
0075 using iterator_category = std::forward_iterator_tag;
0076 using difference_type = std::ptrdiff_t;
0077
0078 arg_iterator(
0079 BaseIter Current, BaseIter End,
0080 const OptSpecifier (&Ids)[NumOptSpecifiers ? NumOptSpecifiers : 1] = {})
0081 : Current(Current), End(End) {
0082 for (unsigned I = 0; I != NumOptSpecifiers; ++I)
0083 this->Ids[I] = Ids[I];
0084 SkipToNextArg();
0085 }
0086
0087 reference operator*() const { return *Current; }
0088 pointer operator->() const { return Current; }
0089
0090 arg_iterator &operator++() {
0091 ++Current;
0092 SkipToNextArg();
0093 return *this;
0094 }
0095
0096 arg_iterator operator++(int) {
0097 arg_iterator tmp(*this);
0098 ++(*this);
0099 return tmp;
0100 }
0101
0102 friend bool operator==(arg_iterator LHS, arg_iterator RHS) {
0103 return LHS.Current == RHS.Current;
0104 }
0105 friend bool operator!=(arg_iterator LHS, arg_iterator RHS) {
0106 return !(LHS == RHS);
0107 }
0108 };
0109
0110
0111
0112
0113
0114
0115
0116 class ArgList {
0117 public:
0118 using arglist_type = SmallVector<Arg *, 16>;
0119 using iterator = arg_iterator<arglist_type::iterator>;
0120 using const_iterator = arg_iterator<arglist_type::const_iterator>;
0121 using reverse_iterator = arg_iterator<arglist_type::reverse_iterator>;
0122 using const_reverse_iterator =
0123 arg_iterator<arglist_type::const_reverse_iterator>;
0124
0125 template<unsigned N> using filtered_iterator =
0126 arg_iterator<arglist_type::const_iterator, N>;
0127 template<unsigned N> using filtered_reverse_iterator =
0128 arg_iterator<arglist_type::const_reverse_iterator, N>;
0129
0130 private:
0131
0132 arglist_type Args;
0133
0134 using OptRange = std::pair<unsigned, unsigned>;
0135 static OptRange emptyRange() { return {-1u, 0u}; }
0136
0137
0138 DenseMap<unsigned, OptRange> OptRanges;
0139
0140
0141
0142 OptRange getRange(std::initializer_list<OptSpecifier> Ids) const;
0143
0144 protected:
0145
0146
0147
0148 ArgList() = default;
0149
0150
0151
0152
0153
0154
0155 ArgList(ArgList &&RHS)
0156 : Args(std::move(RHS.Args)), OptRanges(std::move(RHS.OptRanges)) {
0157 RHS.Args.clear();
0158 RHS.OptRanges.clear();
0159 }
0160
0161 ArgList &operator=(ArgList &&RHS) {
0162 Args = std::move(RHS.Args);
0163 RHS.Args.clear();
0164 OptRanges = std::move(RHS.OptRanges);
0165 RHS.OptRanges.clear();
0166 return *this;
0167 }
0168
0169
0170 ~ArgList() = default;
0171
0172
0173
0174 static OptSpecifier toOptSpecifier(OptSpecifier S) { return S; }
0175
0176 public:
0177
0178
0179
0180
0181 void append(Arg *A);
0182
0183 const arglist_type &getArgs() const { return Args; }
0184
0185 unsigned size() const { return Args.size(); }
0186
0187
0188
0189
0190
0191 iterator begin() { return {Args.begin(), Args.end()}; }
0192 iterator end() { return {Args.end(), Args.end()}; }
0193
0194 reverse_iterator rbegin() { return {Args.rbegin(), Args.rend()}; }
0195 reverse_iterator rend() { return {Args.rend(), Args.rend()}; }
0196
0197 const_iterator begin() const { return {Args.begin(), Args.end()}; }
0198 const_iterator end() const { return {Args.end(), Args.end()}; }
0199
0200 const_reverse_iterator rbegin() const { return {Args.rbegin(), Args.rend()}; }
0201 const_reverse_iterator rend() const { return {Args.rend(), Args.rend()}; }
0202
0203 template<typename ...OptSpecifiers>
0204 iterator_range<filtered_iterator<sizeof...(OptSpecifiers)>>
0205 filtered(OptSpecifiers ...Ids) const {
0206 OptRange Range = getRange({toOptSpecifier(Ids)...});
0207 auto B = Args.begin() + Range.first;
0208 auto E = Args.begin() + Range.second;
0209 using Iterator = filtered_iterator<sizeof...(OptSpecifiers)>;
0210 return make_range(Iterator(B, E, {toOptSpecifier(Ids)...}),
0211 Iterator(E, E, {toOptSpecifier(Ids)...}));
0212 }
0213
0214 template<typename ...OptSpecifiers>
0215 iterator_range<filtered_reverse_iterator<sizeof...(OptSpecifiers)>>
0216 filtered_reverse(OptSpecifiers ...Ids) const {
0217 OptRange Range = getRange({toOptSpecifier(Ids)...});
0218 auto B = Args.rend() - Range.second;
0219 auto E = Args.rend() - Range.first;
0220 using Iterator = filtered_reverse_iterator<sizeof...(OptSpecifiers)>;
0221 return make_range(Iterator(B, E, {toOptSpecifier(Ids)...}),
0222 Iterator(E, E, {toOptSpecifier(Ids)...}));
0223 }
0224
0225
0226
0227
0228
0229
0230 void eraseArg(OptSpecifier Id);
0231
0232
0233
0234
0235
0236
0237
0238
0239 template<typename ...OptSpecifiers>
0240 bool hasArgNoClaim(OptSpecifiers ...Ids) const {
0241 return getLastArgNoClaim(Ids...) != nullptr;
0242 }
0243 template<typename ...OptSpecifiers>
0244 bool hasArg(OptSpecifiers ...Ids) const {
0245 return getLastArg(Ids...) != nullptr;
0246 }
0247
0248
0249 bool hasMultipleArgs(OptSpecifier Id) const {
0250 auto Args = filtered(Id);
0251 return (Args.begin() != Args.end()) && (++Args.begin()) != Args.end();
0252 }
0253
0254
0255 template<typename ...OptSpecifiers>
0256 Arg *getLastArg(OptSpecifiers ...Ids) const {
0257 Arg *Res = nullptr;
0258 for (Arg *A : filtered(Ids...)) {
0259 Res = A;
0260 Res->claim();
0261 }
0262 return Res;
0263 }
0264
0265
0266
0267 template<typename ...OptSpecifiers>
0268 Arg *getLastArgNoClaim(OptSpecifiers ...Ids) const {
0269 for (Arg *A : filtered_reverse(Ids...))
0270 return A;
0271 return nullptr;
0272 }
0273
0274
0275 virtual const char *getArgString(unsigned Index) const = 0;
0276
0277
0278
0279
0280 virtual unsigned getNumInputArgStrings() const = 0;
0281
0282
0283
0284
0285
0286
0287 StringRef getLastArgValue(OptSpecifier Id, StringRef Default = "") const;
0288
0289
0290
0291 std::vector<std::string> getAllArgValues(OptSpecifier Id) const;
0292
0293
0294
0295
0296
0297
0298
0299
0300
0301 bool hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const;
0302 bool hasFlagNoClaim(OptSpecifier Pos, OptSpecifier Neg, bool Default) const;
0303
0304
0305
0306
0307
0308 bool hasFlag(OptSpecifier Pos, OptSpecifier PosAlias, OptSpecifier Neg,
0309 bool Default) const;
0310
0311
0312
0313 void addOptInFlag(ArgStringList &Output, OptSpecifier Pos,
0314 OptSpecifier Neg) const;
0315
0316 void addOptOutFlag(ArgStringList &Output, OptSpecifier Pos,
0317 OptSpecifier Neg) const {
0318 addOptInFlag(Output, Neg, Pos);
0319 }
0320
0321
0322 template <typename... OptSpecifiers>
0323 void addLastArg(ArgStringList &Output, OptSpecifiers... Ids) const {
0324 if (Arg *A = getLastArg(Ids...))
0325 A->render(*this, Output);
0326 }
0327 template <typename... OptSpecifiers>
0328 void AddLastArg(ArgStringList &Output, OptSpecifiers... Ids) const {
0329 addLastArg(Output, Ids...);
0330 }
0331
0332
0333
0334 void AddAllArgsExcept(ArgStringList &Output, ArrayRef<OptSpecifier> Ids,
0335 ArrayRef<OptSpecifier> ExcludeIds) const;
0336
0337 void addAllArgs(ArgStringList &Output, ArrayRef<OptSpecifier> Ids) const;
0338
0339
0340 void AddAllArgs(ArgStringList &Output, OptSpecifier Id0) const;
0341
0342
0343
0344 void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
0345 OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;
0346
0347
0348
0349
0350
0351
0352
0353 void AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
0354 const char *Translation,
0355 bool Joined = false) const;
0356
0357
0358
0359 void ClaimAllArgs(OptSpecifier Id0) const;
0360
0361 template <typename... OptSpecifiers>
0362 void claimAllArgs(OptSpecifiers... Ids) const {
0363 for (Arg *A : filtered(Ids...))
0364 A->claim();
0365 }
0366
0367
0368
0369 void ClaimAllArgs() const;
0370
0371
0372
0373
0374
0375
0376 virtual const char *MakeArgStringRef(StringRef Str) const = 0;
0377 const char *MakeArgString(const Twine &Str) const {
0378 SmallString<256> Buf;
0379 return MakeArgStringRef(Str.toStringRef(Buf));
0380 }
0381
0382
0383
0384 const char *GetOrMakeJoinedArgString(unsigned Index, StringRef LHS,
0385 StringRef RHS) const;
0386
0387 void print(raw_ostream &O) const;
0388 void dump() const;
0389
0390
0391 };
0392
0393 class InputArgList final : public ArgList {
0394 private:
0395
0396
0397
0398
0399
0400 mutable ArgStringList ArgStrings;
0401
0402
0403
0404
0405
0406
0407 mutable std::list<std::string> SynthesizedStrings;
0408
0409
0410 unsigned NumInputArgStrings;
0411
0412
0413 void releaseMemory();
0414
0415 public:
0416 InputArgList() : NumInputArgStrings(0) {}
0417
0418 InputArgList(const char* const *ArgBegin, const char* const *ArgEnd);
0419
0420 InputArgList(InputArgList &&RHS)
0421 : ArgList(std::move(RHS)), ArgStrings(std::move(RHS.ArgStrings)),
0422 SynthesizedStrings(std::move(RHS.SynthesizedStrings)),
0423 NumInputArgStrings(RHS.NumInputArgStrings) {}
0424
0425 InputArgList &operator=(InputArgList &&RHS) {
0426 if (this == &RHS)
0427 return *this;
0428 releaseMemory();
0429 ArgList::operator=(std::move(RHS));
0430 ArgStrings = std::move(RHS.ArgStrings);
0431 SynthesizedStrings = std::move(RHS.SynthesizedStrings);
0432 NumInputArgStrings = RHS.NumInputArgStrings;
0433 return *this;
0434 }
0435
0436 ~InputArgList() { releaseMemory(); }
0437
0438 const char *getArgString(unsigned Index) const override {
0439 return ArgStrings[Index];
0440 }
0441
0442 void replaceArgString(unsigned Index, const Twine &S) {
0443 ArgStrings[Index] = MakeArgString(S);
0444 }
0445
0446 unsigned getNumInputArgStrings() const override {
0447 return NumInputArgStrings;
0448 }
0449
0450
0451
0452
0453 public:
0454
0455 unsigned MakeIndex(StringRef String0) const;
0456 unsigned MakeIndex(StringRef String0, StringRef String1) const;
0457
0458 using ArgList::MakeArgString;
0459 const char *MakeArgStringRef(StringRef Str) const override;
0460
0461
0462 };
0463
0464
0465
0466 class DerivedArgList final : public ArgList {
0467 const InputArgList &BaseArgs;
0468
0469
0470 mutable SmallVector<std::unique_ptr<Arg>, 16> SynthesizedArgs;
0471
0472 public:
0473
0474 DerivedArgList(const InputArgList &BaseArgs);
0475
0476 const char *getArgString(unsigned Index) const override {
0477 return BaseArgs.getArgString(Index);
0478 }
0479
0480 unsigned getNumInputArgStrings() const override {
0481 return BaseArgs.getNumInputArgStrings();
0482 }
0483
0484 const InputArgList &getBaseArgs() const {
0485 return BaseArgs;
0486 }
0487
0488
0489
0490
0491
0492
0493 void AddSynthesizedArg(Arg *A);
0494
0495 using ArgList::MakeArgString;
0496 const char *MakeArgStringRef(StringRef Str) const override;
0497
0498
0499
0500 void AddFlagArg(const Arg *BaseArg, const Option Opt) {
0501 append(MakeFlagArg(BaseArg, Opt));
0502 }
0503
0504
0505
0506
0507 void AddPositionalArg(const Arg *BaseArg, const Option Opt,
0508 StringRef Value) {
0509 append(MakePositionalArg(BaseArg, Opt, Value));
0510 }
0511
0512
0513
0514
0515 void AddSeparateArg(const Arg *BaseArg, const Option Opt,
0516 StringRef Value) {
0517 append(MakeSeparateArg(BaseArg, Opt, Value));
0518 }
0519
0520
0521
0522 void AddJoinedArg(const Arg *BaseArg, const Option Opt,
0523 StringRef Value) {
0524 append(MakeJoinedArg(BaseArg, Opt, Value));
0525 }
0526
0527
0528 Arg *MakeFlagArg(const Arg *BaseArg, const Option Opt) const;
0529
0530
0531
0532 Arg *MakePositionalArg(const Arg *BaseArg, const Option Opt,
0533 StringRef Value) const;
0534
0535
0536
0537 Arg *MakeSeparateArg(const Arg *BaseArg, const Option Opt,
0538 StringRef Value) const;
0539
0540
0541
0542 Arg *MakeJoinedArg(const Arg *BaseArg, const Option Opt,
0543 StringRef Value) const;
0544
0545
0546 };
0547
0548 }
0549
0550 }
0551
0552 #endif