xref: /freebsd/contrib/llvm-project/llvm/include/llvm/Option/ArgList.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- ArgList.h - Argument List Management ---------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef LLVM_OPTION_ARGLIST_H
10 #define LLVM_OPTION_ARGLIST_H
11 
12 #include "llvm/ADT/ArrayRef.h"
13 #include "llvm/ADT/DenseMap.h"
14 #include "llvm/ADT/SmallString.h"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/ADT/Twine.h"
18 #include "llvm/ADT/iterator_range.h"
19 #include "llvm/Option/Arg.h"
20 #include "llvm/Option/OptSpecifier.h"
21 #include "llvm/Option/Option.h"
22 #include "llvm/Support/Compiler.h"
23 #include <algorithm>
24 #include <cstddef>
25 #include <initializer_list>
26 #include <iterator>
27 #include <list>
28 #include <memory>
29 #include <string>
30 #include <utility>
31 #include <vector>
32 
33 namespace llvm {
34 
35 class raw_ostream;
36 
37 namespace opt {
38 
39 /// arg_iterator - Iterates through arguments stored inside an ArgList.
40 template<typename BaseIter, unsigned NumOptSpecifiers = 0>
41 class arg_iterator {
42   /// The current argument and the end of the sequence we're iterating.
43   BaseIter Current, End;
44 
45   /// Optional filters on the arguments which will be match. To avoid a
46   /// zero-sized array, we store one specifier even if we're asked for none.
47   OptSpecifier Ids[NumOptSpecifiers ? NumOptSpecifiers : 1];
48 
SkipToNextArg()49   void SkipToNextArg() {
50     for (; Current != End; ++Current) {
51       // Skip erased elements.
52       if (!*Current)
53         continue;
54 
55       // Done if there are no filters.
56       if (!NumOptSpecifiers)
57         return;
58 
59       // Otherwise require a match.
60       const Option &O = (*Current)->getOption();
61       for (auto Id : Ids) {
62         if (!Id.isValid())
63           break;
64         if (O.matches(Id))
65           return;
66       }
67     }
68   }
69 
70   using Traits = std::iterator_traits<BaseIter>;
71 
72 public:
73   using value_type = typename Traits::value_type;
74   using reference = typename Traits::reference;
75   using pointer = typename Traits::pointer;
76   using iterator_category = std::forward_iterator_tag;
77   using difference_type = std::ptrdiff_t;
78 
79   arg_iterator(
80       BaseIter Current, BaseIter End,
81       const OptSpecifier (&Ids)[NumOptSpecifiers ? NumOptSpecifiers : 1] = {})
Current(Current)82       : Current(Current), End(End) {
83     for (unsigned I = 0; I != NumOptSpecifiers; ++I)
84       this->Ids[I] = Ids[I];
85     SkipToNextArg();
86   }
87 
88   reference operator*() const { return *Current; }
89   pointer operator->() const { return Current; }
90 
91   arg_iterator &operator++() {
92     ++Current;
93     SkipToNextArg();
94     return *this;
95   }
96 
97   arg_iterator operator++(int) {
98     arg_iterator tmp(*this);
99     ++(*this);
100     return tmp;
101   }
102 
103   friend bool operator==(arg_iterator LHS, arg_iterator RHS) {
104     return LHS.Current == RHS.Current;
105   }
106   friend bool operator!=(arg_iterator LHS, arg_iterator RHS) {
107     return !(LHS == RHS);
108   }
109 };
110 
111 /// ArgList - Ordered collection of driver arguments.
112 ///
113 /// The ArgList class manages a list of Arg instances as well as
114 /// auxiliary data and convenience methods to allow Tools to quickly
115 /// check for the presence of Arg instances for a particular Option
116 /// and to iterate over groups of arguments.
117 class ArgList {
118 public:
119   using arglist_type = SmallVector<Arg *, 16>;
120   using iterator = arg_iterator<arglist_type::iterator>;
121   using const_iterator = arg_iterator<arglist_type::const_iterator>;
122   using reverse_iterator = arg_iterator<arglist_type::reverse_iterator>;
123   using const_reverse_iterator =
124       arg_iterator<arglist_type::const_reverse_iterator>;
125 
126   template<unsigned N> using filtered_iterator =
127       arg_iterator<arglist_type::const_iterator, N>;
128   template<unsigned N> using filtered_reverse_iterator =
129       arg_iterator<arglist_type::const_reverse_iterator, N>;
130 
131 private:
132   /// The internal list of arguments.
133   arglist_type Args;
134 
135   using OptRange = std::pair<unsigned, unsigned>;
emptyRange()136   static OptRange emptyRange() { return {-1u, 0u}; }
137 
138   /// The first and last index of each different OptSpecifier ID.
139   DenseMap<unsigned, OptRange> OptRanges;
140 
141   /// Get the range of indexes in which options with the specified IDs might
142   /// reside, or (0, 0) if there are no such options.
143   LLVM_ABI OptRange getRange(std::initializer_list<OptSpecifier> Ids) const;
144 
145 protected:
146   // Make the default special members protected so they won't be used to slice
147   // derived objects, but can still be used by derived objects to implement
148   // their own special members.
149   ArgList() = default;
150 
151   // Explicit move operations to ensure the container is cleared post-move
152   // otherwise it could lead to a double-delete in the case of moving of an
153   // InputArgList which deletes the contents of the container. If we could fix
154   // up the ownership here (delegate storage/ownership to the derived class so
155   // it can be a container of unique_ptr) this would be simpler.
ArgList(ArgList && RHS)156   ArgList(ArgList &&RHS)
157       : Args(std::move(RHS.Args)), OptRanges(std::move(RHS.OptRanges)) {
158     RHS.Args.clear();
159     RHS.OptRanges.clear();
160   }
161 
162   ArgList &operator=(ArgList &&RHS) {
163     Args = std::move(RHS.Args);
164     RHS.Args.clear();
165     OptRanges = std::move(RHS.OptRanges);
166     RHS.OptRanges.clear();
167     return *this;
168   }
169 
170   // Protect the dtor to ensure this type is never destroyed polymorphically.
171   ~ArgList() = default;
172 
173   // Implicitly convert a value to an OptSpecifier. Used to work around a bug
174   // in MSVC's implementation of narrowing conversion checking.
toOptSpecifier(OptSpecifier S)175   static OptSpecifier toOptSpecifier(OptSpecifier S) { return S; }
176 
177 public:
178   /// @name Arg Access
179   /// @{
180 
181   /// append - Append \p A to the arg list.
182   LLVM_ABI void append(Arg *A);
183 
getArgs()184   const arglist_type &getArgs() const { return Args; }
185 
size()186   unsigned size() const { return Args.size(); }
187 
188   /// @}
189   /// @name Arg Iteration
190   /// @{
191 
begin()192   iterator begin() { return {Args.begin(), Args.end()}; }
end()193   iterator end() { return {Args.end(), Args.end()}; }
194 
rbegin()195   reverse_iterator rbegin() { return {Args.rbegin(), Args.rend()}; }
rend()196   reverse_iterator rend() { return {Args.rend(), Args.rend()}; }
197 
begin()198   const_iterator begin() const { return {Args.begin(), Args.end()}; }
end()199   const_iterator end() const { return {Args.end(), Args.end()}; }
200 
rbegin()201   const_reverse_iterator rbegin() const { return {Args.rbegin(), Args.rend()}; }
rend()202   const_reverse_iterator rend() const { return {Args.rend(), Args.rend()}; }
203 
204   template<typename ...OptSpecifiers>
205   iterator_range<filtered_iterator<sizeof...(OptSpecifiers)>>
filtered(OptSpecifiers...Ids)206   filtered(OptSpecifiers ...Ids) const {
207     OptRange Range = getRange({toOptSpecifier(Ids)...});
208     auto B = Args.begin() + Range.first;
209     auto E = Args.begin() + Range.second;
210     using Iterator = filtered_iterator<sizeof...(OptSpecifiers)>;
211     return make_range(Iterator(B, E, {toOptSpecifier(Ids)...}),
212                       Iterator(E, E, {toOptSpecifier(Ids)...}));
213   }
214 
215   template<typename ...OptSpecifiers>
216   iterator_range<filtered_reverse_iterator<sizeof...(OptSpecifiers)>>
filtered_reverse(OptSpecifiers...Ids)217   filtered_reverse(OptSpecifiers ...Ids) const {
218     OptRange Range = getRange({toOptSpecifier(Ids)...});
219     auto B = Args.rend() - Range.second;
220     auto E = Args.rend() - Range.first;
221     using Iterator = filtered_reverse_iterator<sizeof...(OptSpecifiers)>;
222     return make_range(Iterator(B, E, {toOptSpecifier(Ids)...}),
223                       Iterator(E, E, {toOptSpecifier(Ids)...}));
224   }
225 
226   /// @}
227   /// @name Arg Removal
228   /// @{
229 
230   /// eraseArg - Remove any option matching \p Id.
231   LLVM_ABI void eraseArg(OptSpecifier Id);
232 
233   /// @}
234   /// @name Arg Access
235   /// @{
236 
237   /// hasArg - Does the arg list contain any option matching \p Id.
238   ///
239   /// \p Claim Whether the argument should be claimed, if it exists.
240   template<typename ...OptSpecifiers>
hasArgNoClaim(OptSpecifiers...Ids)241   bool hasArgNoClaim(OptSpecifiers ...Ids) const {
242     return getLastArgNoClaim(Ids...) != nullptr;
243   }
244   template<typename ...OptSpecifiers>
hasArg(OptSpecifiers...Ids)245   bool hasArg(OptSpecifiers ...Ids) const {
246     return getLastArg(Ids...) != nullptr;
247   }
248 
249   /// Return true if the arg list contains multiple arguments matching \p Id.
hasMultipleArgs(OptSpecifier Id)250   bool hasMultipleArgs(OptSpecifier Id) const {
251     auto Args = filtered(Id);
252     return (Args.begin() != Args.end()) && (++Args.begin()) != Args.end();
253   }
254 
255   /// Return the last argument matching \p Id, or null.
256   template<typename ...OptSpecifiers>
getLastArg(OptSpecifiers...Ids)257   Arg *getLastArg(OptSpecifiers ...Ids) const {
258     Arg *Res = nullptr;
259     for (Arg *A : filtered(Ids...)) {
260       Res = A;
261       Res->claim();
262     }
263     return Res;
264   }
265 
266   /// Return the last argument matching \p Id, or null. Do not "claim" the
267   /// option (don't mark it as having been used).
268   template<typename ...OptSpecifiers>
getLastArgNoClaim(OptSpecifiers...Ids)269   Arg *getLastArgNoClaim(OptSpecifiers ...Ids) const {
270     for (Arg *A : filtered_reverse(Ids...))
271       return A;
272     return nullptr;
273   }
274 
275   /// getArgString - Return the input argument string at \p Index.
276   virtual const char *getArgString(unsigned Index) const = 0;
277 
278   /// getNumInputArgStrings - Return the number of original argument strings,
279   /// which are guaranteed to be the first strings in the argument string
280   /// list.
281   virtual unsigned getNumInputArgStrings() const = 0;
282 
283   /// @}
284   /// @name Argument Lookup Utilities
285   /// @{
286 
287   /// getLastArgValue - Return the value of the last argument, or a default.
288   LLVM_ABI StringRef getLastArgValue(OptSpecifier Id,
289                                      StringRef Default = "") const;
290 
291   /// getAllArgValues - Get the values of all instances of the given argument
292   /// as strings.
293   LLVM_ABI std::vector<std::string> getAllArgValues(OptSpecifier Id) const;
294 
295   /// @}
296   /// @name Translation Utilities
297   /// @{
298 
299   /// hasFlag - Given an option \p Pos and its negative form \p Neg, return
300   /// true if the option is present, false if the negation is present, and
301   /// \p Default if neither option is given. If both the option and its
302   /// negation are present, the last one wins.
303   LLVM_ABI bool hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const;
304   LLVM_ABI bool hasFlagNoClaim(OptSpecifier Pos, OptSpecifier Neg,
305                                bool Default) const;
306 
307   /// hasFlag - Given an option \p Pos, an alias \p PosAlias and its negative
308   /// form \p Neg, return true if the option or its alias is present, false if
309   /// the negation is present, and \p Default if none of the options are
310   /// given. If multiple options are present, the last one wins.
311   LLVM_ABI bool hasFlag(OptSpecifier Pos, OptSpecifier PosAlias,
312                         OptSpecifier Neg, bool Default) const;
313 
314   /// Given an option Pos and its negative form Neg, render the option if Pos is
315   /// present.
316   LLVM_ABI void addOptInFlag(ArgStringList &Output, OptSpecifier Pos,
317                              OptSpecifier Neg) const;
318   /// Render the option if Neg is present.
addOptOutFlag(ArgStringList & Output,OptSpecifier Pos,OptSpecifier Neg)319   void addOptOutFlag(ArgStringList &Output, OptSpecifier Pos,
320                      OptSpecifier Neg) const {
321     addOptInFlag(Output, Neg, Pos);
322   }
323 
324   /// Render only the last argument match \p Id0, if present.
325   template <typename... OptSpecifiers>
addLastArg(ArgStringList & Output,OptSpecifiers...Ids)326   void addLastArg(ArgStringList &Output, OptSpecifiers... Ids) const {
327     if (Arg *A = getLastArg(Ids...)) // Calls claim() on all Ids's Args.
328       A->render(*this, Output);
329   }
330   template <typename... OptSpecifiers>
AddLastArg(ArgStringList & Output,OptSpecifiers...Ids)331   void AddLastArg(ArgStringList &Output, OptSpecifiers... Ids) const {
332     addLastArg(Output, Ids...);
333   }
334 
335   /// AddAllArgsExcept - Render all arguments matching any of the given ids
336   /// and not matching any of the excluded ids.
337   LLVM_ABI void AddAllArgsExcept(ArgStringList &Output,
338                                  ArrayRef<OptSpecifier> Ids,
339                                  ArrayRef<OptSpecifier> ExcludeIds) const;
340   /// Render all arguments matching any of the given ids.
341   LLVM_ABI void addAllArgs(ArgStringList &Output,
342                            ArrayRef<OptSpecifier> Ids) const;
343 
344   /// AddAllArgs - Render all arguments matching the given ids.
345   LLVM_ABI void AddAllArgs(ArgStringList &Output, OptSpecifier Id0) const;
346 
347   /// AddAllArgValues - Render the argument values of all arguments
348   /// matching the given ids.
349   LLVM_ABI void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
350                                 OptSpecifier Id1 = 0U,
351                                 OptSpecifier Id2 = 0U) const;
352 
353   /// AddAllArgsTranslated - Render all the arguments matching the
354   /// given ids, but forced to separate args and using the provided
355   /// name instead of the first option value.
356   ///
357   /// \param Joined - If true, render the argument as joined with
358   /// the option specifier.
359   LLVM_ABI void AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
360                                      const char *Translation,
361                                      bool Joined = false) const;
362 
363   /// ClaimAllArgs - Claim all arguments which match the given
364   /// option id.
365   LLVM_ABI void ClaimAllArgs(OptSpecifier Id0) const;
366 
367   template <typename... OptSpecifiers>
claimAllArgs(OptSpecifiers...Ids)368   void claimAllArgs(OptSpecifiers... Ids) const {
369     for (Arg *A : filtered(Ids...))
370       A->claim();
371   }
372 
373   /// ClaimAllArgs - Claim all arguments.
374   ///
375   LLVM_ABI void ClaimAllArgs() const;
376   /// @}
377   /// @name Arg Synthesis
378   /// @{
379 
380   /// Construct a constant string pointer whose
381   /// lifetime will match that of the ArgList.
382   virtual const char *MakeArgStringRef(StringRef Str) const = 0;
MakeArgString(const Twine & Str)383   const char *MakeArgString(const Twine &Str) const {
384     SmallString<256> Buf;
385     return MakeArgStringRef(Str.toStringRef(Buf));
386   }
387 
388   /// Create an arg string for (\p LHS + \p RHS), reusing the
389   /// string at \p Index if possible.
390   LLVM_ABI const char *GetOrMakeJoinedArgString(unsigned Index, StringRef LHS,
391                                                 StringRef RHS) const;
392 
393   LLVM_ABI void print(raw_ostream &O) const;
394   LLVM_ABI void dump() const;
395 
396   /// @}
397 };
398 
399 class LLVM_ABI InputArgList final : public ArgList {
400 private:
401   /// List of argument strings used by the contained Args.
402   ///
403   /// This is mutable since we treat the ArgList as being the list
404   /// of Args, and allow routines to add new strings (to have a
405   /// convenient place to store the memory) via MakeIndex.
406   mutable ArgStringList ArgStrings;
407 
408   /// Strings for synthesized arguments.
409   ///
410   /// This is mutable since we treat the ArgList as being the list
411   /// of Args, and allow routines to add new strings (to have a
412   /// convenient place to store the memory) via MakeIndex.
413   mutable std::list<std::string> SynthesizedStrings;
414 
415   /// The number of original input argument strings.
416   unsigned NumInputArgStrings;
417 
418   /// Release allocated arguments.
419   void releaseMemory();
420 
421 public:
InputArgList()422   InputArgList() : NumInputArgStrings(0) {}
423 
424   InputArgList(const char* const *ArgBegin, const char* const *ArgEnd);
425 
InputArgList(InputArgList && RHS)426   InputArgList(InputArgList &&RHS)
427       : ArgList(std::move(RHS)), ArgStrings(std::move(RHS.ArgStrings)),
428         SynthesizedStrings(std::move(RHS.SynthesizedStrings)),
429         NumInputArgStrings(RHS.NumInputArgStrings) {}
430 
431   InputArgList &operator=(InputArgList &&RHS) {
432     if (this == &RHS)
433       return *this;
434     releaseMemory();
435     ArgList::operator=(std::move(RHS));
436     ArgStrings = std::move(RHS.ArgStrings);
437     SynthesizedStrings = std::move(RHS.SynthesizedStrings);
438     NumInputArgStrings = RHS.NumInputArgStrings;
439     return *this;
440   }
441 
~InputArgList()442   ~InputArgList() { releaseMemory(); }
443 
getArgString(unsigned Index)444   const char *getArgString(unsigned Index) const override {
445     return ArgStrings[Index];
446   }
447 
replaceArgString(unsigned Index,const Twine & S)448   void replaceArgString(unsigned Index, const Twine &S) {
449     ArgStrings[Index] = MakeArgString(S);
450   }
451 
getNumInputArgStrings()452   unsigned getNumInputArgStrings() const override {
453     return NumInputArgStrings;
454   }
455 
456   /// @name Arg Synthesis
457   /// @{
458 
459 public:
460   /// MakeIndex - Get an index for the given string(s).
461   unsigned MakeIndex(StringRef String0) const;
462   unsigned MakeIndex(StringRef String0, StringRef String1) const;
463 
464   using ArgList::MakeArgString;
465   const char *MakeArgStringRef(StringRef Str) const override;
466 
467   /// @}
468 };
469 
470 /// DerivedArgList - An ordered collection of driver arguments,
471 /// whose storage may be in another argument list.
472 class LLVM_ABI DerivedArgList final : public ArgList {
473   const InputArgList &BaseArgs;
474 
475   /// The list of arguments we synthesized.
476   mutable SmallVector<std::unique_ptr<Arg>, 16> SynthesizedArgs;
477 
478 public:
479   /// Construct a new derived arg list from \p BaseArgs.
480   DerivedArgList(const InputArgList &BaseArgs);
481 
getArgString(unsigned Index)482   const char *getArgString(unsigned Index) const override {
483     return BaseArgs.getArgString(Index);
484   }
485 
getNumInputArgStrings()486   unsigned getNumInputArgStrings() const override {
487     return BaseArgs.getNumInputArgStrings();
488   }
489 
getBaseArgs()490   const InputArgList &getBaseArgs() const {
491     return BaseArgs;
492   }
493 
494   /// @name Arg Synthesis
495   /// @{
496 
497   /// AddSynthesizedArg - Add a argument to the list of synthesized arguments
498   /// (to be freed).
499   void AddSynthesizedArg(Arg *A);
500 
501   using ArgList::MakeArgString;
502   const char *MakeArgStringRef(StringRef Str) const override;
503 
504   /// AddFlagArg - Construct a new FlagArg for the given option \p Id and
505   /// append it to the argument list.
AddFlagArg(const Arg * BaseArg,const Option Opt)506   void AddFlagArg(const Arg *BaseArg, const Option Opt) {
507     append(MakeFlagArg(BaseArg, Opt));
508   }
509 
510   /// AddPositionalArg - Construct a new Positional arg for the given option
511   /// \p Id, with the provided \p Value and append it to the argument
512   /// list.
AddPositionalArg(const Arg * BaseArg,const Option Opt,StringRef Value)513   void AddPositionalArg(const Arg *BaseArg, const Option Opt,
514                         StringRef Value) {
515     append(MakePositionalArg(BaseArg, Opt, Value));
516   }
517 
518   /// AddSeparateArg - Construct a new Positional arg for the given option
519   /// \p Id, with the provided \p Value and append it to the argument
520   /// list.
AddSeparateArg(const Arg * BaseArg,const Option Opt,StringRef Value)521   void AddSeparateArg(const Arg *BaseArg, const Option Opt,
522                       StringRef Value) {
523     append(MakeSeparateArg(BaseArg, Opt, Value));
524   }
525 
526   /// AddJoinedArg - Construct a new Positional arg for the given option
527   /// \p Id, with the provided \p Value and append it to the argument list.
AddJoinedArg(const Arg * BaseArg,const Option Opt,StringRef Value)528   void AddJoinedArg(const Arg *BaseArg, const Option Opt,
529                     StringRef Value) {
530     append(MakeJoinedArg(BaseArg, Opt, Value));
531   }
532 
533   /// MakeFlagArg - Construct a new FlagArg for the given option \p Id.
534   Arg *MakeFlagArg(const Arg *BaseArg, const Option Opt) const;
535 
536   /// MakePositionalArg - Construct a new Positional arg for the
537   /// given option \p Id, with the provided \p Value.
538   Arg *MakePositionalArg(const Arg *BaseArg, const Option Opt,
539                           StringRef Value) const;
540 
541   /// MakeSeparateArg - Construct a new Positional arg for the
542   /// given option \p Id, with the provided \p Value.
543   Arg *MakeSeparateArg(const Arg *BaseArg, const Option Opt,
544                         StringRef Value) const;
545 
546   /// MakeJoinedArg - Construct a new Positional arg for the
547   /// given option \p Id, with the provided \p Value.
548   Arg *MakeJoinedArg(const Arg *BaseArg, const Option Opt,
549                       StringRef Value) const;
550 
551   /// @}
552 };
553 
554 } // end namespace opt
555 
556 } // end namespace llvm
557 
558 #endif // LLVM_OPTION_ARGLIST_H
559