- //===- ArgList.h - Argument List Management ---------------------*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_OPTION_ARGLIST_H 
- #define LLVM_OPTION_ARGLIST_H 
-   
- #include "llvm/ADT/ArrayRef.h" 
- #include "llvm/ADT/DenseMap.h" 
- #include "llvm/ADT/iterator_range.h" 
- #include "llvm/ADT/SmallString.h" 
- #include "llvm/ADT/SmallVector.h" 
- #include "llvm/ADT/StringRef.h" 
- #include "llvm/ADT/Twine.h" 
- #include "llvm/Option/Arg.h" 
- #include "llvm/Option/OptSpecifier.h" 
- #include "llvm/Option/Option.h" 
- #include <algorithm> 
- #include <cstddef> 
- #include <initializer_list> 
- #include <iterator> 
- #include <list> 
- #include <memory> 
- #include <string> 
- #include <utility> 
- #include <vector> 
-   
- namespace llvm { 
-   
- class raw_ostream; 
-   
- namespace opt { 
-   
- /// arg_iterator - Iterates through arguments stored inside an ArgList. 
- template<typename BaseIter, unsigned NumOptSpecifiers = 0> 
- class arg_iterator { 
-   /// The current argument and the end of the sequence we're iterating. 
-   BaseIter Current, End; 
-   
-   /// Optional filters on the arguments which will be match. To avoid a 
-   /// zero-sized array, we store one specifier even if we're asked for none. 
-   OptSpecifier Ids[NumOptSpecifiers ? NumOptSpecifiers : 1]; 
-   
-   void SkipToNextArg() { 
-     for (; Current != End; ++Current) { 
-       // Skip erased elements. 
-       if (!*Current) 
-         continue; 
-   
-       // Done if there are no filters. 
-       if (!NumOptSpecifiers) 
-         return; 
-   
-       // Otherwise require a match. 
-       const Option &O = (*Current)->getOption(); 
-       for (auto Id : Ids) { 
-         if (!Id.isValid()) 
-           break; 
-         if (O.matches(Id)) 
-           return; 
-       } 
-     } 
-   } 
-   
-   using Traits = std::iterator_traits<BaseIter>; 
-   
- public: 
-   using value_type = typename Traits::value_type; 
-   using reference = typename Traits::reference; 
-   using pointer = typename Traits::pointer; 
-   using iterator_category = std::forward_iterator_tag; 
-   using difference_type = std::ptrdiff_t; 
-   
-   arg_iterator( 
-       BaseIter Current, BaseIter End, 
-       const OptSpecifier (&Ids)[NumOptSpecifiers ? NumOptSpecifiers : 1] = {}) 
-       : Current(Current), End(End) { 
-     for (unsigned I = 0; I != NumOptSpecifiers; ++I) 
-       this->Ids[I] = Ids[I]; 
-     SkipToNextArg(); 
-   } 
-   
-   reference operator*() const { return *Current; } 
-   pointer operator->() const { return Current; } 
-   
-   arg_iterator &operator++() { 
-     ++Current; 
-     SkipToNextArg(); 
-     return *this; 
-   } 
-   
-   arg_iterator operator++(int) { 
-     arg_iterator tmp(*this); 
-     ++(*this); 
-     return tmp; 
-   } 
-   
-   friend bool operator==(arg_iterator LHS, arg_iterator RHS) { 
-     return LHS.Current == RHS.Current; 
-   } 
-   friend bool operator!=(arg_iterator LHS, arg_iterator RHS) { 
-     return !(LHS == RHS); 
-   } 
- }; 
-   
- /// ArgList - Ordered collection of driver arguments. 
- /// 
- /// The ArgList class manages a list of Arg instances as well as 
- /// auxiliary data and convenience methods to allow Tools to quickly 
- /// check for the presence of Arg instances for a particular Option 
- /// and to iterate over groups of arguments. 
- class ArgList { 
- public: 
-   using arglist_type = SmallVector<Arg *, 16>; 
-   using iterator = arg_iterator<arglist_type::iterator>; 
-   using const_iterator = arg_iterator<arglist_type::const_iterator>; 
-   using reverse_iterator = arg_iterator<arglist_type::reverse_iterator>; 
-   using const_reverse_iterator = 
-       arg_iterator<arglist_type::const_reverse_iterator>; 
-   
-   template<unsigned N> using filtered_iterator = 
-       arg_iterator<arglist_type::const_iterator, N>; 
-   template<unsigned N> using filtered_reverse_iterator = 
-       arg_iterator<arglist_type::const_reverse_iterator, N>; 
-   
- private: 
-   /// The internal list of arguments. 
-   arglist_type Args; 
-   
-   using OptRange = std::pair<unsigned, unsigned>; 
-   static OptRange emptyRange() { return {-1u, 0u}; } 
-   
-   /// The first and last index of each different OptSpecifier ID. 
-   DenseMap<unsigned, OptRange> OptRanges; 
-   
-   /// Get the range of indexes in which options with the specified IDs might 
-   /// reside, or (0, 0) if there are no such options. 
-   OptRange getRange(std::initializer_list<OptSpecifier> Ids) const; 
-   
- protected: 
-   // Make the default special members protected so they won't be used to slice 
-   // derived objects, but can still be used by derived objects to implement 
-   // their own special members. 
-   ArgList() = default; 
-   
-   // Explicit move operations to ensure the container is cleared post-move 
-   // otherwise it could lead to a double-delete in the case of moving of an 
-   // InputArgList which deletes the contents of the container. If we could fix 
-   // up the ownership here (delegate storage/ownership to the derived class so 
-   // it can be a container of unique_ptr) this would be simpler. 
-   ArgList(ArgList &&RHS) 
-       : Args(std::move(RHS.Args)), OptRanges(std::move(RHS.OptRanges)) { 
-     RHS.Args.clear(); 
-     RHS.OptRanges.clear(); 
-   } 
-   
-   ArgList &operator=(ArgList &&RHS) { 
-     Args = std::move(RHS.Args); 
-     RHS.Args.clear(); 
-     OptRanges = std::move(RHS.OptRanges); 
-     RHS.OptRanges.clear(); 
-     return *this; 
-   } 
-   
-   // Protect the dtor to ensure this type is never destroyed polymorphically. 
-   ~ArgList() = default; 
-   
-   // Implicitly convert a value to an OptSpecifier. Used to work around a bug 
-   // in MSVC's implementation of narrowing conversion checking. 
-   static OptSpecifier toOptSpecifier(OptSpecifier S) { return S; } 
-   
- public: 
-   /// @name Arg Access 
-   /// @{ 
-   
-   /// append - Append \p A to the arg list. 
-   void append(Arg *A); 
-   
-   const arglist_type &getArgs() const { return Args; } 
-   
-   unsigned size() const { return Args.size(); } 
-   
-   /// @} 
-   /// @name Arg Iteration 
-   /// @{ 
-   
-   iterator begin() { return {Args.begin(), Args.end()}; } 
-   iterator end() { return {Args.end(), Args.end()}; } 
-   
-   reverse_iterator rbegin() { return {Args.rbegin(), Args.rend()}; } 
-   reverse_iterator rend() { return {Args.rend(), Args.rend()}; } 
-   
-   const_iterator begin() const { return {Args.begin(), Args.end()}; } 
-   const_iterator end() const { return {Args.end(), Args.end()}; } 
-   
-   const_reverse_iterator rbegin() const { return {Args.rbegin(), Args.rend()}; } 
-   const_reverse_iterator rend() const { return {Args.rend(), Args.rend()}; } 
-   
-   template<typename ...OptSpecifiers> 
-   iterator_range<filtered_iterator<sizeof...(OptSpecifiers)>> 
-   filtered(OptSpecifiers ...Ids) const { 
-     OptRange Range = getRange({toOptSpecifier(Ids)...}); 
-     auto B = Args.begin() + Range.first; 
-     auto E = Args.begin() + Range.second; 
-     using Iterator = filtered_iterator<sizeof...(OptSpecifiers)>; 
-     return make_range(Iterator(B, E, {toOptSpecifier(Ids)...}), 
-                       Iterator(E, E, {toOptSpecifier(Ids)...})); 
-   } 
-   
-   template<typename ...OptSpecifiers> 
-   iterator_range<filtered_reverse_iterator<sizeof...(OptSpecifiers)>> 
-   filtered_reverse(OptSpecifiers ...Ids) const { 
-     OptRange Range = getRange({toOptSpecifier(Ids)...}); 
-     auto B = Args.rend() - Range.second; 
-     auto E = Args.rend() - Range.first; 
-     using Iterator = filtered_reverse_iterator<sizeof...(OptSpecifiers)>; 
-     return make_range(Iterator(B, E, {toOptSpecifier(Ids)...}), 
-                       Iterator(E, E, {toOptSpecifier(Ids)...})); 
-   } 
-   
-   /// @} 
-   /// @name Arg Removal 
-   /// @{ 
-   
-   /// eraseArg - Remove any option matching \p Id. 
-   void eraseArg(OptSpecifier Id); 
-   
-   /// @} 
-   /// @name Arg Access 
-   /// @{ 
-   
-   /// hasArg - Does the arg list contain any option matching \p Id. 
-   /// 
-   /// \p Claim Whether the argument should be claimed, if it exists. 
-   template<typename ...OptSpecifiers> 
-   bool hasArgNoClaim(OptSpecifiers ...Ids) const { 
-     return getLastArgNoClaim(Ids...) != nullptr; 
-   } 
-   template<typename ...OptSpecifiers> 
-   bool hasArg(OptSpecifiers ...Ids) const { 
-     return getLastArg(Ids...) != nullptr; 
-   } 
-   
-   /// Return true if the arg list contains multiple arguments matching \p Id. 
-   bool hasMultipleArgs(OptSpecifier Id) const { 
-     auto Args = filtered(Id); 
-     return (Args.begin() != Args.end()) && (++Args.begin()) != Args.end(); 
-   } 
-   
-   /// Return the last argument matching \p Id, or null. 
-   template<typename ...OptSpecifiers> 
-   Arg *getLastArg(OptSpecifiers ...Ids) const { 
-     Arg *Res = nullptr; 
-     for (Arg *A : filtered(Ids...)) { 
-       Res = A; 
-       Res->claim(); 
-     } 
-     return Res; 
-   } 
-   
-   /// Return the last argument matching \p Id, or null. Do not "claim" the 
-   /// option (don't mark it as having been used). 
-   template<typename ...OptSpecifiers> 
-   Arg *getLastArgNoClaim(OptSpecifiers ...Ids) const { 
-     for (Arg *A : filtered_reverse(Ids...)) 
-       return A; 
-     return nullptr; 
-   } 
-   
-   /// getArgString - Return the input argument string at \p Index. 
-   virtual const char *getArgString(unsigned Index) const = 0; 
-   
-   /// getNumInputArgStrings - Return the number of original argument strings, 
-   /// which are guaranteed to be the first strings in the argument string 
-   /// list. 
-   virtual unsigned getNumInputArgStrings() const = 0; 
-   
-   /// @} 
-   /// @name Argument Lookup Utilities 
-   /// @{ 
-   
-   /// getLastArgValue - Return the value of the last argument, or a default. 
-   StringRef getLastArgValue(OptSpecifier Id, StringRef Default = "") const; 
-   
-   /// getAllArgValues - Get the values of all instances of the given argument 
-   /// as strings. 
-   std::vector<std::string> getAllArgValues(OptSpecifier Id) const; 
-   
-   /// @} 
-   /// @name Translation Utilities 
-   /// @{ 
-   
-   /// hasFlag - Given an option \p Pos and its negative form \p Neg, return 
-   /// true if the option is present, false if the negation is present, and 
-   /// \p Default if neither option is given. If both the option and its 
-   /// negation are present, the last one wins. 
-   bool hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const; 
-   
-   /// hasFlag - Given an option \p Pos, an alias \p PosAlias and its negative 
-   /// form \p Neg, return true if the option or its alias is present, false if 
-   /// the negation is present, and \p Default if none of the options are 
-   /// given. If multiple options are present, the last one wins. 
-   bool hasFlag(OptSpecifier Pos, OptSpecifier PosAlias, OptSpecifier Neg, 
-                bool Default) const; 
-   
-   /// Given an option Pos and its negative form Neg, render the option if Pos is 
-   /// present. 
-   void addOptInFlag(ArgStringList &Output, OptSpecifier Pos, 
-                     OptSpecifier Neg) const; 
-   /// Render the option if Neg is present. 
-   void addOptOutFlag(ArgStringList &Output, OptSpecifier Pos, 
-                      OptSpecifier Neg) const { 
-     addOptInFlag(Output, Neg, Pos); 
-   } 
-   
-   /// Render only the last argument match \p Id0, if present. 
-   template<typename ...OptSpecifiers> 
-   void AddLastArg(ArgStringList &Output, OptSpecifiers ...Ids) const { 
-     if (Arg *A = getLastArg(Ids...)) // Calls claim() on all Ids's Args. 
-       A->render(*this, Output); 
-   } 
-   
-   /// AddAllArgsExcept - Render all arguments matching any of the given ids 
-   /// and not matching any of the excluded ids. 
-   void AddAllArgsExcept(ArgStringList &Output, ArrayRef<OptSpecifier> Ids, 
-                         ArrayRef<OptSpecifier> ExcludeIds) const; 
-   /// AddAllArgs - Render all arguments matching any of the given ids. 
-   void AddAllArgs(ArgStringList &Output, ArrayRef<OptSpecifier> Ids) const; 
-   
-   /// AddAllArgs - Render all arguments matching the given ids. 
-   void AddAllArgs(ArgStringList &Output, OptSpecifier Id0, 
-                   OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const; 
-   
-   /// AddAllArgValues - Render the argument values of all arguments 
-   /// matching the given ids. 
-   void AddAllArgValues(ArgStringList &Output, OptSpecifier Id0, 
-                        OptSpecifier Id1 = 0U, OptSpecifier Id2 = 0U) const; 
-   
-   /// AddAllArgsTranslated - Render all the arguments matching the 
-   /// given ids, but forced to separate args and using the provided 
-   /// name instead of the first option value. 
-   /// 
-   /// \param Joined - If true, render the argument as joined with 
-   /// the option specifier. 
-   void AddAllArgsTranslated(ArgStringList &Output, OptSpecifier Id0, 
-                             const char *Translation, 
-                             bool Joined = false) const; 
-   
-   /// ClaimAllArgs - Claim all arguments which match the given 
-   /// option id. 
-   void ClaimAllArgs(OptSpecifier Id0) const; 
-   
-   /// ClaimAllArgs - Claim all arguments. 
-   /// 
-   void ClaimAllArgs() const; 
-   /// @} 
-   /// @name Arg Synthesis 
-   /// @{ 
-   
-   /// Construct a constant string pointer whose 
-   /// lifetime will match that of the ArgList. 
-   virtual const char *MakeArgStringRef(StringRef Str) const = 0; 
-   const char *MakeArgString(const Twine &Str) const { 
-     SmallString<256> Buf; 
-     return MakeArgStringRef(Str.toStringRef(Buf)); 
-   } 
-   
-   /// Create an arg string for (\p LHS + \p RHS), reusing the 
-   /// string at \p Index if possible. 
-   const char *GetOrMakeJoinedArgString(unsigned Index, StringRef LHS, 
-                                         StringRef RHS) const; 
-   
-   void print(raw_ostream &O) const; 
-   void dump() const; 
-   
-   /// @} 
- }; 
-   
- class InputArgList final : public ArgList { 
- private: 
-   /// List of argument strings used by the contained Args. 
-   /// 
-   /// This is mutable since we treat the ArgList as being the list 
-   /// of Args, and allow routines to add new strings (to have a 
-   /// convenient place to store the memory) via MakeIndex. 
-   mutable ArgStringList ArgStrings; 
-   
-   /// Strings for synthesized arguments. 
-   /// 
-   /// This is mutable since we treat the ArgList as being the list 
-   /// of Args, and allow routines to add new strings (to have a 
-   /// convenient place to store the memory) via MakeIndex. 
-   mutable std::list<std::string> SynthesizedStrings; 
-   
-   /// The number of original input argument strings. 
-   unsigned NumInputArgStrings; 
-   
-   /// Release allocated arguments. 
-   void releaseMemory(); 
-   
- public: 
-   InputArgList() : NumInputArgStrings(0) {} 
-   
-   InputArgList(const char* const *ArgBegin, const char* const *ArgEnd); 
-   
-   InputArgList(InputArgList &&RHS) 
-       : ArgList(std::move(RHS)), ArgStrings(std::move(RHS.ArgStrings)), 
-         SynthesizedStrings(std::move(RHS.SynthesizedStrings)), 
-         NumInputArgStrings(RHS.NumInputArgStrings) {} 
-   
-   InputArgList &operator=(InputArgList &&RHS) { 
-     releaseMemory(); 
-     ArgList::operator=(std::move(RHS)); 
-     ArgStrings = std::move(RHS.ArgStrings); 
-     SynthesizedStrings = std::move(RHS.SynthesizedStrings); 
-     NumInputArgStrings = RHS.NumInputArgStrings; 
-     return *this; 
-   } 
-   
-   ~InputArgList() { releaseMemory(); } 
-   
-   const char *getArgString(unsigned Index) const override { 
-     return ArgStrings[Index]; 
-   } 
-   
-   void replaceArgString(unsigned Index, const Twine &S) { 
-     ArgStrings[Index] = MakeArgString(S); 
-   } 
-   
-   unsigned getNumInputArgStrings() const override { 
-     return NumInputArgStrings; 
-   } 
-   
-   /// @name Arg Synthesis 
-   /// @{ 
-   
- public: 
-   /// MakeIndex - Get an index for the given string(s). 
-   unsigned MakeIndex(StringRef String0) const; 
-   unsigned MakeIndex(StringRef String0, StringRef String1) const; 
-   
-   using ArgList::MakeArgString; 
-   const char *MakeArgStringRef(StringRef Str) const override; 
-   
-   /// @} 
- }; 
-   
- /// DerivedArgList - An ordered collection of driver arguments, 
- /// whose storage may be in another argument list. 
- class DerivedArgList final : public ArgList { 
-   const InputArgList &BaseArgs; 
-   
-   /// The list of arguments we synthesized. 
-   mutable SmallVector<std::unique_ptr<Arg>, 16> SynthesizedArgs; 
-   
- public: 
-   /// Construct a new derived arg list from \p BaseArgs. 
-   DerivedArgList(const InputArgList &BaseArgs); 
-   
-   const char *getArgString(unsigned Index) const override { 
-     return BaseArgs.getArgString(Index); 
-   } 
-   
-   unsigned getNumInputArgStrings() const override { 
-     return BaseArgs.getNumInputArgStrings(); 
-   } 
-   
-   const InputArgList &getBaseArgs() const { 
-     return BaseArgs; 
-   } 
-   
-   /// @name Arg Synthesis 
-   /// @{ 
-   
-   /// AddSynthesizedArg - Add a argument to the list of synthesized arguments 
-   /// (to be freed). 
-   void AddSynthesizedArg(Arg *A); 
-   
-   using ArgList::MakeArgString; 
-   const char *MakeArgStringRef(StringRef Str) const override; 
-   
-   /// AddFlagArg - Construct a new FlagArg for the given option \p Id and 
-   /// append it to the argument list. 
-   void AddFlagArg(const Arg *BaseArg, const Option Opt) { 
-     append(MakeFlagArg(BaseArg, Opt)); 
-   } 
-   
-   /// AddPositionalArg - Construct a new Positional arg for the given option 
-   /// \p Id, with the provided \p Value and append it to the argument 
-   /// list. 
-   void AddPositionalArg(const Arg *BaseArg, const Option Opt, 
-                         StringRef Value) { 
-     append(MakePositionalArg(BaseArg, Opt, Value)); 
-   } 
-   
-   /// AddSeparateArg - Construct a new Positional arg for the given option 
-   /// \p Id, with the provided \p Value and append it to the argument 
-   /// list. 
-   void AddSeparateArg(const Arg *BaseArg, const Option Opt, 
-                       StringRef Value) { 
-     append(MakeSeparateArg(BaseArg, Opt, Value)); 
-   } 
-   
-   /// AddJoinedArg - Construct a new Positional arg for the given option 
-   /// \p Id, with the provided \p Value and append it to the argument list. 
-   void AddJoinedArg(const Arg *BaseArg, const Option Opt, 
-                     StringRef Value) { 
-     append(MakeJoinedArg(BaseArg, Opt, Value)); 
-   } 
-   
-   /// MakeFlagArg - Construct a new FlagArg for the given option \p Id. 
-   Arg *MakeFlagArg(const Arg *BaseArg, const Option Opt) const; 
-   
-   /// MakePositionalArg - Construct a new Positional arg for the 
-   /// given option \p Id, with the provided \p Value. 
-   Arg *MakePositionalArg(const Arg *BaseArg, const Option Opt, 
-                           StringRef Value) const; 
-   
-   /// MakeSeparateArg - Construct a new Positional arg for the 
-   /// given option \p Id, with the provided \p Value. 
-   Arg *MakeSeparateArg(const Arg *BaseArg, const Option Opt, 
-                         StringRef Value) const; 
-   
-   /// MakeJoinedArg - Construct a new Positional arg for the 
-   /// given option \p Id, with the provided \p Value. 
-   Arg *MakeJoinedArg(const Arg *BaseArg, const Option Opt, 
-                       StringRef Value) const; 
-   
-   /// @} 
- }; 
-   
- } // end namespace opt 
-   
- } // end namespace llvm 
-   
- #endif // LLVM_OPTION_ARGLIST_H 
-