//===- 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;

  /// The OptSpecifiers that were queried from this argument list.
  mutable DenseSet<unsigned> QueriedOpts;

  /// Record the queried OptSpecifiers.
  template <typename... OptSpecifiers>
  void recordQueriedOpts(OptSpecifiers... Ids) const {
    SmallVector<unsigned, 4> OptsSpecifiers({toOptSpecifier(Ids).getID()...});
    QueriedOpts.insert(OptsSpecifiers.begin(), OptsSpecifiers.end());
  }

  /// 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 {
    recordQueriedOpts(Ids...);
    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 {
    recordQueriedOpts(Ids...);
    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 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=true) 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 = true) const;

  /// 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 not matching any of the excluded
  /// ids.
  void AddAllArgsExcept(ArgStringList &Output,
                        const DenseSet<unsigned> &ExcludeIds) const;
  /// 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;

  /// Return the OptSpecifiers queried from this argument list.
  const DenseSet<unsigned> &getQueriedOpts() const { return QueriedOpts; }

  /// Clear the set of queried OptSpecifiers.
  void clearQueriedOpts() const { QueriedOpts.clear(); }

  /// @}
  /// @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
