• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===- ArgList.h - Argument List Management ---------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_OPTION_ARGLIST_H
11 #define LLVM_OPTION_ARGLIST_H
12 
13 #include "llvm/ADT/ArrayRef.h"
14 #include "llvm/ADT/DenseMap.h"
15 #include "llvm/ADT/iterator_range.h"
16 #include "llvm/ADT/SmallString.h"
17 #include "llvm/ADT/SmallVector.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ADT/Twine.h"
20 #include "llvm/Option/Arg.h"
21 #include "llvm/Option/OptSpecifier.h"
22 #include "llvm/Option/Option.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   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   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   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 the last argument matching \p Id, or null.
250   template<typename ...OptSpecifiers>
getLastArg(OptSpecifiers...Ids)251   Arg *getLastArg(OptSpecifiers ...Ids) const {
252     Arg *Res = nullptr;
253     for (Arg *A : filtered(Ids...)) {
254       Res = A;
255       Res->claim();
256     }
257     return Res;
258   }
259 
260   /// Return the last argument matching \p Id, or null. Do not "claim" the
261   /// option (don't mark it as having been used).
262   template<typename ...OptSpecifiers>
getLastArgNoClaim(OptSpecifiers...Ids)263   Arg *getLastArgNoClaim(OptSpecifiers ...Ids) const {
264     for (Arg *A : filtered_reverse(Ids...))
265       return A;
266     return nullptr;
267   }
268 
269   /// getArgString - Return the input argument string at \p Index.
270   virtual const char *getArgString(unsigned Index) const = 0;
271 
272   /// getNumInputArgStrings - Return the number of original argument strings,
273   /// which are guaranteed to be the first strings in the argument string
274   /// list.
275   virtual unsigned getNumInputArgStrings() const = 0;
276 
277   /// @}
278   /// @name Argument Lookup Utilities
279   /// @{
280 
281   /// getLastArgValue - Return the value of the last argument, or a default.
282   StringRef getLastArgValue(OptSpecifier Id, StringRef Default = "") const;
283 
284   /// getAllArgValues - Get the values of all instances of the given argument
285   /// as strings.
286   std::vector<std::string> getAllArgValues(OptSpecifier Id) const;
287 
288   /// @}
289   /// @name Translation Utilities
290   /// @{
291 
292   /// hasFlag - Given an option \p Pos and its negative form \p Neg, return
293   /// true if the option is present, false if the negation is present, and
294   /// \p Default if neither option is given. If both the option and its
295   /// negation are present, the last one wins.
296   bool hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default=true) const;
297 
298   /// hasFlag - Given an option \p Pos, an alias \p PosAlias and its negative
299   /// form \p Neg, return true if the option or its alias is present, false if
300   /// the negation is present, and \p Default if none of the options are
301   /// given. If multiple options are present, the last one wins.
302   bool hasFlag(OptSpecifier Pos, OptSpecifier PosAlias, OptSpecifier Neg,
303                bool Default = true) const;
304 
305   /// AddLastArg - Render only the last argument match \p Id0, if present.
306   void AddLastArg(ArgStringList &Output, OptSpecifier Id0) const;
307   void AddLastArg(ArgStringList &Output, OptSpecifier Id0,
308                   OptSpecifier Id1) const;
309 
310   /// AddAllArgsExcept - Render all arguments matching any of the given ids
311   /// and not matching any of the excluded ids.
312   void AddAllArgsExcept(ArgStringList &Output, ArrayRef<OptSpecifier> Ids,
313                         ArrayRef<OptSpecifier> ExcludeIds) const;
314   /// AddAllArgs - Render all arguments matching any of the given ids.
315   void AddAllArgs(ArgStringList &Output, ArrayRef<OptSpecifier> Ids) const;
316 
317   /// AddAllArgs - Render all arguments matching the given ids.
318   void AddAllArgs(ArgStringList &Output, OptSpecifier Id0,
319                   OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;
320 
321   /// AddAllArgValues - Render the argument values of all arguments
322   /// matching the given ids.
323   void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0,
324                        OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const;
325 
326   /// AddAllArgsTranslated - Render all the arguments matching the
327   /// given ids, but forced to separate args and using the provided
328   /// name instead of the first option value.
329   ///
330   /// \param Joined - If true, render the argument as joined with
331   /// the option specifier.
332   void AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0,
333                             const char *Translation,
334                             bool Joined = false) const;
335 
336   /// ClaimAllArgs - Claim all arguments which match the given
337   /// option id.
338   void ClaimAllArgs(OptSpecifier Id0) const;
339 
340   /// ClaimAllArgs - Claim all arguments.
341   ///
342   void ClaimAllArgs() const;
343 
344   /// @}
345   /// @name Arg Synthesis
346   /// @{
347 
348   /// Construct a constant string pointer whose
349   /// lifetime will match that of the ArgList.
350   virtual const char *MakeArgStringRef(StringRef Str) const = 0;
MakeArgString(const Twine & Str)351   const char *MakeArgString(const Twine &Str) const {
352     SmallString<256> Buf;
353     return MakeArgStringRef(Str.toStringRef(Buf));
354   }
355 
356   /// Create an arg string for (\p LHS + \p RHS), reusing the
357   /// string at \p Index if possible.
358   const char *GetOrMakeJoinedArgString(unsigned Index, StringRef LHS,
359                                         StringRef RHS) const;
360 
361   void print(raw_ostream &O) const;
362   void dump() const;
363 
364   /// @}
365 };
366 
367 class InputArgList final : public ArgList {
368 private:
369   /// List of argument strings used by the contained Args.
370   ///
371   /// This is mutable since we treat the ArgList as being the list
372   /// of Args, and allow routines to add new strings (to have a
373   /// convenient place to store the memory) via MakeIndex.
374   mutable ArgStringList ArgStrings;
375 
376   /// Strings for synthesized arguments.
377   ///
378   /// This is mutable since we treat the ArgList as being the list
379   /// of Args, and allow routines to add new strings (to have a
380   /// convenient place to store the memory) via MakeIndex.
381   mutable std::list<std::string> SynthesizedStrings;
382 
383   /// The number of original input argument strings.
384   unsigned NumInputArgStrings;
385 
386   /// Release allocated arguments.
387   void releaseMemory();
388 
389 public:
InputArgList()390   InputArgList() : NumInputArgStrings(0) {}
391 
392   InputArgList(const char* const *ArgBegin, const char* const *ArgEnd);
393 
InputArgList(InputArgList && RHS)394   InputArgList(InputArgList &&RHS)
395       : ArgList(std::move(RHS)), ArgStrings(std::move(RHS.ArgStrings)),
396         SynthesizedStrings(std::move(RHS.SynthesizedStrings)),
397         NumInputArgStrings(RHS.NumInputArgStrings) {}
398 
399   InputArgList &operator=(InputArgList &&RHS) {
400     releaseMemory();
401     ArgList::operator=(std::move(RHS));
402     ArgStrings = std::move(RHS.ArgStrings);
403     SynthesizedStrings = std::move(RHS.SynthesizedStrings);
404     NumInputArgStrings = RHS.NumInputArgStrings;
405     return *this;
406   }
407 
~InputArgList()408   ~InputArgList() { releaseMemory(); }
409 
getArgString(unsigned Index)410   const char *getArgString(unsigned Index) const override {
411     return ArgStrings[Index];
412   }
413 
getNumInputArgStrings()414   unsigned getNumInputArgStrings() const override {
415     return NumInputArgStrings;
416   }
417 
418   /// @name Arg Synthesis
419   /// @{
420 
421 public:
422   /// MakeIndex - Get an index for the given string(s).
423   unsigned MakeIndex(StringRef String0) const;
424   unsigned MakeIndex(StringRef String0, StringRef String1) const;
425 
426   using ArgList::MakeArgString;
427   const char *MakeArgStringRef(StringRef Str) const override;
428 
429   /// @}
430 };
431 
432 /// DerivedArgList - An ordered collection of driver arguments,
433 /// whose storage may be in another argument list.
434 class DerivedArgList final : public ArgList {
435   const InputArgList &BaseArgs;
436 
437   /// The list of arguments we synthesized.
438   mutable SmallVector<std::unique_ptr<Arg>, 16> SynthesizedArgs;
439 
440 public:
441   /// Construct a new derived arg list from \p BaseArgs.
442   DerivedArgList(const InputArgList &BaseArgs);
443 
getArgString(unsigned Index)444   const char *getArgString(unsigned Index) const override {
445     return BaseArgs.getArgString(Index);
446   }
447 
getNumInputArgStrings()448   unsigned getNumInputArgStrings() const override {
449     return BaseArgs.getNumInputArgStrings();
450   }
451 
getBaseArgs()452   const InputArgList &getBaseArgs() const {
453     return BaseArgs;
454   }
455 
456   /// @name Arg Synthesis
457   /// @{
458 
459   /// AddSynthesizedArg - Add a argument to the list of synthesized arguments
460   /// (to be freed).
461   void AddSynthesizedArg(Arg *A);
462 
463   using ArgList::MakeArgString;
464   const char *MakeArgStringRef(StringRef Str) const override;
465 
466   /// AddFlagArg - Construct a new FlagArg for the given option \p Id and
467   /// append it to the argument list.
AddFlagArg(const Arg * BaseArg,const Option Opt)468   void AddFlagArg(const Arg *BaseArg, const Option Opt) {
469     append(MakeFlagArg(BaseArg, Opt));
470   }
471 
472   /// AddPositionalArg - Construct a new Positional arg for the given option
473   /// \p Id, with the provided \p Value and append it to the argument
474   /// list.
AddPositionalArg(const Arg * BaseArg,const Option Opt,StringRef Value)475   void AddPositionalArg(const Arg *BaseArg, const Option Opt,
476                         StringRef Value) {
477     append(MakePositionalArg(BaseArg, Opt, Value));
478   }
479 
480   /// AddSeparateArg - Construct a new Positional arg for the given option
481   /// \p Id, with the provided \p Value and append it to the argument
482   /// list.
AddSeparateArg(const Arg * BaseArg,const Option Opt,StringRef Value)483   void AddSeparateArg(const Arg *BaseArg, const Option Opt,
484                       StringRef Value) {
485     append(MakeSeparateArg(BaseArg, Opt, Value));
486   }
487 
488   /// AddJoinedArg - Construct a new Positional arg for the given option
489   /// \p Id, with the provided \p Value and append it to the argument list.
AddJoinedArg(const Arg * BaseArg,const Option Opt,StringRef Value)490   void AddJoinedArg(const Arg *BaseArg, const Option Opt,
491                     StringRef Value) {
492     append(MakeJoinedArg(BaseArg, Opt, Value));
493   }
494 
495   /// MakeFlagArg - Construct a new FlagArg for the given option \p Id.
496   Arg *MakeFlagArg(const Arg *BaseArg, const Option Opt) const;
497 
498   /// MakePositionalArg - Construct a new Positional arg for the
499   /// given option \p Id, with the provided \p Value.
500   Arg *MakePositionalArg(const Arg *BaseArg, const Option Opt,
501                           StringRef Value) const;
502 
503   /// MakeSeparateArg - Construct a new Positional arg for the
504   /// given option \p Id, with the provided \p Value.
505   Arg *MakeSeparateArg(const Arg *BaseArg, const Option Opt,
506                         StringRef Value) const;
507 
508   /// MakeJoinedArg - Construct a new Positional arg for the
509   /// given option \p Id, with the provided \p Value.
510   Arg *MakeJoinedArg(const Arg *BaseArg, const Option Opt,
511                       StringRef Value) const;
512 
513   /// @}
514 };
515 
516 } // end namespace opt
517 
518 } // end namespace llvm
519 
520 #endif // LLVM_OPTION_ARGLIST_H
521