LCOV - code coverage report
Current view: top level - /usr/lib/llvm-19/include/llvm/ADT - STLExtras.h (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 0.0 % 23 0
Test Date: 2026-07-03 19:57:34 Functions: 0.0 % 8 0
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 0.0 % 12 0

             Branch data     Line data    Source code
       1                 :             : //===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- 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                 :             : /// \file
      10                 :             : /// This file contains some templates that are useful if you are working with
      11                 :             : /// the STL at all.
      12                 :             : ///
      13                 :             : /// No library is required when using these functions.
      14                 :             : ///
      15                 :             : //===----------------------------------------------------------------------===//
      16                 :             : 
      17                 :             : #ifndef LLVM_ADT_STLEXTRAS_H
      18                 :             : #define LLVM_ADT_STLEXTRAS_H
      19                 :             : 
      20                 :             : #include "llvm/ADT/ADL.h"
      21                 :             : #include "llvm/ADT/Hashing.h"
      22                 :             : #include "llvm/ADT/STLForwardCompat.h"
      23                 :             : #include "llvm/ADT/STLFunctionalExtras.h"
      24                 :             : #include "llvm/ADT/iterator.h"
      25                 :             : #include "llvm/ADT/iterator_range.h"
      26                 :             : #include "llvm/Config/abi-breaking.h"
      27                 :             : #include "llvm/Support/ErrorHandling.h"
      28                 :             : #include <algorithm>
      29                 :             : #include <cassert>
      30                 :             : #include <cstddef>
      31                 :             : #include <cstdint>
      32                 :             : #include <cstdlib>
      33                 :             : #include <functional>
      34                 :             : #include <initializer_list>
      35                 :             : #include <iterator>
      36                 :             : #include <limits>
      37                 :             : #include <memory>
      38                 :             : #include <optional>
      39                 :             : #include <tuple>
      40                 :             : #include <type_traits>
      41                 :             : #include <utility>
      42                 :             : 
      43                 :             : #ifdef EXPENSIVE_CHECKS
      44                 :             : #include <random> // for std::mt19937
      45                 :             : #endif
      46                 :             : 
      47                 :             : namespace llvm {
      48                 :             : 
      49                 :             : //===----------------------------------------------------------------------===//
      50                 :             : //     Extra additions to <type_traits>
      51                 :             : //===----------------------------------------------------------------------===//
      52                 :             : 
      53                 :             : template <typename T> struct make_const_ptr {
      54                 :             :   using type = std::add_pointer_t<std::add_const_t<T>>;
      55                 :             : };
      56                 :             : 
      57                 :             : template <typename T> struct make_const_ref {
      58                 :             :   using type = std::add_lvalue_reference_t<std::add_const_t<T>>;
      59                 :             : };
      60                 :             : 
      61                 :             : namespace detail {
      62                 :             : template <class, template <class...> class Op, class... Args> struct detector {
      63                 :             :   using value_t = std::false_type;
      64                 :             : };
      65                 :             : template <template <class...> class Op, class... Args>
      66                 :             : struct detector<std::void_t<Op<Args...>>, Op, Args...> {
      67                 :             :   using value_t = std::true_type;
      68                 :             : };
      69                 :             : } // end namespace detail
      70                 :             : 
      71                 :             : /// Detects if a given trait holds for some set of arguments 'Args'.
      72                 :             : /// For example, the given trait could be used to detect if a given type
      73                 :             : /// has a copy assignment operator:
      74                 :             : ///   template<class T>
      75                 :             : ///   using has_copy_assign_t = decltype(std::declval<T&>()
      76                 :             : ///                                                 = std::declval<const T&>());
      77                 :             : ///   bool fooHasCopyAssign = is_detected<has_copy_assign_t, FooClass>::value;
      78                 :             : template <template <class...> class Op, class... Args>
      79                 :             : using is_detected = typename detail::detector<void, Op, Args...>::value_t;
      80                 :             : 
      81                 :             : /// This class provides various trait information about a callable object.
      82                 :             : ///   * To access the number of arguments: Traits::num_args
      83                 :             : ///   * To access the type of an argument: Traits::arg_t<Index>
      84                 :             : ///   * To access the type of the result:  Traits::result_t
      85                 :             : template <typename T, bool isClass = std::is_class<T>::value>
      86                 :             : struct function_traits : public function_traits<decltype(&T::operator())> {};
      87                 :             : 
      88                 :             : /// Overload for class function types.
      89                 :             : template <typename ClassType, typename ReturnType, typename... Args>
      90                 :             : struct function_traits<ReturnType (ClassType::*)(Args...) const, false> {
      91                 :             :   /// The number of arguments to this function.
      92                 :             :   enum { num_args = sizeof...(Args) };
      93                 :             : 
      94                 :             :   /// The result type of this function.
      95                 :             :   using result_t = ReturnType;
      96                 :             : 
      97                 :             :   /// The type of an argument to this function.
      98                 :             :   template <size_t Index>
      99                 :             :   using arg_t = std::tuple_element_t<Index, std::tuple<Args...>>;
     100                 :             : };
     101                 :             : /// Overload for class function types.
     102                 :             : template <typename ClassType, typename ReturnType, typename... Args>
     103                 :             : struct function_traits<ReturnType (ClassType::*)(Args...), false>
     104                 :             :     : public function_traits<ReturnType (ClassType::*)(Args...) const> {};
     105                 :             : /// Overload for non-class function types.
     106                 :             : template <typename ReturnType, typename... Args>
     107                 :             : struct function_traits<ReturnType (*)(Args...), false> {
     108                 :             :   /// The number of arguments to this function.
     109                 :             :   enum { num_args = sizeof...(Args) };
     110                 :             : 
     111                 :             :   /// The result type of this function.
     112                 :             :   using result_t = ReturnType;
     113                 :             : 
     114                 :             :   /// The type of an argument to this function.
     115                 :             :   template <size_t i>
     116                 :             :   using arg_t = std::tuple_element_t<i, std::tuple<Args...>>;
     117                 :             : };
     118                 :             : template <typename ReturnType, typename... Args>
     119                 :             : struct function_traits<ReturnType (*const)(Args...), false>
     120                 :             :     : public function_traits<ReturnType (*)(Args...)> {};
     121                 :             : /// Overload for non-class function type references.
     122                 :             : template <typename ReturnType, typename... Args>
     123                 :             : struct function_traits<ReturnType (&)(Args...), false>
     124                 :             :     : public function_traits<ReturnType (*)(Args...)> {};
     125                 :             : 
     126                 :             : /// traits class for checking whether type T is one of any of the given
     127                 :             : /// types in the variadic list.
     128                 :             : template <typename T, typename... Ts>
     129                 :             : using is_one_of = std::disjunction<std::is_same<T, Ts>...>;
     130                 :             : 
     131                 :             : /// traits class for checking whether type T is a base class for all
     132                 :             : ///  the given types in the variadic list.
     133                 :             : template <typename T, typename... Ts>
     134                 :             : using are_base_of = std::conjunction<std::is_base_of<T, Ts>...>;
     135                 :             : 
     136                 :             : namespace detail {
     137                 :             : template <typename T, typename... Us> struct TypesAreDistinct;
     138                 :             : template <typename T, typename... Us>
     139                 :             : struct TypesAreDistinct
     140                 :             :     : std::integral_constant<bool, !is_one_of<T, Us...>::value &&
     141                 :             :                                        TypesAreDistinct<Us...>::value> {};
     142                 :             : template <typename T> struct TypesAreDistinct<T> : std::true_type {};
     143                 :             : } // namespace detail
     144                 :             : 
     145                 :             : /// Determine if all types in Ts are distinct.
     146                 :             : ///
     147                 :             : /// Useful to statically assert when Ts is intended to describe a non-multi set
     148                 :             : /// of types.
     149                 :             : ///
     150                 :             : /// Expensive (currently quadratic in sizeof(Ts...)), and so should only be
     151                 :             : /// asserted once per instantiation of a type which requires it.
     152                 :             : template <typename... Ts> struct TypesAreDistinct;
     153                 :             : template <> struct TypesAreDistinct<> : std::true_type {};
     154                 :             : template <typename... Ts>
     155                 :             : struct TypesAreDistinct
     156                 :             :     : std::integral_constant<bool, detail::TypesAreDistinct<Ts...>::value> {};
     157                 :             : 
     158                 :             : /// Find the first index where a type appears in a list of types.
     159                 :             : ///
     160                 :             : /// FirstIndexOfType<T, Us...>::value is the first index of T in Us.
     161                 :             : ///
     162                 :             : /// Typically only meaningful when it is otherwise statically known that the
     163                 :             : /// type pack has no duplicate types. This should be guaranteed explicitly with
     164                 :             : /// static_assert(TypesAreDistinct<Us...>::value).
     165                 :             : ///
     166                 :             : /// It is a compile-time error to instantiate when T is not present in Us, i.e.
     167                 :             : /// if is_one_of<T, Us...>::value is false.
     168                 :             : template <typename T, typename... Us> struct FirstIndexOfType;
     169                 :             : template <typename T, typename U, typename... Us>
     170                 :             : struct FirstIndexOfType<T, U, Us...>
     171                 :             :     : std::integral_constant<size_t, 1 + FirstIndexOfType<T, Us...>::value> {};
     172                 :             : template <typename T, typename... Us>
     173                 :             : struct FirstIndexOfType<T, T, Us...> : std::integral_constant<size_t, 0> {};
     174                 :             : 
     175                 :             : /// Find the type at a given index in a list of types.
     176                 :             : ///
     177                 :             : /// TypeAtIndex<I, Ts...> is the type at index I in Ts.
     178                 :             : template <size_t I, typename... Ts>
     179                 :             : using TypeAtIndex = std::tuple_element_t<I, std::tuple<Ts...>>;
     180                 :             : 
     181                 :             : /// Helper which adds two underlying types of enumeration type.
     182                 :             : /// Implicit conversion to a common type is accepted.
     183                 :             : template <typename EnumTy1, typename EnumTy2,
     184                 :             :           typename UT1 = std::enable_if_t<std::is_enum<EnumTy1>::value,
     185                 :             :                                           std::underlying_type_t<EnumTy1>>,
     186                 :             :           typename UT2 = std::enable_if_t<std::is_enum<EnumTy2>::value,
     187                 :             :                                           std::underlying_type_t<EnumTy2>>>
     188                 :             : constexpr auto addEnumValues(EnumTy1 LHS, EnumTy2 RHS) {
     189                 :             :   return static_cast<UT1>(LHS) + static_cast<UT2>(RHS);
     190                 :             : }
     191                 :             : 
     192                 :             : //===----------------------------------------------------------------------===//
     193                 :             : //     Extra additions to <iterator>
     194                 :             : //===----------------------------------------------------------------------===//
     195                 :             : 
     196                 :             : namespace callable_detail {
     197                 :             : 
     198                 :             : /// Templated storage wrapper for a callable.
     199                 :             : ///
     200                 :             : /// This class is consistently default constructible, copy / move
     201                 :             : /// constructible / assignable.
     202                 :             : ///
     203                 :             : /// Supported callable types:
     204                 :             : ///  - Function pointer
     205                 :             : ///  - Function reference
     206                 :             : ///  - Lambda
     207                 :             : ///  - Function object
     208                 :             : template <typename T,
     209                 :             :           bool = std::is_function_v<std::remove_pointer_t<remove_cvref_t<T>>>>
     210                 :             : class Callable {
     211                 :             :   using value_type = std::remove_reference_t<T>;
     212                 :             :   using reference = value_type &;
     213                 :             :   using const_reference = value_type const &;
     214                 :             : 
     215                 :             :   std::optional<value_type> Obj;
     216                 :             : 
     217                 :             :   static_assert(!std::is_pointer_v<value_type>,
     218                 :             :                 "Pointers to non-functions are not callable.");
     219                 :             : 
     220                 :             : public:
     221                 :             :   Callable() = default;
     222                 :           0 :   Callable(T const &O) : Obj(std::in_place, O) {}
     223                 :             : 
     224                 :             :   Callable(Callable const &Other) = default;
     225                 :             :   Callable(Callable &&Other) = default;
     226                 :             : 
     227                 :             :   Callable &operator=(Callable const &Other) {
     228                 :             :     Obj = std::nullopt;
     229                 :             :     if (Other.Obj)
     230                 :             :       Obj.emplace(*Other.Obj);
     231                 :             :     return *this;
     232                 :             :   }
     233                 :             : 
     234                 :             :   Callable &operator=(Callable &&Other) {
     235                 :             :     Obj = std::nullopt;
     236                 :             :     if (Other.Obj)
     237                 :             :       Obj.emplace(std::move(*Other.Obj));
     238                 :             :     return *this;
     239                 :             :   }
     240                 :             : 
     241                 :             :   template <typename... Pn,
     242                 :             :             std::enable_if_t<std::is_invocable_v<T, Pn...>, int> = 0>
     243                 :             :   decltype(auto) operator()(Pn &&...Params) {
     244                 :             :     return (*Obj)(std::forward<Pn>(Params)...);
     245                 :             :   }
     246                 :             : 
     247                 :             :   template <typename... Pn,
     248                 :             :             std::enable_if_t<std::is_invocable_v<T const, Pn...>, int> = 0>
     249                 :             :   decltype(auto) operator()(Pn &&...Params) const {
     250                 :             :     return (*Obj)(std::forward<Pn>(Params)...);
     251                 :             :   }
     252                 :             : 
     253                 :             :   bool valid() const { return Obj != std::nullopt; }
     254                 :             :   bool reset() { return Obj = std::nullopt; }
     255                 :             : 
     256                 :             :   operator reference() { return *Obj; }
     257                 :             :   operator const_reference() const { return *Obj; }
     258                 :             : };
     259                 :             : 
     260                 :             : // Function specialization.  No need to waste extra space wrapping with a
     261                 :             : // std::optional.
     262                 :             : template <typename T> class Callable<T, true> {
     263                 :             :   static constexpr bool IsPtr = std::is_pointer_v<remove_cvref_t<T>>;
     264                 :             : 
     265                 :             :   using StorageT = std::conditional_t<IsPtr, T, std::remove_reference_t<T> *>;
     266                 :             :   using CastT = std::conditional_t<IsPtr, T, T &>;
     267                 :             : 
     268                 :             : private:
     269                 :             :   StorageT Func = nullptr;
     270                 :             : 
     271                 :             : private:
     272                 :             :   template <typename In> static constexpr auto convertIn(In &&I) {
     273                 :             :     if constexpr (IsPtr) {
     274                 :             :       // Pointer... just echo it back.
     275                 :             :       return I;
     276                 :             :     } else {
     277                 :             :       // Must be a function reference.  Return its address.
     278                 :             :       return &I;
     279                 :             :     }
     280                 :             :   }
     281                 :             : 
     282                 :             : public:
     283                 :             :   Callable() = default;
     284                 :             : 
     285                 :             :   // Construct from a function pointer or reference.
     286                 :             :   //
     287                 :             :   // Disable this constructor for references to 'Callable' so we don't violate
     288                 :             :   // the rule of 0.
     289                 :             :   template < // clang-format off
     290                 :             :     typename FnPtrOrRef,
     291                 :             :     std::enable_if_t<
     292                 :             :       !std::is_same_v<remove_cvref_t<FnPtrOrRef>, Callable>, int
     293                 :             :     > = 0
     294                 :             :   > // clang-format on
     295                 :             :   Callable(FnPtrOrRef &&F) : Func(convertIn(F)) {}
     296                 :             : 
     297                 :             :   template <typename... Pn,
     298                 :             :             std::enable_if_t<std::is_invocable_v<T, Pn...>, int> = 0>
     299                 :             :   decltype(auto) operator()(Pn &&...Params) const {
     300                 :             :     return Func(std::forward<Pn>(Params)...);
     301                 :             :   }
     302                 :             : 
     303                 :             :   bool valid() const { return Func != nullptr; }
     304                 :             :   void reset() { Func = nullptr; }
     305                 :             : 
     306                 :             :   operator T const &() const {
     307                 :             :     if constexpr (IsPtr) {
     308                 :             :       // T is a pointer... just echo it back.
     309                 :             :       return Func;
     310                 :             :     } else {
     311                 :             :       static_assert(std::is_reference_v<T>,
     312                 :             :                     "Expected a reference to a function.");
     313                 :             :       // T is a function reference... dereference the stored pointer.
     314                 :             :       return *Func;
     315                 :             :     }
     316                 :             :   }
     317                 :             : };
     318                 :             : 
     319                 :             : } // namespace callable_detail
     320                 :             : 
     321                 :             : /// Returns true if the given container only contains a single element.
     322                 :             : template <typename ContainerTy> bool hasSingleElement(ContainerTy &&C) {
     323                 :             :   auto B = std::begin(C), E = std::end(C);
     324                 :             :   return B != E && std::next(B) == E;
     325                 :             : }
     326                 :             : 
     327                 :             : /// Return a range covering \p RangeOrContainer with the first N elements
     328                 :             : /// excluded.
     329                 :             : template <typename T> auto drop_begin(T &&RangeOrContainer, size_t N = 1) {
     330                 :             :   return make_range(std::next(adl_begin(RangeOrContainer), N),
     331                 :             :                     adl_end(RangeOrContainer));
     332                 :             : }
     333                 :             : 
     334                 :             : /// Return a range covering \p RangeOrContainer with the last N elements
     335                 :             : /// excluded.
     336                 :             : template <typename T> auto drop_end(T &&RangeOrContainer, size_t N = 1) {
     337                 :             :   return make_range(adl_begin(RangeOrContainer),
     338                 :             :                     std::prev(adl_end(RangeOrContainer), N));
     339                 :             : }
     340                 :             : 
     341                 :             : // mapped_iterator - This is a simple iterator adapter that causes a function to
     342                 :             : // be applied whenever operator* is invoked on the iterator.
     343                 :             : 
     344                 :             : template <typename ItTy, typename FuncTy,
     345                 :             :           typename ReferenceTy =
     346                 :             :               decltype(std::declval<FuncTy>()(*std::declval<ItTy>()))>
     347                 :             : class mapped_iterator
     348                 :             :     : public iterator_adaptor_base<
     349                 :             :           mapped_iterator<ItTy, FuncTy>, ItTy,
     350                 :             :           typename std::iterator_traits<ItTy>::iterator_category,
     351                 :             :           std::remove_reference_t<ReferenceTy>,
     352                 :             :           typename std::iterator_traits<ItTy>::difference_type,
     353                 :             :           std::remove_reference_t<ReferenceTy> *, ReferenceTy> {
     354                 :             : public:
     355                 :             :   mapped_iterator() = default;
     356                 :           0 :   mapped_iterator(ItTy U, FuncTy F)
     357                 :           0 :     : mapped_iterator::iterator_adaptor_base(std::move(U)), F(std::move(F)) {}
     358                 :             : 
     359                 :             :   ItTy getCurrent() { return this->I; }
     360                 :             : 
     361                 :             :   const FuncTy &getFunction() const { return F; }
     362                 :             : 
     363                 :             :   ReferenceTy operator*() const { return F(*this->I); }
     364                 :             : 
     365                 :             : private:
     366                 :             :   callable_detail::Callable<FuncTy> F{};
     367                 :             : };
     368                 :             : 
     369                 :             : // map_iterator - Provide a convenient way to create mapped_iterators, just like
     370                 :             : // make_pair is useful for creating pairs...
     371                 :             : template <class ItTy, class FuncTy>
     372                 :           0 : inline mapped_iterator<ItTy, FuncTy> map_iterator(ItTy I, FuncTy F) {
     373                 :           0 :   return mapped_iterator<ItTy, FuncTy>(std::move(I), std::move(F));
     374                 :             : }
     375                 :             : 
     376                 :             : template <class ContainerTy, class FuncTy>
     377                 :           0 : auto map_range(ContainerTy &&C, FuncTy F) {
     378                 :           0 :   return make_range(map_iterator(std::begin(C), F),
     379                 :           0 :                     map_iterator(std::end(C), F));
     380                 :             : }
     381                 :             : 
     382                 :             : /// A base type of mapped iterator, that is useful for building derived
     383                 :             : /// iterators that do not need/want to store the map function (as in
     384                 :             : /// mapped_iterator). These iterators must simply provide a `mapElement` method
     385                 :             : /// that defines how to map a value of the iterator to the provided reference
     386                 :             : /// type.
     387                 :             : template <typename DerivedT, typename ItTy, typename ReferenceTy>
     388                 :             : class mapped_iterator_base
     389                 :             :     : public iterator_adaptor_base<
     390                 :             :           DerivedT, ItTy,
     391                 :             :           typename std::iterator_traits<ItTy>::iterator_category,
     392                 :             :           std::remove_reference_t<ReferenceTy>,
     393                 :             :           typename std::iterator_traits<ItTy>::difference_type,
     394                 :             :           std::remove_reference_t<ReferenceTy> *, ReferenceTy> {
     395                 :             : public:
     396                 :             :   using BaseT = mapped_iterator_base;
     397                 :             : 
     398                 :             :   mapped_iterator_base(ItTy U)
     399                 :             :       : mapped_iterator_base::iterator_adaptor_base(std::move(U)) {}
     400                 :             : 
     401                 :             :   ItTy getCurrent() { return this->I; }
     402                 :             : 
     403                 :             :   ReferenceTy operator*() const {
     404                 :             :     return static_cast<const DerivedT &>(*this).mapElement(*this->I);
     405                 :             :   }
     406                 :             : };
     407                 :             : 
     408                 :             : namespace detail {
     409                 :             : template <typename Range>
     410                 :             : using check_has_free_function_rbegin =
     411                 :             :     decltype(adl_rbegin(std::declval<Range &>()));
     412                 :             : 
     413                 :             : template <typename Range>
     414                 :             : static constexpr bool HasFreeFunctionRBegin =
     415                 :             :     is_detected<check_has_free_function_rbegin, Range>::value;
     416                 :             : } // namespace detail
     417                 :             : 
     418                 :             : // Returns an iterator_range over the given container which iterates in reverse.
     419                 :             : template <typename ContainerTy> auto reverse(ContainerTy &&C) {
     420                 :             :   if constexpr (detail::HasFreeFunctionRBegin<ContainerTy>)
     421                 :             :     return make_range(adl_rbegin(C), adl_rend(C));
     422                 :             :   else
     423                 :             :     return make_range(std::make_reverse_iterator(adl_end(C)),
     424                 :             :                       std::make_reverse_iterator(adl_begin(C)));
     425                 :             : }
     426                 :             : 
     427                 :             : /// An iterator adaptor that filters the elements of given inner iterators.
     428                 :             : ///
     429                 :             : /// The predicate parameter should be a callable object that accepts the wrapped
     430                 :             : /// iterator's reference type and returns a bool. When incrementing or
     431                 :             : /// decrementing the iterator, it will call the predicate on each element and
     432                 :             : /// skip any where it returns false.
     433                 :             : ///
     434                 :             : /// \code
     435                 :             : ///   int A[] = { 1, 2, 3, 4 };
     436                 :             : ///   auto R = make_filter_range(A, [](int N) { return N % 2 == 1; });
     437                 :             : ///   // R contains { 1, 3 }.
     438                 :             : /// \endcode
     439                 :             : ///
     440                 :             : /// Note: filter_iterator_base implements support for forward iteration.
     441                 :             : /// filter_iterator_impl exists to provide support for bidirectional iteration,
     442                 :             : /// conditional on whether the wrapped iterator supports it.
     443                 :             : template <typename WrappedIteratorT, typename PredicateT, typename IterTag>
     444                 :             : class filter_iterator_base
     445                 :             :     : public iterator_adaptor_base<
     446                 :             :           filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>,
     447                 :             :           WrappedIteratorT,
     448                 :             :           std::common_type_t<IterTag,
     449                 :             :                              typename std::iterator_traits<
     450                 :             :                                  WrappedIteratorT>::iterator_category>> {
     451                 :             :   using BaseT = typename filter_iterator_base::iterator_adaptor_base;
     452                 :             : 
     453                 :             : protected:
     454                 :             :   WrappedIteratorT End;
     455                 :             :   PredicateT Pred;
     456                 :             : 
     457                 :           0 :   void findNextValid() {
     458   [ #  #  #  #  :           0 :     while (this->I != End && !Pred(*this->I))
                   #  # ]
     459                 :           0 :       BaseT::operator++();
     460                 :           0 :   }
     461                 :             : 
     462                 :             :   filter_iterator_base() = default;
     463                 :             : 
     464                 :             :   // Construct the iterator. The begin iterator needs to know where the end
     465                 :             :   // is, so that it can properly stop when it gets there. The end iterator only
     466                 :             :   // needs the predicate to support bidirectional iteration.
     467                 :           0 :   filter_iterator_base(WrappedIteratorT Begin, WrappedIteratorT End,
     468                 :             :                        PredicateT Pred)
     469                 :           0 :       : BaseT(Begin), End(End), Pred(Pred) {
     470                 :           0 :     findNextValid();
     471                 :           0 :   }
     472                 :             : 
     473                 :             : public:
     474                 :             :   using BaseT::operator++;
     475                 :             : 
     476                 :             :   filter_iterator_base &operator++() {
     477                 :             :     BaseT::operator++();
     478                 :             :     findNextValid();
     479                 :             :     return *this;
     480                 :             :   }
     481                 :             : 
     482                 :             :   decltype(auto) operator*() const {
     483                 :             :     assert(BaseT::wrapped() != End && "Cannot dereference end iterator!");
     484                 :             :     return BaseT::operator*();
     485                 :             :   }
     486                 :             : 
     487                 :             :   decltype(auto) operator->() const {
     488                 :             :     assert(BaseT::wrapped() != End && "Cannot dereference end iterator!");
     489                 :             :     return BaseT::operator->();
     490                 :             :   }
     491                 :             : };
     492                 :             : 
     493                 :             : /// Specialization of filter_iterator_base for forward iteration only.
     494                 :             : template <typename WrappedIteratorT, typename PredicateT,
     495                 :             :           typename IterTag = std::forward_iterator_tag>
     496                 :             : class filter_iterator_impl
     497                 :             :     : public filter_iterator_base<WrappedIteratorT, PredicateT, IterTag> {
     498                 :             : public:
     499                 :             :   filter_iterator_impl() = default;
     500                 :             : 
     501                 :             :   filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End,
     502                 :             :                        PredicateT Pred)
     503                 :             :       : filter_iterator_impl::filter_iterator_base(Begin, End, Pred) {}
     504                 :             : };
     505                 :             : 
     506                 :             : /// Specialization of filter_iterator_base for bidirectional iteration.
     507                 :             : template <typename WrappedIteratorT, typename PredicateT>
     508                 :             : class filter_iterator_impl<WrappedIteratorT, PredicateT,
     509                 :             :                            std::bidirectional_iterator_tag>
     510                 :             :     : public filter_iterator_base<WrappedIteratorT, PredicateT,
     511                 :             :                                   std::bidirectional_iterator_tag> {
     512                 :             :   using BaseT = typename filter_iterator_impl::filter_iterator_base;
     513                 :             : 
     514                 :             :   void findPrevValid() {
     515                 :             :     while (!this->Pred(*this->I))
     516                 :             :       BaseT::operator--();
     517                 :             :   }
     518                 :             : 
     519                 :             : public:
     520                 :             :   using BaseT::operator--;
     521                 :             : 
     522                 :             :   filter_iterator_impl() = default;
     523                 :             : 
     524                 :           0 :   filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End,
     525                 :             :                        PredicateT Pred)
     526                 :           0 :       : BaseT(Begin, End, Pred) {}
     527                 :             : 
     528                 :             :   filter_iterator_impl &operator--() {
     529                 :             :     BaseT::operator--();
     530                 :             :     findPrevValid();
     531                 :             :     return *this;
     532                 :             :   }
     533                 :             : };
     534                 :             : 
     535                 :             : namespace detail {
     536                 :             : 
     537                 :             : template <bool is_bidirectional> struct fwd_or_bidi_tag_impl {
     538                 :             :   using type = std::forward_iterator_tag;
     539                 :             : };
     540                 :             : 
     541                 :             : template <> struct fwd_or_bidi_tag_impl<true> {
     542                 :             :   using type = std::bidirectional_iterator_tag;
     543                 :             : };
     544                 :             : 
     545                 :             : /// Helper which sets its type member to forward_iterator_tag if the category
     546                 :             : /// of \p IterT does not derive from bidirectional_iterator_tag, and to
     547                 :             : /// bidirectional_iterator_tag otherwise.
     548                 :             : template <typename IterT> struct fwd_or_bidi_tag {
     549                 :             :   using type = typename fwd_or_bidi_tag_impl<std::is_base_of<
     550                 :             :       std::bidirectional_iterator_tag,
     551                 :             :       typename std::iterator_traits<IterT>::iterator_category>::value>::type;
     552                 :             : };
     553                 :             : 
     554                 :             : } // namespace detail
     555                 :             : 
     556                 :             : /// Defines filter_iterator to a suitable specialization of
     557                 :             : /// filter_iterator_impl, based on the underlying iterator's category.
     558                 :             : template <typename WrappedIteratorT, typename PredicateT>
     559                 :             : using filter_iterator = filter_iterator_impl<
     560                 :             :     WrappedIteratorT, PredicateT,
     561                 :             :     typename detail::fwd_or_bidi_tag<WrappedIteratorT>::type>;
     562                 :             : 
     563                 :             : /// Convenience function that takes a range of elements and a predicate,
     564                 :             : /// and return a new filter_iterator range.
     565                 :             : ///
     566                 :             : /// FIXME: Currently if RangeT && is a rvalue reference to a temporary, the
     567                 :             : /// lifetime of that temporary is not kept by the returned range object, and the
     568                 :             : /// temporary is going to be dropped on the floor after the make_iterator_range
     569                 :             : /// full expression that contains this function call.
     570                 :             : template <typename RangeT, typename PredicateT>
     571                 :             : iterator_range<filter_iterator<detail::IterOfRange<RangeT>, PredicateT>>
     572                 :           0 : make_filter_range(RangeT &&Range, PredicateT Pred) {
     573                 :             :   using FilterIteratorT =
     574                 :             :       filter_iterator<detail::IterOfRange<RangeT>, PredicateT>;
     575         [ #  # ]:           0 :   return make_range(
     576         [ #  # ]:           0 :       FilterIteratorT(std::begin(std::forward<RangeT>(Range)),
     577                 :             :                       std::end(std::forward<RangeT>(Range)), Pred),
     578         [ #  # ]:           0 :       FilterIteratorT(std::end(std::forward<RangeT>(Range)),
     579                 :           0 :                       std::end(std::forward<RangeT>(Range)), Pred));
     580                 :             : }
     581                 :             : 
     582                 :             : /// A pseudo-iterator adaptor that is designed to implement "early increment"
     583                 :             : /// style loops.
     584                 :             : ///
     585                 :             : /// This is *not a normal iterator* and should almost never be used directly. It
     586                 :             : /// is intended primarily to be used with range based for loops and some range
     587                 :             : /// algorithms.
     588                 :             : ///
     589                 :             : /// The iterator isn't quite an `OutputIterator` or an `InputIterator` but
     590                 :             : /// somewhere between them. The constraints of these iterators are:
     591                 :             : ///
     592                 :             : /// - On construction or after being incremented, it is comparable and
     593                 :             : ///   dereferencable. It is *not* incrementable.
     594                 :             : /// - After being dereferenced, it is neither comparable nor dereferencable, it
     595                 :             : ///   is only incrementable.
     596                 :             : ///
     597                 :             : /// This means you can only dereference the iterator once, and you can only
     598                 :             : /// increment it once between dereferences.
     599                 :             : template <typename WrappedIteratorT>
     600                 :             : class early_inc_iterator_impl
     601                 :             :     : public iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>,
     602                 :             :                                    WrappedIteratorT, std::input_iterator_tag> {
     603                 :             :   using BaseT = typename early_inc_iterator_impl::iterator_adaptor_base;
     604                 :             : 
     605                 :             :   using PointerT = typename std::iterator_traits<WrappedIteratorT>::pointer;
     606                 :             : 
     607                 :             : protected:
     608                 :             : #if LLVM_ENABLE_ABI_BREAKING_CHECKS
     609                 :             :   bool IsEarlyIncremented = false;
     610                 :             : #endif
     611                 :             : 
     612                 :             : public:
     613                 :             :   early_inc_iterator_impl(WrappedIteratorT I) : BaseT(I) {}
     614                 :             : 
     615                 :             :   using BaseT::operator*;
     616                 :             :   decltype(*std::declval<WrappedIteratorT>()) operator*() {
     617                 :             : #if LLVM_ENABLE_ABI_BREAKING_CHECKS
     618                 :             :     assert(!IsEarlyIncremented && "Cannot dereference twice!");
     619                 :             :     IsEarlyIncremented = true;
     620                 :             : #endif
     621                 :             :     return *(this->I)++;
     622                 :             :   }
     623                 :             : 
     624                 :             :   using BaseT::operator++;
     625                 :             :   early_inc_iterator_impl &operator++() {
     626                 :             : #if LLVM_ENABLE_ABI_BREAKING_CHECKS
     627                 :             :     assert(IsEarlyIncremented && "Cannot increment before dereferencing!");
     628                 :             :     IsEarlyIncremented = false;
     629                 :             : #endif
     630                 :             :     return *this;
     631                 :             :   }
     632                 :             : 
     633                 :             :   friend bool operator==(const early_inc_iterator_impl &LHS,
     634                 :             :                          const early_inc_iterator_impl &RHS) {
     635                 :             : #if LLVM_ENABLE_ABI_BREAKING_CHECKS
     636                 :             :     assert(!LHS.IsEarlyIncremented && "Cannot compare after dereferencing!");
     637                 :             : #endif
     638                 :             :     return (const BaseT &)LHS == (const BaseT &)RHS;
     639                 :             :   }
     640                 :             : };
     641                 :             : 
     642                 :             : /// Make a range that does early increment to allow mutation of the underlying
     643                 :             : /// range without disrupting iteration.
     644                 :             : ///
     645                 :             : /// The underlying iterator will be incremented immediately after it is
     646                 :             : /// dereferenced, allowing deletion of the current node or insertion of nodes to
     647                 :             : /// not disrupt iteration provided they do not invalidate the *next* iterator --
     648                 :             : /// the current iterator can be invalidated.
     649                 :             : ///
     650                 :             : /// This requires a very exact pattern of use that is only really suitable to
     651                 :             : /// range based for loops and other range algorithms that explicitly guarantee
     652                 :             : /// to dereference exactly once each element, and to increment exactly once each
     653                 :             : /// element.
     654                 :             : template <typename RangeT>
     655                 :             : iterator_range<early_inc_iterator_impl<detail::IterOfRange<RangeT>>>
     656                 :             : make_early_inc_range(RangeT &&Range) {
     657                 :             :   using EarlyIncIteratorT =
     658                 :             :       early_inc_iterator_impl<detail::IterOfRange<RangeT>>;
     659                 :             :   return make_range(EarlyIncIteratorT(std::begin(std::forward<RangeT>(Range))),
     660                 :             :                     EarlyIncIteratorT(std::end(std::forward<RangeT>(Range))));
     661                 :             : }
     662                 :             : 
     663                 :             : // Forward declarations required by zip_shortest/zip_equal/zip_first/zip_longest
     664                 :             : template <typename R, typename UnaryPredicate>
     665                 :             : bool all_of(R &&range, UnaryPredicate P);
     666                 :             : 
     667                 :             : template <typename R, typename UnaryPredicate>
     668                 :             : bool any_of(R &&range, UnaryPredicate P);
     669                 :             : 
     670                 :             : template <typename T> bool all_equal(std::initializer_list<T> Values);
     671                 :             : 
     672                 :             : template <typename R> constexpr size_t range_size(R &&Range);
     673                 :             : 
     674                 :             : namespace detail {
     675                 :             : 
     676                 :             : using std::declval;
     677                 :             : 
     678                 :             : // We have to alias this since inlining the actual type at the usage site
     679                 :             : // in the parameter list of iterator_facade_base<> below ICEs MSVC 2017.
     680                 :             : template<typename... Iters> struct ZipTupleType {
     681                 :             :   using type = std::tuple<decltype(*declval<Iters>())...>;
     682                 :             : };
     683                 :             : 
     684                 :             : template <typename ZipType, typename ReferenceTupleType, typename... Iters>
     685                 :             : using zip_traits = iterator_facade_base<
     686                 :             :     ZipType,
     687                 :             :     std::common_type_t<
     688                 :             :         std::bidirectional_iterator_tag,
     689                 :             :         typename std::iterator_traits<Iters>::iterator_category...>,
     690                 :             :     // ^ TODO: Implement random access methods.
     691                 :             :     ReferenceTupleType,
     692                 :             :     typename std::iterator_traits<
     693                 :             :         std::tuple_element_t<0, std::tuple<Iters...>>>::difference_type,
     694                 :             :     // ^ FIXME: This follows boost::make_zip_iterator's assumption that all
     695                 :             :     // inner iterators have the same difference_type. It would fail if, for
     696                 :             :     // instance, the second field's difference_type were non-numeric while the
     697                 :             :     // first is.
     698                 :             :     ReferenceTupleType *, ReferenceTupleType>;
     699                 :             : 
     700                 :             : template <typename ZipType, typename ReferenceTupleType, typename... Iters>
     701                 :             : struct zip_common : public zip_traits<ZipType, ReferenceTupleType, Iters...> {
     702                 :             :   using Base = zip_traits<ZipType, ReferenceTupleType, Iters...>;
     703                 :             :   using IndexSequence = std::index_sequence_for<Iters...>;
     704                 :             :   using value_type = typename Base::value_type;
     705                 :             : 
     706                 :             :   std::tuple<Iters...> iterators;
     707                 :             : 
     708                 :             : protected:
     709                 :             :   template <size_t... Ns> value_type deref(std::index_sequence<Ns...>) const {
     710                 :             :     return value_type(*std::get<Ns>(iterators)...);
     711                 :             :   }
     712                 :             : 
     713                 :             :   template <size_t... Ns> void tup_inc(std::index_sequence<Ns...>) {
     714                 :             :     (++std::get<Ns>(iterators), ...);
     715                 :             :   }
     716                 :             : 
     717                 :             :   template <size_t... Ns> void tup_dec(std::index_sequence<Ns...>) {
     718                 :             :     (--std::get<Ns>(iterators), ...);
     719                 :             :   }
     720                 :             : 
     721                 :             :   template <size_t... Ns>
     722                 :             :   bool test_all_equals(const zip_common &other,
     723                 :             :                        std::index_sequence<Ns...>) const {
     724                 :             :     return ((std::get<Ns>(this->iterators) == std::get<Ns>(other.iterators)) &&
     725                 :             :             ...);
     726                 :             :   }
     727                 :             : 
     728                 :             : public:
     729                 :             :   zip_common(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {}
     730                 :             : 
     731                 :             :   value_type operator*() const { return deref(IndexSequence{}); }
     732                 :             : 
     733                 :             :   ZipType &operator++() {
     734                 :             :     tup_inc(IndexSequence{});
     735                 :             :     return static_cast<ZipType &>(*this);
     736                 :             :   }
     737                 :             : 
     738                 :             :   ZipType &operator--() {
     739                 :             :     static_assert(Base::IsBidirectional,
     740                 :             :                   "All inner iterators must be at least bidirectional.");
     741                 :             :     tup_dec(IndexSequence{});
     742                 :             :     return static_cast<ZipType &>(*this);
     743                 :             :   }
     744                 :             : 
     745                 :             :   /// Return true if all the iterator are matching `other`'s iterators.
     746                 :             :   bool all_equals(zip_common &other) {
     747                 :             :     return test_all_equals(other, IndexSequence{});
     748                 :             :   }
     749                 :             : };
     750                 :             : 
     751                 :             : template <typename... Iters>
     752                 :             : struct zip_first : zip_common<zip_first<Iters...>,
     753                 :             :                               typename ZipTupleType<Iters...>::type, Iters...> {
     754                 :             :   using zip_common<zip_first, typename ZipTupleType<Iters...>::type,
     755                 :             :                    Iters...>::zip_common;
     756                 :             : 
     757                 :             :   bool operator==(const zip_first &other) const {
     758                 :             :     return std::get<0>(this->iterators) == std::get<0>(other.iterators);
     759                 :             :   }
     760                 :             : };
     761                 :             : 
     762                 :             : template <typename... Iters>
     763                 :             : struct zip_shortest
     764                 :             :     : zip_common<zip_shortest<Iters...>, typename ZipTupleType<Iters...>::type,
     765                 :             :                  Iters...> {
     766                 :             :   using zip_common<zip_shortest, typename ZipTupleType<Iters...>::type,
     767                 :             :                    Iters...>::zip_common;
     768                 :             : 
     769                 :             :   bool operator==(const zip_shortest &other) const {
     770                 :             :     return any_iterator_equals(other, std::index_sequence_for<Iters...>{});
     771                 :             :   }
     772                 :             : 
     773                 :             : private:
     774                 :             :   template <size_t... Ns>
     775                 :             :   bool any_iterator_equals(const zip_shortest &other,
     776                 :             :                            std::index_sequence<Ns...>) const {
     777                 :             :     return ((std::get<Ns>(this->iterators) == std::get<Ns>(other.iterators)) ||
     778                 :             :             ...);
     779                 :             :   }
     780                 :             : };
     781                 :             : 
     782                 :             : /// Helper to obtain the iterator types for the tuple storage within `zippy`.
     783                 :             : template <template <typename...> class ItType, typename TupleStorageType,
     784                 :             :           typename IndexSequence>
     785                 :             : struct ZippyIteratorTuple;
     786                 :             : 
     787                 :             : /// Partial specialization for non-const tuple storage.
     788                 :             : template <template <typename...> class ItType, typename... Args,
     789                 :             :           std::size_t... Ns>
     790                 :             : struct ZippyIteratorTuple<ItType, std::tuple<Args...>,
     791                 :             :                           std::index_sequence<Ns...>> {
     792                 :             :   using type = ItType<decltype(adl_begin(
     793                 :             :       std::get<Ns>(declval<std::tuple<Args...> &>())))...>;
     794                 :             : };
     795                 :             : 
     796                 :             : /// Partial specialization for const tuple storage.
     797                 :             : template <template <typename...> class ItType, typename... Args,
     798                 :             :           std::size_t... Ns>
     799                 :             : struct ZippyIteratorTuple<ItType, const std::tuple<Args...>,
     800                 :             :                           std::index_sequence<Ns...>> {
     801                 :             :   using type = ItType<decltype(adl_begin(
     802                 :             :       std::get<Ns>(declval<const std::tuple<Args...> &>())))...>;
     803                 :             : };
     804                 :             : 
     805                 :             : template <template <typename...> class ItType, typename... Args> class zippy {
     806                 :             : private:
     807                 :             :   std::tuple<Args...> storage;
     808                 :             :   using IndexSequence = std::index_sequence_for<Args...>;
     809                 :             : 
     810                 :             : public:
     811                 :             :   using iterator = typename ZippyIteratorTuple<ItType, decltype(storage),
     812                 :             :                                                IndexSequence>::type;
     813                 :             :   using const_iterator =
     814                 :             :       typename ZippyIteratorTuple<ItType, const decltype(storage),
     815                 :             :                                   IndexSequence>::type;
     816                 :             :   using iterator_category = typename iterator::iterator_category;
     817                 :             :   using value_type = typename iterator::value_type;
     818                 :             :   using difference_type = typename iterator::difference_type;
     819                 :             :   using pointer = typename iterator::pointer;
     820                 :             :   using reference = typename iterator::reference;
     821                 :             :   using const_reference = typename const_iterator::reference;
     822                 :             : 
     823                 :             :   zippy(Args &&...args) : storage(std::forward<Args>(args)...) {}
     824                 :             : 
     825                 :             :   const_iterator begin() const { return begin_impl(IndexSequence{}); }
     826                 :             :   iterator begin() { return begin_impl(IndexSequence{}); }
     827                 :             :   const_iterator end() const { return end_impl(IndexSequence{}); }
     828                 :             :   iterator end() { return end_impl(IndexSequence{}); }
     829                 :             : 
     830                 :             : private:
     831                 :             :   template <size_t... Ns>
     832                 :             :   const_iterator begin_impl(std::index_sequence<Ns...>) const {
     833                 :             :     return const_iterator(adl_begin(std::get<Ns>(storage))...);
     834                 :             :   }
     835                 :             :   template <size_t... Ns> iterator begin_impl(std::index_sequence<Ns...>) {
     836                 :             :     return iterator(adl_begin(std::get<Ns>(storage))...);
     837                 :             :   }
     838                 :             : 
     839                 :             :   template <size_t... Ns>
     840                 :             :   const_iterator end_impl(std::index_sequence<Ns...>) const {
     841                 :             :     return const_iterator(adl_end(std::get<Ns>(storage))...);
     842                 :             :   }
     843                 :             :   template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) {
     844                 :             :     return iterator(adl_end(std::get<Ns>(storage))...);
     845                 :             :   }
     846                 :             : };
     847                 :             : 
     848                 :             : } // end namespace detail
     849                 :             : 
     850                 :             : /// zip iterator for two or more iteratable types. Iteration continues until the
     851                 :             : /// end of the *shortest* iteratee is reached.
     852                 :             : template <typename T, typename U, typename... Args>
     853                 :             : detail::zippy<detail::zip_shortest, T, U, Args...> zip(T &&t, U &&u,
     854                 :             :                                                        Args &&...args) {
     855                 :             :   return detail::zippy<detail::zip_shortest, T, U, Args...>(
     856                 :             :       std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
     857                 :             : }
     858                 :             : 
     859                 :             : /// zip iterator that assumes that all iteratees have the same length.
     860                 :             : /// In builds with assertions on, this assumption is checked before the
     861                 :             : /// iteration starts.
     862                 :             : template <typename T, typename U, typename... Args>
     863                 :             : detail::zippy<detail::zip_first, T, U, Args...> zip_equal(T &&t, U &&u,
     864                 :             :                                                           Args &&...args) {
     865                 :             :   assert(all_equal({range_size(t), range_size(u), range_size(args)...}) &&
     866                 :             :          "Iteratees do not have equal length");
     867                 :             :   return detail::zippy<detail::zip_first, T, U, Args...>(
     868                 :             :       std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
     869                 :             : }
     870                 :             : 
     871                 :             : /// zip iterator that, for the sake of efficiency, assumes the first iteratee to
     872                 :             : /// be the shortest. Iteration continues until the end of the first iteratee is
     873                 :             : /// reached. In builds with assertions on, we check that the assumption about
     874                 :             : /// the first iteratee being the shortest holds.
     875                 :             : template <typename T, typename U, typename... Args>
     876                 :             : detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u,
     877                 :             :                                                           Args &&...args) {
     878                 :             :   assert(range_size(t) <= std::min({range_size(u), range_size(args)...}) &&
     879                 :             :          "First iteratee is not the shortest");
     880                 :             : 
     881                 :             :   return detail::zippy<detail::zip_first, T, U, Args...>(
     882                 :             :       std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
     883                 :             : }
     884                 :             : 
     885                 :             : namespace detail {
     886                 :             : template <typename Iter>
     887                 :             : Iter next_or_end(const Iter &I, const Iter &End) {
     888                 :             :   if (I == End)
     889                 :             :     return End;
     890                 :             :   return std::next(I);
     891                 :             : }
     892                 :             : 
     893                 :             : template <typename Iter>
     894                 :             : auto deref_or_none(const Iter &I, const Iter &End) -> std::optional<
     895                 :             :     std::remove_const_t<std::remove_reference_t<decltype(*I)>>> {
     896                 :             :   if (I == End)
     897                 :             :     return std::nullopt;
     898                 :             :   return *I;
     899                 :             : }
     900                 :             : 
     901                 :             : template <typename Iter> struct ZipLongestItemType {
     902                 :             :   using type = std::optional<std::remove_const_t<
     903                 :             :       std::remove_reference_t<decltype(*std::declval<Iter>())>>>;
     904                 :             : };
     905                 :             : 
     906                 :             : template <typename... Iters> struct ZipLongestTupleType {
     907                 :             :   using type = std::tuple<typename ZipLongestItemType<Iters>::type...>;
     908                 :             : };
     909                 :             : 
     910                 :             : template <typename... Iters>
     911                 :             : class zip_longest_iterator
     912                 :             :     : public iterator_facade_base<
     913                 :             :           zip_longest_iterator<Iters...>,
     914                 :             :           std::common_type_t<
     915                 :             :               std::forward_iterator_tag,
     916                 :             :               typename std::iterator_traits<Iters>::iterator_category...>,
     917                 :             :           typename ZipLongestTupleType<Iters...>::type,
     918                 :             :           typename std::iterator_traits<
     919                 :             :               std::tuple_element_t<0, std::tuple<Iters...>>>::difference_type,
     920                 :             :           typename ZipLongestTupleType<Iters...>::type *,
     921                 :             :           typename ZipLongestTupleType<Iters...>::type> {
     922                 :             : public:
     923                 :             :   using value_type = typename ZipLongestTupleType<Iters...>::type;
     924                 :             : 
     925                 :             : private:
     926                 :             :   std::tuple<Iters...> iterators;
     927                 :             :   std::tuple<Iters...> end_iterators;
     928                 :             : 
     929                 :             :   template <size_t... Ns>
     930                 :             :   bool test(const zip_longest_iterator<Iters...> &other,
     931                 :             :             std::index_sequence<Ns...>) const {
     932                 :             :     return ((std::get<Ns>(this->iterators) != std::get<Ns>(other.iterators)) ||
     933                 :             :             ...);
     934                 :             :   }
     935                 :             : 
     936                 :             :   template <size_t... Ns> value_type deref(std::index_sequence<Ns...>) const {
     937                 :             :     return value_type(
     938                 :             :         deref_or_none(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
     939                 :             :   }
     940                 :             : 
     941                 :             :   template <size_t... Ns>
     942                 :             :   decltype(iterators) tup_inc(std::index_sequence<Ns...>) const {
     943                 :             :     return std::tuple<Iters...>(
     944                 :             :         next_or_end(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
     945                 :             :   }
     946                 :             : 
     947                 :             : public:
     948                 :             :   zip_longest_iterator(std::pair<Iters &&, Iters &&>... ts)
     949                 :             :       : iterators(std::forward<Iters>(ts.first)...),
     950                 :             :         end_iterators(std::forward<Iters>(ts.second)...) {}
     951                 :             : 
     952                 :             :   value_type operator*() const {
     953                 :             :     return deref(std::index_sequence_for<Iters...>{});
     954                 :             :   }
     955                 :             : 
     956                 :             :   zip_longest_iterator<Iters...> &operator++() {
     957                 :             :     iterators = tup_inc(std::index_sequence_for<Iters...>{});
     958                 :             :     return *this;
     959                 :             :   }
     960                 :             : 
     961                 :             :   bool operator==(const zip_longest_iterator<Iters...> &other) const {
     962                 :             :     return !test(other, std::index_sequence_for<Iters...>{});
     963                 :             :   }
     964                 :             : };
     965                 :             : 
     966                 :             : template <typename... Args> class zip_longest_range {
     967                 :             : public:
     968                 :             :   using iterator =
     969                 :             :       zip_longest_iterator<decltype(adl_begin(std::declval<Args>()))...>;
     970                 :             :   using iterator_category = typename iterator::iterator_category;
     971                 :             :   using value_type = typename iterator::value_type;
     972                 :             :   using difference_type = typename iterator::difference_type;
     973                 :             :   using pointer = typename iterator::pointer;
     974                 :             :   using reference = typename iterator::reference;
     975                 :             : 
     976                 :             : private:
     977                 :             :   std::tuple<Args...> ts;
     978                 :             : 
     979                 :             :   template <size_t... Ns>
     980                 :             :   iterator begin_impl(std::index_sequence<Ns...>) const {
     981                 :             :     return iterator(std::make_pair(adl_begin(std::get<Ns>(ts)),
     982                 :             :                                    adl_end(std::get<Ns>(ts)))...);
     983                 :             :   }
     984                 :             : 
     985                 :             :   template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) const {
     986                 :             :     return iterator(std::make_pair(adl_end(std::get<Ns>(ts)),
     987                 :             :                                    adl_end(std::get<Ns>(ts)))...);
     988                 :             :   }
     989                 :             : 
     990                 :             : public:
     991                 :             :   zip_longest_range(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {}
     992                 :             : 
     993                 :             :   iterator begin() const {
     994                 :             :     return begin_impl(std::index_sequence_for<Args...>{});
     995                 :             :   }
     996                 :             :   iterator end() const { return end_impl(std::index_sequence_for<Args...>{}); }
     997                 :             : };
     998                 :             : } // namespace detail
     999                 :             : 
    1000                 :             : /// Iterate over two or more iterators at the same time. Iteration continues
    1001                 :             : /// until all iterators reach the end. The std::optional only contains a value
    1002                 :             : /// if the iterator has not reached the end.
    1003                 :             : template <typename T, typename U, typename... Args>
    1004                 :             : detail::zip_longest_range<T, U, Args...> zip_longest(T &&t, U &&u,
    1005                 :             :                                                      Args &&... args) {
    1006                 :             :   return detail::zip_longest_range<T, U, Args...>(
    1007                 :             :       std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
    1008                 :             : }
    1009                 :             : 
    1010                 :             : /// Iterator wrapper that concatenates sequences together.
    1011                 :             : ///
    1012                 :             : /// This can concatenate different iterators, even with different types, into
    1013                 :             : /// a single iterator provided the value types of all the concatenated
    1014                 :             : /// iterators expose `reference` and `pointer` types that can be converted to
    1015                 :             : /// `ValueT &` and `ValueT *` respectively. It doesn't support more
    1016                 :             : /// interesting/customized pointer or reference types.
    1017                 :             : ///
    1018                 :             : /// Currently this only supports forward or higher iterator categories as
    1019                 :             : /// inputs and always exposes a forward iterator interface.
    1020                 :             : template <typename ValueT, typename... IterTs>
    1021                 :             : class concat_iterator
    1022                 :             :     : public iterator_facade_base<concat_iterator<ValueT, IterTs...>,
    1023                 :             :                                   std::forward_iterator_tag, ValueT> {
    1024                 :             :   using BaseT = typename concat_iterator::iterator_facade_base;
    1025                 :             : 
    1026                 :             :   /// We store both the current and end iterators for each concatenated
    1027                 :             :   /// sequence in a tuple of pairs.
    1028                 :             :   ///
    1029                 :             :   /// Note that something like iterator_range seems nice at first here, but the
    1030                 :             :   /// range properties are of little benefit and end up getting in the way
    1031                 :             :   /// because we need to do mutation on the current iterators.
    1032                 :             :   std::tuple<IterTs...> Begins;
    1033                 :             :   std::tuple<IterTs...> Ends;
    1034                 :             : 
    1035                 :             :   /// Attempts to increment a specific iterator.
    1036                 :             :   ///
    1037                 :             :   /// Returns true if it was able to increment the iterator. Returns false if
    1038                 :             :   /// the iterator is already at the end iterator.
    1039                 :             :   template <size_t Index> bool incrementHelper() {
    1040                 :             :     auto &Begin = std::get<Index>(Begins);
    1041                 :             :     auto &End = std::get<Index>(Ends);
    1042                 :             :     if (Begin == End)
    1043                 :             :       return false;
    1044                 :             : 
    1045                 :             :     ++Begin;
    1046                 :             :     return true;
    1047                 :             :   }
    1048                 :             : 
    1049                 :             :   /// Increments the first non-end iterator.
    1050                 :             :   ///
    1051                 :             :   /// It is an error to call this with all iterators at the end.
    1052                 :             :   template <size_t... Ns> void increment(std::index_sequence<Ns...>) {
    1053                 :             :     // Build a sequence of functions to increment each iterator if possible.
    1054                 :             :     bool (concat_iterator::*IncrementHelperFns[])() = {
    1055                 :             :         &concat_iterator::incrementHelper<Ns>...};
    1056                 :             : 
    1057                 :             :     // Loop over them, and stop as soon as we succeed at incrementing one.
    1058                 :             :     for (auto &IncrementHelperFn : IncrementHelperFns)
    1059                 :             :       if ((this->*IncrementHelperFn)())
    1060                 :             :         return;
    1061                 :             : 
    1062                 :             :     llvm_unreachable("Attempted to increment an end concat iterator!");
    1063                 :             :   }
    1064                 :             : 
    1065                 :             :   /// Returns null if the specified iterator is at the end. Otherwise,
    1066                 :             :   /// dereferences the iterator and returns the address of the resulting
    1067                 :             :   /// reference.
    1068                 :             :   template <size_t Index> ValueT *getHelper() const {
    1069                 :             :     auto &Begin = std::get<Index>(Begins);
    1070                 :             :     auto &End = std::get<Index>(Ends);
    1071                 :             :     if (Begin == End)
    1072                 :             :       return nullptr;
    1073                 :             : 
    1074                 :             :     return &*Begin;
    1075                 :             :   }
    1076                 :             : 
    1077                 :             :   /// Finds the first non-end iterator, dereferences, and returns the resulting
    1078                 :             :   /// reference.
    1079                 :             :   ///
    1080                 :             :   /// It is an error to call this with all iterators at the end.
    1081                 :             :   template <size_t... Ns> ValueT &get(std::index_sequence<Ns...>) const {
    1082                 :             :     // Build a sequence of functions to get from iterator if possible.
    1083                 :             :     ValueT *(concat_iterator::*GetHelperFns[])() const = {
    1084                 :             :         &concat_iterator::getHelper<Ns>...};
    1085                 :             : 
    1086                 :             :     // Loop over them, and return the first result we find.
    1087                 :             :     for (auto &GetHelperFn : GetHelperFns)
    1088                 :             :       if (ValueT *P = (this->*GetHelperFn)())
    1089                 :             :         return *P;
    1090                 :             : 
    1091                 :             :     llvm_unreachable("Attempted to get a pointer from an end concat iterator!");
    1092                 :             :   }
    1093                 :             : 
    1094                 :             : public:
    1095                 :             :   /// Constructs an iterator from a sequence of ranges.
    1096                 :             :   ///
    1097                 :             :   /// We need the full range to know how to switch between each of the
    1098                 :             :   /// iterators.
    1099                 :             :   template <typename... RangeTs>
    1100                 :             :   explicit concat_iterator(RangeTs &&... Ranges)
    1101                 :             :       : Begins(std::begin(Ranges)...), Ends(std::end(Ranges)...) {}
    1102                 :             : 
    1103                 :             :   using BaseT::operator++;
    1104                 :             : 
    1105                 :             :   concat_iterator &operator++() {
    1106                 :             :     increment(std::index_sequence_for<IterTs...>());
    1107                 :             :     return *this;
    1108                 :             :   }
    1109                 :             : 
    1110                 :             :   ValueT &operator*() const {
    1111                 :             :     return get(std::index_sequence_for<IterTs...>());
    1112                 :             :   }
    1113                 :             : 
    1114                 :             :   bool operator==(const concat_iterator &RHS) const {
    1115                 :             :     return Begins == RHS.Begins && Ends == RHS.Ends;
    1116                 :             :   }
    1117                 :             : };
    1118                 :             : 
    1119                 :             : namespace detail {
    1120                 :             : 
    1121                 :             : /// Helper to store a sequence of ranges being concatenated and access them.
    1122                 :             : ///
    1123                 :             : /// This is designed to facilitate providing actual storage when temporaries
    1124                 :             : /// are passed into the constructor such that we can use it as part of range
    1125                 :             : /// based for loops.
    1126                 :             : template <typename ValueT, typename... RangeTs> class concat_range {
    1127                 :             : public:
    1128                 :             :   using iterator =
    1129                 :             :       concat_iterator<ValueT,
    1130                 :             :                       decltype(std::begin(std::declval<RangeTs &>()))...>;
    1131                 :             : 
    1132                 :             : private:
    1133                 :             :   std::tuple<RangeTs...> Ranges;
    1134                 :             : 
    1135                 :             :   template <size_t... Ns>
    1136                 :             :   iterator begin_impl(std::index_sequence<Ns...>) {
    1137                 :             :     return iterator(std::get<Ns>(Ranges)...);
    1138                 :             :   }
    1139                 :             :   template <size_t... Ns>
    1140                 :             :   iterator begin_impl(std::index_sequence<Ns...>) const {
    1141                 :             :     return iterator(std::get<Ns>(Ranges)...);
    1142                 :             :   }
    1143                 :             :   template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) {
    1144                 :             :     return iterator(make_range(std::end(std::get<Ns>(Ranges)),
    1145                 :             :                                std::end(std::get<Ns>(Ranges)))...);
    1146                 :             :   }
    1147                 :             :   template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) const {
    1148                 :             :     return iterator(make_range(std::end(std::get<Ns>(Ranges)),
    1149                 :             :                                std::end(std::get<Ns>(Ranges)))...);
    1150                 :             :   }
    1151                 :             : 
    1152                 :             : public:
    1153                 :             :   concat_range(RangeTs &&... Ranges)
    1154                 :             :       : Ranges(std::forward<RangeTs>(Ranges)...) {}
    1155                 :             : 
    1156                 :             :   iterator begin() {
    1157                 :             :     return begin_impl(std::index_sequence_for<RangeTs...>{});
    1158                 :             :   }
    1159                 :             :   iterator begin() const {
    1160                 :             :     return begin_impl(std::index_sequence_for<RangeTs...>{});
    1161                 :             :   }
    1162                 :             :   iterator end() {
    1163                 :             :     return end_impl(std::index_sequence_for<RangeTs...>{});
    1164                 :             :   }
    1165                 :             :   iterator end() const {
    1166                 :             :     return end_impl(std::index_sequence_for<RangeTs...>{});
    1167                 :             :   }
    1168                 :             : };
    1169                 :             : 
    1170                 :             : } // end namespace detail
    1171                 :             : 
    1172                 :             : /// Concatenated range across two or more ranges.
    1173                 :             : ///
    1174                 :             : /// The desired value type must be explicitly specified.
    1175                 :             : template <typename ValueT, typename... RangeTs>
    1176                 :             : detail::concat_range<ValueT, RangeTs...> concat(RangeTs &&... Ranges) {
    1177                 :             :   static_assert(sizeof...(RangeTs) > 1,
    1178                 :             :                 "Need more than one range to concatenate!");
    1179                 :             :   return detail::concat_range<ValueT, RangeTs...>(
    1180                 :             :       std::forward<RangeTs>(Ranges)...);
    1181                 :             : }
    1182                 :             : 
    1183                 :             : /// A utility class used to implement an iterator that contains some base object
    1184                 :             : /// and an index. The iterator moves the index but keeps the base constant.
    1185                 :             : template <typename DerivedT, typename BaseT, typename T,
    1186                 :             :           typename PointerT = T *, typename ReferenceT = T &>
    1187                 :             : class indexed_accessor_iterator
    1188                 :             :     : public llvm::iterator_facade_base<DerivedT,
    1189                 :             :                                         std::random_access_iterator_tag, T,
    1190                 :             :                                         std::ptrdiff_t, PointerT, ReferenceT> {
    1191                 :             : public:
    1192                 :             :   ptrdiff_t operator-(const indexed_accessor_iterator &rhs) const {
    1193                 :             :     assert(base == rhs.base && "incompatible iterators");
    1194                 :             :     return index - rhs.index;
    1195                 :             :   }
    1196                 :             :   bool operator==(const indexed_accessor_iterator &rhs) const {
    1197                 :             :     return base == rhs.base && index == rhs.index;
    1198                 :             :   }
    1199                 :             :   bool operator<(const indexed_accessor_iterator &rhs) const {
    1200                 :             :     assert(base == rhs.base && "incompatible iterators");
    1201                 :             :     return index < rhs.index;
    1202                 :             :   }
    1203                 :             : 
    1204                 :             :   DerivedT &operator+=(ptrdiff_t offset) {
    1205                 :             :     this->index += offset;
    1206                 :             :     return static_cast<DerivedT &>(*this);
    1207                 :             :   }
    1208                 :             :   DerivedT &operator-=(ptrdiff_t offset) {
    1209                 :             :     this->index -= offset;
    1210                 :             :     return static_cast<DerivedT &>(*this);
    1211                 :             :   }
    1212                 :             : 
    1213                 :             :   /// Returns the current index of the iterator.
    1214                 :             :   ptrdiff_t getIndex() const { return index; }
    1215                 :             : 
    1216                 :             :   /// Returns the current base of the iterator.
    1217                 :             :   const BaseT &getBase() const { return base; }
    1218                 :             : 
    1219                 :             : protected:
    1220                 :             :   indexed_accessor_iterator(BaseT base, ptrdiff_t index)
    1221                 :             :       : base(base), index(index) {}
    1222                 :             :   BaseT base;
    1223                 :             :   ptrdiff_t index;
    1224                 :             : };
    1225                 :             : 
    1226                 :             : namespace detail {
    1227                 :             : /// The class represents the base of a range of indexed_accessor_iterators. It
    1228                 :             : /// provides support for many different range functionalities, e.g.
    1229                 :             : /// drop_front/slice/etc.. Derived range classes must implement the following
    1230                 :             : /// static methods:
    1231                 :             : ///   * ReferenceT dereference_iterator(const BaseT &base, ptrdiff_t index)
    1232                 :             : ///     - Dereference an iterator pointing to the base object at the given
    1233                 :             : ///       index.
    1234                 :             : ///   * BaseT offset_base(const BaseT &base, ptrdiff_t index)
    1235                 :             : ///     - Return a new base that is offset from the provide base by 'index'
    1236                 :             : ///       elements.
    1237                 :             : template <typename DerivedT, typename BaseT, typename T,
    1238                 :             :           typename PointerT = T *, typename ReferenceT = T &>
    1239                 :             : class indexed_accessor_range_base {
    1240                 :             : public:
    1241                 :             :   using RangeBaseT = indexed_accessor_range_base;
    1242                 :             : 
    1243                 :             :   /// An iterator element of this range.
    1244                 :             :   class iterator : public indexed_accessor_iterator<iterator, BaseT, T,
    1245                 :             :                                                     PointerT, ReferenceT> {
    1246                 :             :   public:
    1247                 :             :     // Index into this iterator, invoking a static method on the derived type.
    1248                 :             :     ReferenceT operator*() const {
    1249                 :             :       return DerivedT::dereference_iterator(this->getBase(), this->getIndex());
    1250                 :             :     }
    1251                 :             : 
    1252                 :             :   private:
    1253                 :             :     iterator(BaseT owner, ptrdiff_t curIndex)
    1254                 :             :         : iterator::indexed_accessor_iterator(owner, curIndex) {}
    1255                 :             : 
    1256                 :             :     /// Allow access to the constructor.
    1257                 :             :     friend indexed_accessor_range_base<DerivedT, BaseT, T, PointerT,
    1258                 :             :                                        ReferenceT>;
    1259                 :             :   };
    1260                 :             : 
    1261                 :             :   indexed_accessor_range_base(iterator begin, iterator end)
    1262                 :             :       : base(offset_base(begin.getBase(), begin.getIndex())),
    1263                 :             :         count(end.getIndex() - begin.getIndex()) {}
    1264                 :             :   indexed_accessor_range_base(const iterator_range<iterator> &range)
    1265                 :             :       : indexed_accessor_range_base(range.begin(), range.end()) {}
    1266                 :             :   indexed_accessor_range_base(BaseT base, ptrdiff_t count)
    1267                 :             :       : base(base), count(count) {}
    1268                 :             : 
    1269                 :             :   iterator begin() const { return iterator(base, 0); }
    1270                 :             :   iterator end() const { return iterator(base, count); }
    1271                 :             :   ReferenceT operator[](size_t Index) const {
    1272                 :             :     assert(Index < size() && "invalid index for value range");
    1273                 :             :     return DerivedT::dereference_iterator(base, static_cast<ptrdiff_t>(Index));
    1274                 :             :   }
    1275                 :             :   ReferenceT front() const {
    1276                 :             :     assert(!empty() && "expected non-empty range");
    1277                 :             :     return (*this)[0];
    1278                 :             :   }
    1279                 :             :   ReferenceT back() const {
    1280                 :             :     assert(!empty() && "expected non-empty range");
    1281                 :             :     return (*this)[size() - 1];
    1282                 :             :   }
    1283                 :             : 
    1284                 :             :   /// Return the size of this range.
    1285                 :             :   size_t size() const { return count; }
    1286                 :             : 
    1287                 :             :   /// Return if the range is empty.
    1288                 :             :   bool empty() const { return size() == 0; }
    1289                 :             : 
    1290                 :             :   /// Drop the first N elements, and keep M elements.
    1291                 :             :   DerivedT slice(size_t n, size_t m) const {
    1292                 :             :     assert(n + m <= size() && "invalid size specifiers");
    1293                 :             :     return DerivedT(offset_base(base, n), m);
    1294                 :             :   }
    1295                 :             : 
    1296                 :             :   /// Drop the first n elements.
    1297                 :             :   DerivedT drop_front(size_t n = 1) const {
    1298                 :             :     assert(size() >= n && "Dropping more elements than exist");
    1299                 :             :     return slice(n, size() - n);
    1300                 :             :   }
    1301                 :             :   /// Drop the last n elements.
    1302                 :             :   DerivedT drop_back(size_t n = 1) const {
    1303                 :             :     assert(size() >= n && "Dropping more elements than exist");
    1304                 :             :     return DerivedT(base, size() - n);
    1305                 :             :   }
    1306                 :             : 
    1307                 :             :   /// Take the first n elements.
    1308                 :             :   DerivedT take_front(size_t n = 1) const {
    1309                 :             :     return n < size() ? drop_back(size() - n)
    1310                 :             :                       : static_cast<const DerivedT &>(*this);
    1311                 :             :   }
    1312                 :             : 
    1313                 :             :   /// Take the last n elements.
    1314                 :             :   DerivedT take_back(size_t n = 1) const {
    1315                 :             :     return n < size() ? drop_front(size() - n)
    1316                 :             :                       : static_cast<const DerivedT &>(*this);
    1317                 :             :   }
    1318                 :             : 
    1319                 :             :   /// Allow conversion to any type accepting an iterator_range.
    1320                 :             :   template <typename RangeT, typename = std::enable_if_t<std::is_constructible<
    1321                 :             :                                  RangeT, iterator_range<iterator>>::value>>
    1322                 :             :   operator RangeT() const {
    1323                 :             :     return RangeT(iterator_range<iterator>(*this));
    1324                 :             :   }
    1325                 :             : 
    1326                 :             :   /// Returns the base of this range.
    1327                 :             :   const BaseT &getBase() const { return base; }
    1328                 :             : 
    1329                 :             : private:
    1330                 :             :   /// Offset the given base by the given amount.
    1331                 :             :   static BaseT offset_base(const BaseT &base, size_t n) {
    1332                 :             :     return n == 0 ? base : DerivedT::offset_base(base, n);
    1333                 :             :   }
    1334                 :             : 
    1335                 :             : protected:
    1336                 :             :   indexed_accessor_range_base(const indexed_accessor_range_base &) = default;
    1337                 :             :   indexed_accessor_range_base(indexed_accessor_range_base &&) = default;
    1338                 :             :   indexed_accessor_range_base &
    1339                 :             :   operator=(const indexed_accessor_range_base &) = default;
    1340                 :             : 
    1341                 :             :   /// The base that owns the provided range of values.
    1342                 :             :   BaseT base;
    1343                 :             :   /// The size from the owning range.
    1344                 :             :   ptrdiff_t count;
    1345                 :             : };
    1346                 :             : /// Compare this range with another.
    1347                 :             : /// FIXME: Make me a member function instead of friend when it works in C++20.
    1348                 :             : template <typename OtherT, typename DerivedT, typename BaseT, typename T,
    1349                 :             :           typename PointerT, typename ReferenceT>
    1350                 :             : bool operator==(const indexed_accessor_range_base<DerivedT, BaseT, T, PointerT,
    1351                 :             :                                                   ReferenceT> &lhs,
    1352                 :             :                 const OtherT &rhs) {
    1353                 :             :   return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
    1354                 :             : }
    1355                 :             : 
    1356                 :             : template <typename OtherT, typename DerivedT, typename BaseT, typename T,
    1357                 :             :           typename PointerT, typename ReferenceT>
    1358                 :             : bool operator!=(const indexed_accessor_range_base<DerivedT, BaseT, T, PointerT,
    1359                 :             :                                                   ReferenceT> &lhs,
    1360                 :             :                 const OtherT &rhs) {
    1361                 :             :   return !(lhs == rhs);
    1362                 :             : }
    1363                 :             : } // end namespace detail
    1364                 :             : 
    1365                 :             : /// This class provides an implementation of a range of
    1366                 :             : /// indexed_accessor_iterators where the base is not indexable. Ranges with
    1367                 :             : /// bases that are offsetable should derive from indexed_accessor_range_base
    1368                 :             : /// instead. Derived range classes are expected to implement the following
    1369                 :             : /// static method:
    1370                 :             : ///   * ReferenceT dereference(const BaseT &base, ptrdiff_t index)
    1371                 :             : ///     - Dereference an iterator pointing to a parent base at the given index.
    1372                 :             : template <typename DerivedT, typename BaseT, typename T,
    1373                 :             :           typename PointerT = T *, typename ReferenceT = T &>
    1374                 :             : class indexed_accessor_range
    1375                 :             :     : public detail::indexed_accessor_range_base<
    1376                 :             :           DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT, ReferenceT> {
    1377                 :             : public:
    1378                 :             :   indexed_accessor_range(BaseT base, ptrdiff_t startIndex, ptrdiff_t count)
    1379                 :             :       : detail::indexed_accessor_range_base<
    1380                 :             :             DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT, ReferenceT>(
    1381                 :             :             std::make_pair(base, startIndex), count) {}
    1382                 :             :   using detail::indexed_accessor_range_base<
    1383                 :             :       DerivedT, std::pair<BaseT, ptrdiff_t>, T, PointerT,
    1384                 :             :       ReferenceT>::indexed_accessor_range_base;
    1385                 :             : 
    1386                 :             :   /// Returns the current base of the range.
    1387                 :             :   const BaseT &getBase() const { return this->base.first; }
    1388                 :             : 
    1389                 :             :   /// Returns the current start index of the range.
    1390                 :             :   ptrdiff_t getStartIndex() const { return this->base.second; }
    1391                 :             : 
    1392                 :             :   /// See `detail::indexed_accessor_range_base` for details.
    1393                 :             :   static std::pair<BaseT, ptrdiff_t>
    1394                 :             :   offset_base(const std::pair<BaseT, ptrdiff_t> &base, ptrdiff_t index) {
    1395                 :             :     // We encode the internal base as a pair of the derived base and a start
    1396                 :             :     // index into the derived base.
    1397                 :             :     return std::make_pair(base.first, base.second + index);
    1398                 :             :   }
    1399                 :             :   /// See `detail::indexed_accessor_range_base` for details.
    1400                 :             :   static ReferenceT
    1401                 :             :   dereference_iterator(const std::pair<BaseT, ptrdiff_t> &base,
    1402                 :             :                        ptrdiff_t index) {
    1403                 :             :     return DerivedT::dereference(base.first, base.second + index);
    1404                 :             :   }
    1405                 :             : };
    1406                 :             : 
    1407                 :             : namespace detail {
    1408                 :             : /// Return a reference to the first or second member of a reference. Otherwise,
    1409                 :             : /// return a copy of the member of a temporary.
    1410                 :             : ///
    1411                 :             : /// When passing a range whose iterators return values instead of references,
    1412                 :             : /// the reference must be dropped from `decltype((elt.first))`, which will
    1413                 :             : /// always be a reference, to avoid returning a reference to a temporary.
    1414                 :             : template <typename EltTy, typename FirstTy> class first_or_second_type {
    1415                 :             : public:
    1416                 :             :   using type = std::conditional_t<std::is_reference<EltTy>::value, FirstTy,
    1417                 :             :                                   std::remove_reference_t<FirstTy>>;
    1418                 :             : };
    1419                 :             : } // end namespace detail
    1420                 :             : 
    1421                 :             : /// Given a container of pairs, return a range over the first elements.
    1422                 :             : template <typename ContainerTy> auto make_first_range(ContainerTy &&c) {
    1423                 :             :   using EltTy = decltype((*std::begin(c)));
    1424                 :             :   return llvm::map_range(std::forward<ContainerTy>(c),
    1425                 :             :                          [](EltTy elt) -> typename detail::first_or_second_type<
    1426                 :             :                                            EltTy, decltype((elt.first))>::type {
    1427                 :             :                            return elt.first;
    1428                 :             :                          });
    1429                 :             : }
    1430                 :             : 
    1431                 :             : /// Given a container of pairs, return a range over the second elements.
    1432                 :             : template <typename ContainerTy> auto make_second_range(ContainerTy &&c) {
    1433                 :             :   using EltTy = decltype((*std::begin(c)));
    1434                 :             :   return llvm::map_range(
    1435                 :             :       std::forward<ContainerTy>(c),
    1436                 :             :       [](EltTy elt) ->
    1437                 :             :       typename detail::first_or_second_type<EltTy,
    1438                 :             :                                             decltype((elt.second))>::type {
    1439                 :             :         return elt.second;
    1440                 :             :       });
    1441                 :             : }
    1442                 :             : 
    1443                 :             : //===----------------------------------------------------------------------===//
    1444                 :             : //     Extra additions to <utility>
    1445                 :             : //===----------------------------------------------------------------------===//
    1446                 :             : 
    1447                 :             : /// Function object to check whether the first component of a container
    1448                 :             : /// supported by std::get (like std::pair and std::tuple) compares less than the
    1449                 :             : /// first component of another container.
    1450                 :             : struct less_first {
    1451                 :             :   template <typename T> bool operator()(const T &lhs, const T &rhs) const {
    1452                 :             :     return std::less<>()(std::get<0>(lhs), std::get<0>(rhs));
    1453                 :             :   }
    1454                 :             : };
    1455                 :             : 
    1456                 :             : /// Function object to check whether the second component of a container
    1457                 :             : /// supported by std::get (like std::pair and std::tuple) compares less than the
    1458                 :             : /// second component of another container.
    1459                 :             : struct less_second {
    1460                 :             :   template <typename T> bool operator()(const T &lhs, const T &rhs) const {
    1461                 :             :     return std::less<>()(std::get<1>(lhs), std::get<1>(rhs));
    1462                 :             :   }
    1463                 :             : };
    1464                 :             : 
    1465                 :             : /// \brief Function object to apply a binary function to the first component of
    1466                 :             : /// a std::pair.
    1467                 :             : template<typename FuncTy>
    1468                 :             : struct on_first {
    1469                 :             :   FuncTy func;
    1470                 :             : 
    1471                 :             :   template <typename T>
    1472                 :             :   decltype(auto) operator()(const T &lhs, const T &rhs) const {
    1473                 :             :     return func(lhs.first, rhs.first);
    1474                 :             :   }
    1475                 :             : };
    1476                 :             : 
    1477                 :             : /// Utility type to build an inheritance chain that makes it easy to rank
    1478                 :             : /// overload candidates.
    1479                 :             : template <int N> struct rank : rank<N - 1> {};
    1480                 :             : template <> struct rank<0> {};
    1481                 :             : 
    1482                 :             : namespace detail {
    1483                 :             : template <typename... Ts> struct Visitor;
    1484                 :             : 
    1485                 :             : template <typename HeadT, typename... TailTs>
    1486                 :             : struct Visitor<HeadT, TailTs...> : remove_cvref_t<HeadT>, Visitor<TailTs...> {
    1487                 :             :   explicit constexpr Visitor(HeadT &&Head, TailTs &&...Tail)
    1488                 :             :       : remove_cvref_t<HeadT>(std::forward<HeadT>(Head)),
    1489                 :             :         Visitor<TailTs...>(std::forward<TailTs>(Tail)...) {}
    1490                 :             :   using remove_cvref_t<HeadT>::operator();
    1491                 :             :   using Visitor<TailTs...>::operator();
    1492                 :             : };
    1493                 :             : 
    1494                 :             : template <typename HeadT> struct Visitor<HeadT> : remove_cvref_t<HeadT> {
    1495                 :             :   explicit constexpr Visitor(HeadT &&Head)
    1496                 :             :       : remove_cvref_t<HeadT>(std::forward<HeadT>(Head)) {}
    1497                 :             :   using remove_cvref_t<HeadT>::operator();
    1498                 :             : };
    1499                 :             : } // namespace detail
    1500                 :             : 
    1501                 :             : /// Returns an opaquely-typed Callable object whose operator() overload set is
    1502                 :             : /// the sum of the operator() overload sets of each CallableT in CallableTs.
    1503                 :             : ///
    1504                 :             : /// The type of the returned object derives from each CallableT in CallableTs.
    1505                 :             : /// The returned object is constructed by invoking the appropriate copy or move
    1506                 :             : /// constructor of each CallableT, as selected by overload resolution on the
    1507                 :             : /// corresponding argument to makeVisitor.
    1508                 :             : ///
    1509                 :             : /// Example:
    1510                 :             : ///
    1511                 :             : /// \code
    1512                 :             : /// auto visitor = makeVisitor([](auto) { return "unhandled type"; },
    1513                 :             : ///                            [](int i) { return "int"; },
    1514                 :             : ///                            [](std::string s) { return "str"; });
    1515                 :             : /// auto a = visitor(42);    // `a` is now "int".
    1516                 :             : /// auto b = visitor("foo"); // `b` is now "str".
    1517                 :             : /// auto c = visitor(3.14f); // `c` is now "unhandled type".
    1518                 :             : /// \endcode
    1519                 :             : ///
    1520                 :             : /// Example of making a visitor with a lambda which captures a move-only type:
    1521                 :             : ///
    1522                 :             : /// \code
    1523                 :             : /// std::unique_ptr<FooHandler> FH = /* ... */;
    1524                 :             : /// auto visitor = makeVisitor(
    1525                 :             : ///     [FH{std::move(FH)}](Foo F) { return FH->handle(F); },
    1526                 :             : ///     [](int i) { return i; },
    1527                 :             : ///     [](std::string s) { return atoi(s); });
    1528                 :             : /// \endcode
    1529                 :             : template <typename... CallableTs>
    1530                 :             : constexpr decltype(auto) makeVisitor(CallableTs &&...Callables) {
    1531                 :             :   return detail::Visitor<CallableTs...>(std::forward<CallableTs>(Callables)...);
    1532                 :             : }
    1533                 :             : 
    1534                 :             : //===----------------------------------------------------------------------===//
    1535                 :             : //     Extra additions to <algorithm>
    1536                 :             : //===----------------------------------------------------------------------===//
    1537                 :             : 
    1538                 :             : // We have a copy here so that LLVM behaves the same when using different
    1539                 :             : // standard libraries.
    1540                 :             : template <class Iterator, class RNG>
    1541                 :             : void shuffle(Iterator first, Iterator last, RNG &&g) {
    1542                 :             :   // It would be better to use a std::uniform_int_distribution,
    1543                 :             :   // but that would be stdlib dependent.
    1544                 :             :   typedef
    1545                 :             :       typename std::iterator_traits<Iterator>::difference_type difference_type;
    1546                 :             :   for (auto size = last - first; size > 1; ++first, (void)--size) {
    1547                 :             :     difference_type offset = g() % size;
    1548                 :             :     // Avoid self-assignment due to incorrect assertions in libstdc++
    1549                 :             :     // containers (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85828).
    1550                 :             :     if (offset != difference_type(0))
    1551                 :             :       std::iter_swap(first, first + offset);
    1552                 :             :   }
    1553                 :             : }
    1554                 :             : 
    1555                 :             : /// Adapt std::less<T> for array_pod_sort.
    1556                 :             : template<typename T>
    1557                 :             : inline int array_pod_sort_comparator(const void *P1, const void *P2) {
    1558                 :             :   if (std::less<T>()(*reinterpret_cast<const T*>(P1),
    1559                 :             :                      *reinterpret_cast<const T*>(P2)))
    1560                 :             :     return -1;
    1561                 :             :   if (std::less<T>()(*reinterpret_cast<const T*>(P2),
    1562                 :             :                      *reinterpret_cast<const T*>(P1)))
    1563                 :             :     return 1;
    1564                 :             :   return 0;
    1565                 :             : }
    1566                 :             : 
    1567                 :             : /// get_array_pod_sort_comparator - This is an internal helper function used to
    1568                 :             : /// get type deduction of T right.
    1569                 :             : template<typename T>
    1570                 :             : inline int (*get_array_pod_sort_comparator(const T &))
    1571                 :             :              (const void*, const void*) {
    1572                 :             :   return array_pod_sort_comparator<T>;
    1573                 :             : }
    1574                 :             : 
    1575                 :             : #ifdef EXPENSIVE_CHECKS
    1576                 :             : namespace detail {
    1577                 :             : 
    1578                 :             : inline unsigned presortShuffleEntropy() {
    1579                 :             :   static unsigned Result(std::random_device{}());
    1580                 :             :   return Result;
    1581                 :             : }
    1582                 :             : 
    1583                 :             : template <class IteratorTy>
    1584                 :             : inline void presortShuffle(IteratorTy Start, IteratorTy End) {
    1585                 :             :   std::mt19937 Generator(presortShuffleEntropy());
    1586                 :             :   llvm::shuffle(Start, End, Generator);
    1587                 :             : }
    1588                 :             : 
    1589                 :             : } // end namespace detail
    1590                 :             : #endif
    1591                 :             : 
    1592                 :             : /// array_pod_sort - This sorts an array with the specified start and end
    1593                 :             : /// extent.  This is just like std::sort, except that it calls qsort instead of
    1594                 :             : /// using an inlined template.  qsort is slightly slower than std::sort, but
    1595                 :             : /// most sorts are not performance critical in LLVM and std::sort has to be
    1596                 :             : /// template instantiated for each type, leading to significant measured code
    1597                 :             : /// bloat.  This function should generally be used instead of std::sort where
    1598                 :             : /// possible.
    1599                 :             : ///
    1600                 :             : /// This function assumes that you have simple POD-like types that can be
    1601                 :             : /// compared with std::less and can be moved with memcpy.  If this isn't true,
    1602                 :             : /// you should use std::sort.
    1603                 :             : ///
    1604                 :             : /// NOTE: If qsort_r were portable, we could allow a custom comparator and
    1605                 :             : /// default to std::less.
    1606                 :             : template<class IteratorTy>
    1607                 :             : inline void array_pod_sort(IteratorTy Start, IteratorTy End) {
    1608                 :             :   // Don't inefficiently call qsort with one element or trigger undefined
    1609                 :             :   // behavior with an empty sequence.
    1610                 :             :   auto NElts = End - Start;
    1611                 :             :   if (NElts <= 1) return;
    1612                 :             : #ifdef EXPENSIVE_CHECKS
    1613                 :             :   detail::presortShuffle<IteratorTy>(Start, End);
    1614                 :             : #endif
    1615                 :             :   qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start));
    1616                 :             : }
    1617                 :             : 
    1618                 :             : template <class IteratorTy>
    1619                 :             : inline void array_pod_sort(
    1620                 :             :     IteratorTy Start, IteratorTy End,
    1621                 :             :     int (*Compare)(
    1622                 :             :         const typename std::iterator_traits<IteratorTy>::value_type *,
    1623                 :             :         const typename std::iterator_traits<IteratorTy>::value_type *)) {
    1624                 :             :   // Don't inefficiently call qsort with one element or trigger undefined
    1625                 :             :   // behavior with an empty sequence.
    1626                 :             :   auto NElts = End - Start;
    1627                 :             :   if (NElts <= 1) return;
    1628                 :             : #ifdef EXPENSIVE_CHECKS
    1629                 :             :   detail::presortShuffle<IteratorTy>(Start, End);
    1630                 :             : #endif
    1631                 :             :   qsort(&*Start, NElts, sizeof(*Start),
    1632                 :             :         reinterpret_cast<int (*)(const void *, const void *)>(Compare));
    1633                 :             : }
    1634                 :             : 
    1635                 :             : namespace detail {
    1636                 :             : template <typename T>
    1637                 :             : // We can use qsort if the iterator type is a pointer and the underlying value
    1638                 :             : // is trivially copyable.
    1639                 :             : using sort_trivially_copyable = std::conjunction<
    1640                 :             :     std::is_pointer<T>,
    1641                 :             :     std::is_trivially_copyable<typename std::iterator_traits<T>::value_type>>;
    1642                 :             : } // namespace detail
    1643                 :             : 
    1644                 :             : // Provide wrappers to std::sort which shuffle the elements before sorting
    1645                 :             : // to help uncover non-deterministic behavior (PR35135).
    1646                 :             : template <typename IteratorTy>
    1647                 :             : inline void sort(IteratorTy Start, IteratorTy End) {
    1648                 :             :   if constexpr (detail::sort_trivially_copyable<IteratorTy>::value) {
    1649                 :             :     // Forward trivially copyable types to array_pod_sort. This avoids a large
    1650                 :             :     // amount of code bloat for a minor performance hit.
    1651                 :             :     array_pod_sort(Start, End);
    1652                 :             :   } else {
    1653                 :             : #ifdef EXPENSIVE_CHECKS
    1654                 :             :     detail::presortShuffle<IteratorTy>(Start, End);
    1655                 :             : #endif
    1656                 :             :     std::sort(Start, End);
    1657                 :             :   }
    1658                 :             : }
    1659                 :             : 
    1660                 :             : template <typename Container> inline void sort(Container &&C) {
    1661                 :             :   llvm::sort(adl_begin(C), adl_end(C));
    1662                 :             : }
    1663                 :             : 
    1664                 :             : template <typename IteratorTy, typename Compare>
    1665                 :             : inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) {
    1666                 :             : #ifdef EXPENSIVE_CHECKS
    1667                 :             :   detail::presortShuffle<IteratorTy>(Start, End);
    1668                 :             : #endif
    1669                 :             :   std::sort(Start, End, Comp);
    1670                 :             : }
    1671                 :             : 
    1672                 :             : template <typename Container, typename Compare>
    1673                 :             : inline void sort(Container &&C, Compare Comp) {
    1674                 :             :   llvm::sort(adl_begin(C), adl_end(C), Comp);
    1675                 :             : }
    1676                 :             : 
    1677                 :             : /// Get the size of a range. This is a wrapper function around std::distance
    1678                 :             : /// which is only enabled when the operation is O(1).
    1679                 :             : template <typename R>
    1680                 :             : auto size(R &&Range,
    1681                 :             :           std::enable_if_t<
    1682                 :             :               std::is_base_of<std::random_access_iterator_tag,
    1683                 :             :                               typename std::iterator_traits<decltype(
    1684                 :             :                                   Range.begin())>::iterator_category>::value,
    1685                 :             :               void> * = nullptr) {
    1686                 :             :   return std::distance(Range.begin(), Range.end());
    1687                 :             : }
    1688                 :             : 
    1689                 :             : namespace detail {
    1690                 :             : template <typename Range>
    1691                 :             : using check_has_free_function_size =
    1692                 :             :     decltype(adl_size(std::declval<Range &>()));
    1693                 :             : 
    1694                 :             : template <typename Range>
    1695                 :             : static constexpr bool HasFreeFunctionSize =
    1696                 :             :     is_detected<check_has_free_function_size, Range>::value;
    1697                 :             : } // namespace detail
    1698                 :             : 
    1699                 :             : /// Returns the size of the \p Range, i.e., the number of elements. This
    1700                 :             : /// implementation takes inspiration from `std::ranges::size` from C++20 and
    1701                 :             : /// delegates the size check to `adl_size` or `std::distance`, in this order of
    1702                 :             : /// preference. Unlike `llvm::size`, this function does *not* guarantee O(1)
    1703                 :             : /// running time, and is intended to be used in generic code that does not know
    1704                 :             : /// the exact range type.
    1705                 :             : template <typename R> constexpr size_t range_size(R &&Range) {
    1706                 :             :   if constexpr (detail::HasFreeFunctionSize<R>)
    1707                 :             :     return adl_size(Range);
    1708                 :             :   else
    1709                 :             :     return static_cast<size_t>(std::distance(adl_begin(Range), adl_end(Range)));
    1710                 :             : }
    1711                 :             : 
    1712                 :             : /// Provide wrappers to std::for_each which take ranges instead of having to
    1713                 :             : /// pass begin/end explicitly.
    1714                 :             : template <typename R, typename UnaryFunction>
    1715                 :             : UnaryFunction for_each(R &&Range, UnaryFunction F) {
    1716                 :             :   return std::for_each(adl_begin(Range), adl_end(Range), F);
    1717                 :             : }
    1718                 :             : 
    1719                 :             : /// Provide wrappers to std::all_of which take ranges instead of having to pass
    1720                 :             : /// begin/end explicitly.
    1721                 :             : template <typename R, typename UnaryPredicate>
    1722                 :             : bool all_of(R &&Range, UnaryPredicate P) {
    1723                 :             :   return std::all_of(adl_begin(Range), adl_end(Range), P);
    1724                 :             : }
    1725                 :             : 
    1726                 :             : /// Provide wrappers to std::any_of which take ranges instead of having to pass
    1727                 :             : /// begin/end explicitly.
    1728                 :             : template <typename R, typename UnaryPredicate>
    1729                 :             : bool any_of(R &&Range, UnaryPredicate P) {
    1730                 :             :   return std::any_of(adl_begin(Range), adl_end(Range), P);
    1731                 :             : }
    1732                 :             : 
    1733                 :             : /// Provide wrappers to std::none_of which take ranges instead of having to pass
    1734                 :             : /// begin/end explicitly.
    1735                 :             : template <typename R, typename UnaryPredicate>
    1736                 :             : bool none_of(R &&Range, UnaryPredicate P) {
    1737                 :             :   return std::none_of(adl_begin(Range), adl_end(Range), P);
    1738                 :             : }
    1739                 :             : 
    1740                 :             : /// Provide wrappers to std::find which take ranges instead of having to pass
    1741                 :             : /// begin/end explicitly.
    1742                 :             : template <typename R, typename T> auto find(R &&Range, const T &Val) {
    1743                 :             :   return std::find(adl_begin(Range), adl_end(Range), Val);
    1744                 :             : }
    1745                 :             : 
    1746                 :             : /// Provide wrappers to std::find_if which take ranges instead of having to pass
    1747                 :             : /// begin/end explicitly.
    1748                 :             : template <typename R, typename UnaryPredicate>
    1749                 :             : auto find_if(R &&Range, UnaryPredicate P) {
    1750                 :             :   return std::find_if(adl_begin(Range), adl_end(Range), P);
    1751                 :             : }
    1752                 :             : 
    1753                 :             : template <typename R, typename UnaryPredicate>
    1754                 :             : auto find_if_not(R &&Range, UnaryPredicate P) {
    1755                 :             :   return std::find_if_not(adl_begin(Range), adl_end(Range), P);
    1756                 :             : }
    1757                 :             : 
    1758                 :             : /// Provide wrappers to std::remove_if which take ranges instead of having to
    1759                 :             : /// pass begin/end explicitly.
    1760                 :             : template <typename R, typename UnaryPredicate>
    1761                 :             : auto remove_if(R &&Range, UnaryPredicate P) {
    1762                 :             :   return std::remove_if(adl_begin(Range), adl_end(Range), P);
    1763                 :             : }
    1764                 :             : 
    1765                 :             : /// Provide wrappers to std::copy_if which take ranges instead of having to
    1766                 :             : /// pass begin/end explicitly.
    1767                 :             : template <typename R, typename OutputIt, typename UnaryPredicate>
    1768                 :             : OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P) {
    1769                 :             :   return std::copy_if(adl_begin(Range), adl_end(Range), Out, P);
    1770                 :             : }
    1771                 :             : 
    1772                 :             : /// Return the single value in \p Range that satisfies
    1773                 :             : /// \p P(<member of \p Range> *, AllowRepeats)->T * returning nullptr
    1774                 :             : /// when no values or multiple values were found.
    1775                 :             : /// When \p AllowRepeats is true, multiple values that compare equal
    1776                 :             : /// are allowed.
    1777                 :             : template <typename T, typename R, typename Predicate>
    1778                 :             : T *find_singleton(R &&Range, Predicate P, bool AllowRepeats = false) {
    1779                 :             :   T *RC = nullptr;
    1780                 :             :   for (auto &&A : Range) {
    1781                 :             :     if (T *PRC = P(A, AllowRepeats)) {
    1782                 :             :       if (RC) {
    1783                 :             :         if (!AllowRepeats || PRC != RC)
    1784                 :             :           return nullptr;
    1785                 :             :       } else
    1786                 :             :         RC = PRC;
    1787                 :             :     }
    1788                 :             :   }
    1789                 :             :   return RC;
    1790                 :             : }
    1791                 :             : 
    1792                 :             : /// Return a pair consisting of the single value in \p Range that satisfies
    1793                 :             : /// \p P(<member of \p Range> *, AllowRepeats)->std::pair<T*, bool> returning
    1794                 :             : /// nullptr when no values or multiple values were found, and a bool indicating
    1795                 :             : /// whether multiple values were found to cause the nullptr.
    1796                 :             : /// When \p AllowRepeats is true, multiple values that compare equal are
    1797                 :             : /// allowed.  The predicate \p P returns a pair<T *, bool> where T is the
    1798                 :             : /// singleton while the bool indicates whether multiples have already been
    1799                 :             : /// found.  It is expected that first will be nullptr when second is true.
    1800                 :             : /// This allows using find_singleton_nested within the predicate \P.
    1801                 :             : template <typename T, typename R, typename Predicate>
    1802                 :             : std::pair<T *, bool> find_singleton_nested(R &&Range, Predicate P,
    1803                 :             :                                            bool AllowRepeats = false) {
    1804                 :             :   T *RC = nullptr;
    1805                 :             :   for (auto *A : Range) {
    1806                 :             :     std::pair<T *, bool> PRC = P(A, AllowRepeats);
    1807                 :             :     if (PRC.second) {
    1808                 :             :       assert(PRC.first == nullptr &&
    1809                 :             :              "Inconsistent return values in find_singleton_nested.");
    1810                 :             :       return PRC;
    1811                 :             :     }
    1812                 :             :     if (PRC.first) {
    1813                 :             :       if (RC) {
    1814                 :             :         if (!AllowRepeats || PRC.first != RC)
    1815                 :             :           return {nullptr, true};
    1816                 :             :       } else
    1817                 :             :         RC = PRC.first;
    1818                 :             :     }
    1819                 :             :   }
    1820                 :             :   return {RC, false};
    1821                 :             : }
    1822                 :             : 
    1823                 :             : template <typename R, typename OutputIt>
    1824                 :             : OutputIt copy(R &&Range, OutputIt Out) {
    1825                 :             :   return std::copy(adl_begin(Range), adl_end(Range), Out);
    1826                 :             : }
    1827                 :             : 
    1828                 :             : /// Provide wrappers to std::replace_copy_if which take ranges instead of having
    1829                 :             : /// to pass begin/end explicitly.
    1830                 :             : template <typename R, typename OutputIt, typename UnaryPredicate, typename T>
    1831                 :             : OutputIt replace_copy_if(R &&Range, OutputIt Out, UnaryPredicate P,
    1832                 :             :                          const T &NewValue) {
    1833                 :             :   return std::replace_copy_if(adl_begin(Range), adl_end(Range), Out, P,
    1834                 :             :                               NewValue);
    1835                 :             : }
    1836                 :             : 
    1837                 :             : /// Provide wrappers to std::replace_copy which take ranges instead of having to
    1838                 :             : /// pass begin/end explicitly.
    1839                 :             : template <typename R, typename OutputIt, typename T>
    1840                 :             : OutputIt replace_copy(R &&Range, OutputIt Out, const T &OldValue,
    1841                 :             :                       const T &NewValue) {
    1842                 :             :   return std::replace_copy(adl_begin(Range), adl_end(Range), Out, OldValue,
    1843                 :             :                            NewValue);
    1844                 :             : }
    1845                 :             : 
    1846                 :             : /// Provide wrappers to std::move which take ranges instead of having to
    1847                 :             : /// pass begin/end explicitly.
    1848                 :             : template <typename R, typename OutputIt>
    1849                 :             : OutputIt move(R &&Range, OutputIt Out) {
    1850                 :             :   return std::move(adl_begin(Range), adl_end(Range), Out);
    1851                 :             : }
    1852                 :             : 
    1853                 :             : namespace detail {
    1854                 :             : template <typename Range, typename Element>
    1855                 :             : using check_has_member_contains_t =
    1856                 :             :     decltype(std::declval<Range &>().contains(std::declval<const Element &>()));
    1857                 :             : 
    1858                 :             : template <typename Range, typename Element>
    1859                 :             : static constexpr bool HasMemberContains =
    1860                 :             :     is_detected<check_has_member_contains_t, Range, Element>::value;
    1861                 :             : 
    1862                 :             : template <typename Range, typename Element>
    1863                 :             : using check_has_member_find_t =
    1864                 :             :     decltype(std::declval<Range &>().find(std::declval<const Element &>()) !=
    1865                 :             :              std::declval<Range &>().end());
    1866                 :             : 
    1867                 :             : template <typename Range, typename Element>
    1868                 :             : static constexpr bool HasMemberFind =
    1869                 :             :     is_detected<check_has_member_find_t, Range, Element>::value;
    1870                 :             : 
    1871                 :             : } // namespace detail
    1872                 :             : 
    1873                 :             : /// Returns true if \p Element is found in \p Range. Delegates the check to
    1874                 :             : /// either `.contains(Element)`, `.find(Element)`, or `std::find`, in this
    1875                 :             : /// order of preference. This is intended as the canonical way to check if an
    1876                 :             : /// element exists in a range in generic code or range type that does not
    1877                 :             : /// expose a `.contains(Element)` member.
    1878                 :             : template <typename R, typename E>
    1879                 :             : bool is_contained(R &&Range, const E &Element) {
    1880                 :             :   if constexpr (detail::HasMemberContains<R, E>)
    1881                 :             :     return Range.contains(Element);
    1882                 :             :   else if constexpr (detail::HasMemberFind<R, E>)
    1883                 :             :     return Range.find(Element) != Range.end();
    1884                 :             :   else
    1885                 :             :     return std::find(adl_begin(Range), adl_end(Range), Element) !=
    1886                 :             :            adl_end(Range);
    1887                 :             : }
    1888                 :             : 
    1889                 :             : /// Returns true iff \p Element exists in \p Set. This overload takes \p Set as
    1890                 :             : /// an initializer list and is `constexpr`-friendly.
    1891                 :             : template <typename T, typename E>
    1892                 :             : constexpr bool is_contained(std::initializer_list<T> Set, const E &Element) {
    1893                 :             :   // TODO: Use std::find when we switch to C++20.
    1894                 :             :   for (const T &V : Set)
    1895                 :             :     if (V == Element)
    1896                 :             :       return true;
    1897                 :             :   return false;
    1898                 :             : }
    1899                 :             : 
    1900                 :             : /// Wrapper function around std::is_sorted to check if elements in a range \p R
    1901                 :             : /// are sorted with respect to a comparator \p C.
    1902                 :             : template <typename R, typename Compare> bool is_sorted(R &&Range, Compare C) {
    1903                 :             :   return std::is_sorted(adl_begin(Range), adl_end(Range), C);
    1904                 :             : }
    1905                 :             : 
    1906                 :             : /// Wrapper function around std::is_sorted to check if elements in a range \p R
    1907                 :             : /// are sorted in non-descending order.
    1908                 :             : template <typename R> bool is_sorted(R &&Range) {
    1909                 :             :   return std::is_sorted(adl_begin(Range), adl_end(Range));
    1910                 :             : }
    1911                 :             : 
    1912                 :             : /// Wrapper function around std::count to count the number of times an element
    1913                 :             : /// \p Element occurs in the given range \p Range.
    1914                 :             : template <typename R, typename E> auto count(R &&Range, const E &Element) {
    1915                 :             :   return std::count(adl_begin(Range), adl_end(Range), Element);
    1916                 :             : }
    1917                 :             : 
    1918                 :             : /// Wrapper function around std::count_if to count the number of times an
    1919                 :             : /// element satisfying a given predicate occurs in a range.
    1920                 :             : template <typename R, typename UnaryPredicate>
    1921                 :             : auto count_if(R &&Range, UnaryPredicate P) {
    1922                 :             :   return std::count_if(adl_begin(Range), adl_end(Range), P);
    1923                 :             : }
    1924                 :             : 
    1925                 :             : /// Wrapper function around std::transform to apply a function to a range and
    1926                 :             : /// store the result elsewhere.
    1927                 :             : template <typename R, typename OutputIt, typename UnaryFunction>
    1928                 :             : OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F) {
    1929                 :             :   return std::transform(adl_begin(Range), adl_end(Range), d_first, F);
    1930                 :             : }
    1931                 :             : 
    1932                 :             : /// Provide wrappers to std::partition which take ranges instead of having to
    1933                 :             : /// pass begin/end explicitly.
    1934                 :             : template <typename R, typename UnaryPredicate>
    1935                 :             : auto partition(R &&Range, UnaryPredicate P) {
    1936                 :             :   return std::partition(adl_begin(Range), adl_end(Range), P);
    1937                 :             : }
    1938                 :             : 
    1939                 :             : /// Provide wrappers to std::binary_search which take ranges instead of having
    1940                 :             : /// to pass begin/end explicitly.
    1941                 :             : template <typename R, typename T> auto binary_search(R &&Range, T &&Value) {
    1942                 :             :   return std::binary_search(adl_begin(Range), adl_end(Range),
    1943                 :             :                             std::forward<T>(Value));
    1944                 :             : }
    1945                 :             : 
    1946                 :             : template <typename R, typename T, typename Compare>
    1947                 :             : auto binary_search(R &&Range, T &&Value, Compare C) {
    1948                 :             :   return std::binary_search(adl_begin(Range), adl_end(Range),
    1949                 :             :                             std::forward<T>(Value), C);
    1950                 :             : }
    1951                 :             : 
    1952                 :             : /// Provide wrappers to std::lower_bound which take ranges instead of having to
    1953                 :             : /// pass begin/end explicitly.
    1954                 :             : template <typename R, typename T> auto lower_bound(R &&Range, T &&Value) {
    1955                 :             :   return std::lower_bound(adl_begin(Range), adl_end(Range),
    1956                 :             :                           std::forward<T>(Value));
    1957                 :             : }
    1958                 :             : 
    1959                 :             : template <typename R, typename T, typename Compare>
    1960                 :             : auto lower_bound(R &&Range, T &&Value, Compare C) {
    1961                 :             :   return std::lower_bound(adl_begin(Range), adl_end(Range),
    1962                 :             :                           std::forward<T>(Value), C);
    1963                 :             : }
    1964                 :             : 
    1965                 :             : /// Provide wrappers to std::upper_bound which take ranges instead of having to
    1966                 :             : /// pass begin/end explicitly.
    1967                 :             : template <typename R, typename T> auto upper_bound(R &&Range, T &&Value) {
    1968                 :             :   return std::upper_bound(adl_begin(Range), adl_end(Range),
    1969                 :             :                           std::forward<T>(Value));
    1970                 :             : }
    1971                 :             : 
    1972                 :             : template <typename R, typename T, typename Compare>
    1973                 :             : auto upper_bound(R &&Range, T &&Value, Compare C) {
    1974                 :             :   return std::upper_bound(adl_begin(Range), adl_end(Range),
    1975                 :             :                           std::forward<T>(Value), C);
    1976                 :             : }
    1977                 :             : 
    1978                 :             : template <typename R> auto min_element(R &&Range) {
    1979                 :             :   return std::min_element(adl_begin(Range), adl_end(Range));
    1980                 :             : }
    1981                 :             : 
    1982                 :             : template <typename R, typename Compare> auto min_element(R &&Range, Compare C) {
    1983                 :             :   return std::min_element(adl_begin(Range), adl_end(Range), C);
    1984                 :             : }
    1985                 :             : 
    1986                 :             : template <typename R> auto max_element(R &&Range) {
    1987                 :             :   return std::max_element(adl_begin(Range), adl_end(Range));
    1988                 :             : }
    1989                 :             : 
    1990                 :             : template <typename R, typename Compare> auto max_element(R &&Range, Compare C) {
    1991                 :             :   return std::max_element(adl_begin(Range), adl_end(Range), C);
    1992                 :             : }
    1993                 :             : 
    1994                 :             : template <typename R>
    1995                 :             : void stable_sort(R &&Range) {
    1996                 :             :   std::stable_sort(adl_begin(Range), adl_end(Range));
    1997                 :             : }
    1998                 :             : 
    1999                 :             : template <typename R, typename Compare>
    2000                 :             : void stable_sort(R &&Range, Compare C) {
    2001                 :             :   std::stable_sort(adl_begin(Range), adl_end(Range), C);
    2002                 :             : }
    2003                 :             : 
    2004                 :             : /// Binary search for the first iterator in a range where a predicate is false.
    2005                 :             : /// Requires that C is always true below some limit, and always false above it.
    2006                 :             : template <typename R, typename Predicate,
    2007                 :             :           typename Val = decltype(*adl_begin(std::declval<R>()))>
    2008                 :             : auto partition_point(R &&Range, Predicate P) {
    2009                 :             :   return std::partition_point(adl_begin(Range), adl_end(Range), P);
    2010                 :             : }
    2011                 :             : 
    2012                 :             : template<typename Range, typename Predicate>
    2013                 :             : auto unique(Range &&R, Predicate P) {
    2014                 :             :   return std::unique(adl_begin(R), adl_end(R), P);
    2015                 :             : }
    2016                 :             : 
    2017                 :             : /// Wrapper function around std::unique to allow calling unique on a
    2018                 :             : /// container without having to specify the begin/end iterators.
    2019                 :             : template <typename Range> auto unique(Range &&R) {
    2020                 :             :   return std::unique(adl_begin(R), adl_end(R));
    2021                 :             : }
    2022                 :             : 
    2023                 :             : /// Wrapper function around std::equal to detect if pair-wise elements between
    2024                 :             : /// two ranges are the same.
    2025                 :             : template <typename L, typename R> bool equal(L &&LRange, R &&RRange) {
    2026                 :             :   return std::equal(adl_begin(LRange), adl_end(LRange), adl_begin(RRange),
    2027                 :             :                     adl_end(RRange));
    2028                 :             : }
    2029                 :             : 
    2030                 :             : template <typename L, typename R, typename BinaryPredicate>
    2031                 :             : bool equal(L &&LRange, R &&RRange, BinaryPredicate P) {
    2032                 :             :   return std::equal(adl_begin(LRange), adl_end(LRange), adl_begin(RRange),
    2033                 :             :                     adl_end(RRange), P);
    2034                 :             : }
    2035                 :             : 
    2036                 :             : /// Returns true if all elements in Range are equal or when the Range is empty.
    2037                 :             : template <typename R> bool all_equal(R &&Range) {
    2038                 :             :   auto Begin = adl_begin(Range);
    2039                 :             :   auto End = adl_end(Range);
    2040                 :             :   return Begin == End || std::equal(Begin + 1, End, Begin);
    2041                 :             : }
    2042                 :             : 
    2043                 :             : /// Returns true if all Values in the initializer lists are equal or the list
    2044                 :             : // is empty.
    2045                 :             : template <typename T> bool all_equal(std::initializer_list<T> Values) {
    2046                 :             :   return all_equal<std::initializer_list<T>>(std::move(Values));
    2047                 :             : }
    2048                 :             : 
    2049                 :             : /// Provide a container algorithm similar to C++ Library Fundamentals v2's
    2050                 :             : /// `erase_if` which is equivalent to:
    2051                 :             : ///
    2052                 :             : ///   C.erase(remove_if(C, pred), C.end());
    2053                 :             : ///
    2054                 :             : /// This version works for any container with an erase method call accepting
    2055                 :             : /// two iterators.
    2056                 :             : template <typename Container, typename UnaryPredicate>
    2057                 :             : void erase_if(Container &C, UnaryPredicate P) {
    2058                 :             :   C.erase(remove_if(C, P), C.end());
    2059                 :             : }
    2060                 :             : 
    2061                 :             : /// Wrapper function to remove a value from a container:
    2062                 :             : ///
    2063                 :             : /// C.erase(remove(C.begin(), C.end(), V), C.end());
    2064                 :             : template <typename Container, typename ValueType>
    2065                 :             : void erase(Container &C, ValueType V) {
    2066                 :             :   C.erase(std::remove(C.begin(), C.end(), V), C.end());
    2067                 :             : }
    2068                 :             : 
    2069                 :             : /// Wrapper function to append range `R` to container `C`.
    2070                 :             : ///
    2071                 :             : /// C.insert(C.end(), R.begin(), R.end());
    2072                 :             : template <typename Container, typename Range>
    2073                 :             : void append_range(Container &C, Range &&R) {
    2074                 :             :   C.insert(C.end(), adl_begin(R), adl_end(R));
    2075                 :             : }
    2076                 :             : 
    2077                 :             : /// Appends all `Values` to container `C`.
    2078                 :             : template <typename Container, typename... Args>
    2079                 :             : void append_values(Container &C, Args &&...Values) {
    2080                 :             :   C.reserve(range_size(C) + sizeof...(Args));
    2081                 :             :   // Append all values one by one.
    2082                 :             :   ((void)C.insert(C.end(), std::forward<Args>(Values)), ...);
    2083                 :             : }
    2084                 :             : 
    2085                 :             : /// Given a sequence container Cont, replace the range [ContIt, ContEnd) with
    2086                 :             : /// the range [ValIt, ValEnd) (which is not from the same container).
    2087                 :             : template<typename Container, typename RandomAccessIterator>
    2088                 :             : void replace(Container &Cont, typename Container::iterator ContIt,
    2089                 :             :              typename Container::iterator ContEnd, RandomAccessIterator ValIt,
    2090                 :             :              RandomAccessIterator ValEnd) {
    2091                 :             :   while (true) {
    2092                 :             :     if (ValIt == ValEnd) {
    2093                 :             :       Cont.erase(ContIt, ContEnd);
    2094                 :             :       return;
    2095                 :             :     } else if (ContIt == ContEnd) {
    2096                 :             :       Cont.insert(ContIt, ValIt, ValEnd);
    2097                 :             :       return;
    2098                 :             :     }
    2099                 :             :     *ContIt++ = *ValIt++;
    2100                 :             :   }
    2101                 :             : }
    2102                 :             : 
    2103                 :             : /// Given a sequence container Cont, replace the range [ContIt, ContEnd) with
    2104                 :             : /// the range R.
    2105                 :             : template<typename Container, typename Range = std::initializer_list<
    2106                 :             :                                  typename Container::value_type>>
    2107                 :             : void replace(Container &Cont, typename Container::iterator ContIt,
    2108                 :             :              typename Container::iterator ContEnd, Range R) {
    2109                 :             :   replace(Cont, ContIt, ContEnd, R.begin(), R.end());
    2110                 :             : }
    2111                 :             : 
    2112                 :             : /// An STL-style algorithm similar to std::for_each that applies a second
    2113                 :             : /// functor between every pair of elements.
    2114                 :             : ///
    2115                 :             : /// This provides the control flow logic to, for example, print a
    2116                 :             : /// comma-separated list:
    2117                 :             : /// \code
    2118                 :             : ///   interleave(names.begin(), names.end(),
    2119                 :             : ///              [&](StringRef name) { os << name; },
    2120                 :             : ///              [&] { os << ", "; });
    2121                 :             : /// \endcode
    2122                 :             : template <typename ForwardIterator, typename UnaryFunctor,
    2123                 :             :           typename NullaryFunctor,
    2124                 :             :           typename = std::enable_if_t<
    2125                 :             :               !std::is_constructible<StringRef, UnaryFunctor>::value &&
    2126                 :             :               !std::is_constructible<StringRef, NullaryFunctor>::value>>
    2127                 :             : inline void interleave(ForwardIterator begin, ForwardIterator end,
    2128                 :             :                        UnaryFunctor each_fn, NullaryFunctor between_fn) {
    2129                 :             :   if (begin == end)
    2130                 :             :     return;
    2131                 :             :   each_fn(*begin);
    2132                 :             :   ++begin;
    2133                 :             :   for (; begin != end; ++begin) {
    2134                 :             :     between_fn();
    2135                 :             :     each_fn(*begin);
    2136                 :             :   }
    2137                 :             : }
    2138                 :             : 
    2139                 :             : template <typename Container, typename UnaryFunctor, typename NullaryFunctor,
    2140                 :             :           typename = std::enable_if_t<
    2141                 :             :               !std::is_constructible<StringRef, UnaryFunctor>::value &&
    2142                 :             :               !std::is_constructible<StringRef, NullaryFunctor>::value>>
    2143                 :             : inline void interleave(const Container &c, UnaryFunctor each_fn,
    2144                 :             :                        NullaryFunctor between_fn) {
    2145                 :             :   interleave(adl_begin(c), adl_end(c), each_fn, between_fn);
    2146                 :             : }
    2147                 :             : 
    2148                 :             : /// Overload of interleave for the common case of string separator.
    2149                 :             : template <typename Container, typename UnaryFunctor, typename StreamT,
    2150                 :             :           typename T = detail::ValueOfRange<Container>>
    2151                 :             : inline void interleave(const Container &c, StreamT &os, UnaryFunctor each_fn,
    2152                 :             :                        const StringRef &separator) {
    2153                 :             :   interleave(adl_begin(c), adl_end(c), each_fn, [&] { os << separator; });
    2154                 :             : }
    2155                 :             : template <typename Container, typename StreamT,
    2156                 :             :           typename T = detail::ValueOfRange<Container>>
    2157                 :             : inline void interleave(const Container &c, StreamT &os,
    2158                 :             :                        const StringRef &separator) {
    2159                 :             :   interleave(
    2160                 :             :       c, os, [&](const T &a) { os << a; }, separator);
    2161                 :             : }
    2162                 :             : 
    2163                 :             : template <typename Container, typename UnaryFunctor, typename StreamT,
    2164                 :             :           typename T = detail::ValueOfRange<Container>>
    2165                 :             : inline void interleaveComma(const Container &c, StreamT &os,
    2166                 :             :                             UnaryFunctor each_fn) {
    2167                 :             :   interleave(c, os, each_fn, ", ");
    2168                 :             : }
    2169                 :             : template <typename Container, typename StreamT,
    2170                 :             :           typename T = detail::ValueOfRange<Container>>
    2171                 :             : inline void interleaveComma(const Container &c, StreamT &os) {
    2172                 :             :   interleaveComma(c, os, [&](const T &a) { os << a; });
    2173                 :             : }
    2174                 :             : 
    2175                 :             : //===----------------------------------------------------------------------===//
    2176                 :             : //     Extra additions to <memory>
    2177                 :             : //===----------------------------------------------------------------------===//
    2178                 :             : 
    2179                 :             : struct FreeDeleter {
    2180                 :             :   void operator()(void* v) {
    2181                 :             :     ::free(v);
    2182                 :             :   }
    2183                 :             : };
    2184                 :             : 
    2185                 :             : template<typename First, typename Second>
    2186                 :             : struct pair_hash {
    2187                 :             :   size_t operator()(const std::pair<First, Second> &P) const {
    2188                 :             :     return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second);
    2189                 :             :   }
    2190                 :             : };
    2191                 :             : 
    2192                 :             : /// Binary functor that adapts to any other binary functor after dereferencing
    2193                 :             : /// operands.
    2194                 :             : template <typename T> struct deref {
    2195                 :             :   T func;
    2196                 :             : 
    2197                 :             :   // Could be further improved to cope with non-derivable functors and
    2198                 :             :   // non-binary functors (should be a variadic template member function
    2199                 :             :   // operator()).
    2200                 :             :   template <typename A, typename B> auto operator()(A &lhs, B &rhs) const {
    2201                 :             :     assert(lhs);
    2202                 :             :     assert(rhs);
    2203                 :             :     return func(*lhs, *rhs);
    2204                 :             :   }
    2205                 :             : };
    2206                 :             : 
    2207                 :             : namespace detail {
    2208                 :             : 
    2209                 :             : /// Tuple-like type for `zip_enumerator` dereference.
    2210                 :             : template <typename... Refs> struct enumerator_result;
    2211                 :             : 
    2212                 :             : template <typename... Iters>
    2213                 :             : using EnumeratorTupleType = enumerator_result<decltype(*declval<Iters>())...>;
    2214                 :             : 
    2215                 :             : /// Zippy iterator that uses the second iterator for comparisons. For the
    2216                 :             : /// increment to be safe, the second range has to be the shortest.
    2217                 :             : /// Returns `enumerator_result` on dereference to provide `.index()` and
    2218                 :             : /// `.value()` member functions.
    2219                 :             : /// Note: Because the dereference operator returns `enumerator_result` as a
    2220                 :             : /// value instead of a reference and does not strictly conform to the C++17's
    2221                 :             : /// definition of forward iterator. However, it satisfies all the
    2222                 :             : /// forward_iterator requirements that the `zip_common` and `zippy` depend on
    2223                 :             : /// and fully conforms to the C++20 definition of forward iterator.
    2224                 :             : /// This is similar to `std::vector<bool>::iterator` that returns bit reference
    2225                 :             : /// wrappers on dereference.
    2226                 :             : template <typename... Iters>
    2227                 :             : struct zip_enumerator : zip_common<zip_enumerator<Iters...>,
    2228                 :             :                                    EnumeratorTupleType<Iters...>, Iters...> {
    2229                 :             :   static_assert(sizeof...(Iters) >= 2, "Expected at least two iteratees");
    2230                 :             :   using zip_common<zip_enumerator<Iters...>, EnumeratorTupleType<Iters...>,
    2231                 :             :                    Iters...>::zip_common;
    2232                 :             : 
    2233                 :             :   bool operator==(const zip_enumerator &Other) const {
    2234                 :             :     return std::get<1>(this->iterators) == std::get<1>(Other.iterators);
    2235                 :             :   }
    2236                 :             : };
    2237                 :             : 
    2238                 :             : template <typename... Refs> struct enumerator_result<std::size_t, Refs...> {
    2239                 :             :   static constexpr std::size_t NumRefs = sizeof...(Refs);
    2240                 :             :   static_assert(NumRefs != 0);
    2241                 :             :   // `NumValues` includes the index.
    2242                 :             :   static constexpr std::size_t NumValues = NumRefs + 1;
    2243                 :             : 
    2244                 :             :   // Tuple type whose element types are references for each `Ref`.
    2245                 :             :   using range_reference_tuple = std::tuple<Refs...>;
    2246                 :             :   // Tuple type who elements are references to all values, including both
    2247                 :             :   // the index and `Refs` reference types.
    2248                 :             :   using value_reference_tuple = std::tuple<std::size_t, Refs...>;
    2249                 :             : 
    2250                 :             :   enumerator_result(std::size_t Index, Refs &&...Rs)
    2251                 :             :       : Idx(Index), Storage(std::forward<Refs>(Rs)...) {}
    2252                 :             : 
    2253                 :             :   /// Returns the 0-based index of the current position within the original
    2254                 :             :   /// input range(s).
    2255                 :             :   std::size_t index() const { return Idx; }
    2256                 :             : 
    2257                 :             :   /// Returns the value(s) for the current iterator. This does not include the
    2258                 :             :   /// index.
    2259                 :             :   decltype(auto) value() const {
    2260                 :             :     if constexpr (NumRefs == 1)
    2261                 :             :       return std::get<0>(Storage);
    2262                 :             :     else
    2263                 :             :       return Storage;
    2264                 :             :   }
    2265                 :             : 
    2266                 :             :   /// Returns the value at index `I`. This case covers the index.
    2267                 :             :   template <std::size_t I, typename = std::enable_if_t<I == 0>>
    2268                 :             :   friend std::size_t get(const enumerator_result &Result) {
    2269                 :             :     return Result.Idx;
    2270                 :             :   }
    2271                 :             : 
    2272                 :             :   /// Returns the value at index `I`. This case covers references to the
    2273                 :             :   /// iteratees.
    2274                 :             :   template <std::size_t I, typename = std::enable_if_t<I != 0>>
    2275                 :             :   friend decltype(auto) get(const enumerator_result &Result) {
    2276                 :             :     // Note: This is a separate function from the other `get`, instead of an
    2277                 :             :     // `if constexpr` case, to work around an MSVC 19.31.31XXX compiler
    2278                 :             :     // (Visual Studio 2022 17.1) return type deduction bug.
    2279                 :             :     return std::get<I - 1>(Result.Storage);
    2280                 :             :   }
    2281                 :             : 
    2282                 :             :   template <typename... Ts>
    2283                 :             :   friend bool operator==(const enumerator_result &Result,
    2284                 :             :                          const std::tuple<std::size_t, Ts...> &Other) {
    2285                 :             :     static_assert(NumRefs == sizeof...(Ts), "Size mismatch");
    2286                 :             :     if (Result.Idx != std::get<0>(Other))
    2287                 :             :       return false;
    2288                 :             :     return Result.is_value_equal(Other, std::make_index_sequence<NumRefs>{});
    2289                 :             :   }
    2290                 :             : 
    2291                 :             : private:
    2292                 :             :   template <typename Tuple, std::size_t... Idx>
    2293                 :             :   bool is_value_equal(const Tuple &Other, std::index_sequence<Idx...>) const {
    2294                 :             :     return ((std::get<Idx>(Storage) == std::get<Idx + 1>(Other)) && ...);
    2295                 :             :   }
    2296                 :             : 
    2297                 :             :   std::size_t Idx;
    2298                 :             :   // Make this tuple mutable to avoid casts that obfuscate const-correctness
    2299                 :             :   // issues. Const-correctness of references is taken care of by `zippy` that
    2300                 :             :   // defines const-non and const iterator types that will propagate down to
    2301                 :             :   // `enumerator_result`'s `Refs`.
    2302                 :             :   //  Note that unlike the results of `zip*` functions, `enumerate`'s result are
    2303                 :             :   //  supposed to be modifiable even when defined as
    2304                 :             :   // `const`.
    2305                 :             :   mutable range_reference_tuple Storage;
    2306                 :             : };
    2307                 :             : 
    2308                 :             : struct index_iterator
    2309                 :             :     : llvm::iterator_facade_base<index_iterator,
    2310                 :             :                                  std::random_access_iterator_tag, std::size_t> {
    2311                 :             :   index_iterator(std::size_t Index) : Index(Index) {}
    2312                 :             : 
    2313                 :             :   index_iterator &operator+=(std::ptrdiff_t N) {
    2314                 :             :     Index += N;
    2315                 :             :     return *this;
    2316                 :             :   }
    2317                 :             : 
    2318                 :             :   index_iterator &operator-=(std::ptrdiff_t N) {
    2319                 :             :     Index -= N;
    2320                 :             :     return *this;
    2321                 :             :   }
    2322                 :             : 
    2323                 :             :   std::ptrdiff_t operator-(const index_iterator &R) const {
    2324                 :             :     return Index - R.Index;
    2325                 :             :   }
    2326                 :             : 
    2327                 :             :   // Note: This dereference operator returns a value instead of a reference
    2328                 :             :   // and does not strictly conform to the C++17's definition of forward
    2329                 :             :   // iterator. However, it satisfies all the forward_iterator requirements
    2330                 :             :   // that the `zip_common` depends on and fully conforms to the C++20
    2331                 :             :   // definition of forward iterator.
    2332                 :             :   std::size_t operator*() const { return Index; }
    2333                 :             : 
    2334                 :             :   friend bool operator==(const index_iterator &Lhs, const index_iterator &Rhs) {
    2335                 :             :     return Lhs.Index == Rhs.Index;
    2336                 :             :   }
    2337                 :             : 
    2338                 :             :   friend bool operator<(const index_iterator &Lhs, const index_iterator &Rhs) {
    2339                 :             :     return Lhs.Index < Rhs.Index;
    2340                 :             :   }
    2341                 :             : 
    2342                 :             : private:
    2343                 :             :   std::size_t Index;
    2344                 :             : };
    2345                 :             : 
    2346                 :             : /// Infinite stream of increasing 0-based `size_t` indices.
    2347                 :             : struct index_stream {
    2348                 :             :   index_iterator begin() const { return {0}; }
    2349                 :             :   index_iterator end() const {
    2350                 :             :     // We approximate 'infinity' with the max size_t value, which should be good
    2351                 :             :     // enough to index over any container.
    2352                 :             :     return index_iterator{std::numeric_limits<std::size_t>::max()};
    2353                 :             :   }
    2354                 :             : };
    2355                 :             : 
    2356                 :             : } // end namespace detail
    2357                 :             : 
    2358                 :             : /// Increasing range of `size_t` indices.
    2359                 :             : class index_range {
    2360                 :             :   std::size_t Begin;
    2361                 :             :   std::size_t End;
    2362                 :             : 
    2363                 :             : public:
    2364                 :             :   index_range(std::size_t Begin, std::size_t End) : Begin(Begin), End(End) {}
    2365                 :             :   detail::index_iterator begin() const { return {Begin}; }
    2366                 :             :   detail::index_iterator end() const { return {End}; }
    2367                 :             : };
    2368                 :             : 
    2369                 :             : /// Given two or more input ranges, returns a new range whose values are are
    2370                 :             : /// tuples (A, B, C, ...), such that A is the 0-based index of the item in the
    2371                 :             : /// sequence, and B, C, ..., are the values from the original input ranges. All
    2372                 :             : /// input ranges are required to have equal lengths. Note that the returned
    2373                 :             : /// iterator allows for the values (B, C, ...) to be modified.  Example:
    2374                 :             : ///
    2375                 :             : /// ```c++
    2376                 :             : /// std::vector<char> Letters = {'A', 'B', 'C', 'D'};
    2377                 :             : /// std::vector<int> Vals = {10, 11, 12, 13};
    2378                 :             : ///
    2379                 :             : /// for (auto [Index, Letter, Value] : enumerate(Letters, Vals)) {
    2380                 :             : ///   printf("Item %zu - %c: %d\n", Index, Letter, Value);
    2381                 :             : ///   Value -= 10;
    2382                 :             : /// }
    2383                 :             : /// ```
    2384                 :             : ///
    2385                 :             : /// Output:
    2386                 :             : ///   Item 0 - A: 10
    2387                 :             : ///   Item 1 - B: 11
    2388                 :             : ///   Item 2 - C: 12
    2389                 :             : ///   Item 3 - D: 13
    2390                 :             : ///
    2391                 :             : /// or using an iterator:
    2392                 :             : /// ```c++
    2393                 :             : /// for (auto it : enumerate(Vals)) {
    2394                 :             : ///   it.value() += 10;
    2395                 :             : ///   printf("Item %zu: %d\n", it.index(), it.value());
    2396                 :             : /// }
    2397                 :             : /// ```
    2398                 :             : ///
    2399                 :             : /// Output:
    2400                 :             : ///   Item 0: 20
    2401                 :             : ///   Item 1: 21
    2402                 :             : ///   Item 2: 22
    2403                 :             : ///   Item 3: 23
    2404                 :             : ///
    2405                 :             : template <typename FirstRange, typename... RestRanges>
    2406                 :             : auto enumerate(FirstRange &&First, RestRanges &&...Rest) {
    2407                 :             :   if constexpr (sizeof...(Rest) != 0) {
    2408                 :             : #ifndef NDEBUG
    2409                 :             :     // Note: Create an array instead of an initializer list to work around an
    2410                 :             :     // Apple clang 14 compiler bug.
    2411                 :             :     size_t sizes[] = {range_size(First), range_size(Rest)...};
    2412                 :             :     assert(all_equal(sizes) && "Ranges have different length");
    2413                 :             : #endif
    2414                 :             :   }
    2415                 :             :   using enumerator = detail::zippy<detail::zip_enumerator, detail::index_stream,
    2416                 :             :                                    FirstRange, RestRanges...>;
    2417                 :             :   return enumerator(detail::index_stream{}, std::forward<FirstRange>(First),
    2418                 :             :                     std::forward<RestRanges>(Rest)...);
    2419                 :             : }
    2420                 :             : 
    2421                 :             : namespace detail {
    2422                 :             : 
    2423                 :             : template <typename Predicate, typename... Args>
    2424                 :             : bool all_of_zip_predicate_first(Predicate &&P, Args &&...args) {
    2425                 :             :   auto z = zip(args...);
    2426                 :             :   auto it = z.begin();
    2427                 :             :   auto end = z.end();
    2428                 :             :   while (it != end) {
    2429                 :             :     if (!std::apply([&](auto &&...args) { return P(args...); }, *it))
    2430                 :             :       return false;
    2431                 :             :     ++it;
    2432                 :             :   }
    2433                 :             :   return it.all_equals(end);
    2434                 :             : }
    2435                 :             : 
    2436                 :             : // Just an adaptor to switch the order of argument and have the predicate before
    2437                 :             : // the zipped inputs.
    2438                 :             : template <typename... ArgsThenPredicate, size_t... InputIndexes>
    2439                 :             : bool all_of_zip_predicate_last(
    2440                 :             :     std::tuple<ArgsThenPredicate...> argsThenPredicate,
    2441                 :             :     std::index_sequence<InputIndexes...>) {
    2442                 :             :   auto constexpr OutputIndex =
    2443                 :             :       std::tuple_size<decltype(argsThenPredicate)>::value - 1;
    2444                 :             :   return all_of_zip_predicate_first(std::get<OutputIndex>(argsThenPredicate),
    2445                 :             :                              std::get<InputIndexes>(argsThenPredicate)...);
    2446                 :             : }
    2447                 :             : 
    2448                 :             : } // end namespace detail
    2449                 :             : 
    2450                 :             : /// Compare two zipped ranges using the provided predicate (as last argument).
    2451                 :             : /// Return true if all elements satisfy the predicate and false otherwise.
    2452                 :             : //  Return false if the zipped iterator aren't all at end (size mismatch).
    2453                 :             : template <typename... ArgsAndPredicate>
    2454                 :             : bool all_of_zip(ArgsAndPredicate &&...argsAndPredicate) {
    2455                 :             :   return detail::all_of_zip_predicate_last(
    2456                 :             :       std::forward_as_tuple(argsAndPredicate...),
    2457                 :             :       std::make_index_sequence<sizeof...(argsAndPredicate) - 1>{});
    2458                 :             : }
    2459                 :             : 
    2460                 :             : /// Return true if the sequence [Begin, End) has exactly N items. Runs in O(N)
    2461                 :             : /// time. Not meant for use with random-access iterators.
    2462                 :             : /// Can optionally take a predicate to filter lazily some items.
    2463                 :             : template <typename IterTy,
    2464                 :             :           typename Pred = bool (*)(const decltype(*std::declval<IterTy>()) &)>
    2465                 :             : bool hasNItems(
    2466                 :             :     IterTy &&Begin, IterTy &&End, unsigned N,
    2467                 :             :     Pred &&ShouldBeCounted =
    2468                 :             :         [](const decltype(*std::declval<IterTy>()) &) { return true; },
    2469                 :             :     std::enable_if_t<
    2470                 :             :         !std::is_base_of<std::random_access_iterator_tag,
    2471                 :             :                          typename std::iterator_traits<std::remove_reference_t<
    2472                 :             :                              decltype(Begin)>>::iterator_category>::value,
    2473                 :             :         void> * = nullptr) {
    2474                 :             :   for (; N; ++Begin) {
    2475                 :             :     if (Begin == End)
    2476                 :             :       return false; // Too few.
    2477                 :             :     N -= ShouldBeCounted(*Begin);
    2478                 :             :   }
    2479                 :             :   for (; Begin != End; ++Begin)
    2480                 :             :     if (ShouldBeCounted(*Begin))
    2481                 :             :       return false; // Too many.
    2482                 :             :   return true;
    2483                 :             : }
    2484                 :             : 
    2485                 :             : /// Return true if the sequence [Begin, End) has N or more items. Runs in O(N)
    2486                 :             : /// time. Not meant for use with random-access iterators.
    2487                 :             : /// Can optionally take a predicate to lazily filter some items.
    2488                 :             : template <typename IterTy,
    2489                 :             :           typename Pred = bool (*)(const decltype(*std::declval<IterTy>()) &)>
    2490                 :             : bool hasNItemsOrMore(
    2491                 :             :     IterTy &&Begin, IterTy &&End, unsigned N,
    2492                 :             :     Pred &&ShouldBeCounted =
    2493                 :             :         [](const decltype(*std::declval<IterTy>()) &) { return true; },
    2494                 :             :     std::enable_if_t<
    2495                 :             :         !std::is_base_of<std::random_access_iterator_tag,
    2496                 :             :                          typename std::iterator_traits<std::remove_reference_t<
    2497                 :             :                              decltype(Begin)>>::iterator_category>::value,
    2498                 :             :         void> * = nullptr) {
    2499                 :             :   for (; N; ++Begin) {
    2500                 :             :     if (Begin == End)
    2501                 :             :       return false; // Too few.
    2502                 :             :     N -= ShouldBeCounted(*Begin);
    2503                 :             :   }
    2504                 :             :   return true;
    2505                 :             : }
    2506                 :             : 
    2507                 :             : /// Returns true if the sequence [Begin, End) has N or less items. Can
    2508                 :             : /// optionally take a predicate to lazily filter some items.
    2509                 :             : template <typename IterTy,
    2510                 :             :           typename Pred = bool (*)(const decltype(*std::declval<IterTy>()) &)>
    2511                 :             : bool hasNItemsOrLess(
    2512                 :             :     IterTy &&Begin, IterTy &&End, unsigned N,
    2513                 :             :     Pred &&ShouldBeCounted = [](const decltype(*std::declval<IterTy>()) &) {
    2514                 :             :       return true;
    2515                 :             :     }) {
    2516                 :             :   assert(N != std::numeric_limits<unsigned>::max());
    2517                 :             :   return !hasNItemsOrMore(Begin, End, N + 1, ShouldBeCounted);
    2518                 :             : }
    2519                 :             : 
    2520                 :             : /// Returns true if the given container has exactly N items
    2521                 :             : template <typename ContainerTy> bool hasNItems(ContainerTy &&C, unsigned N) {
    2522                 :             :   return hasNItems(std::begin(C), std::end(C), N);
    2523                 :             : }
    2524                 :             : 
    2525                 :             : /// Returns true if the given container has N or more items
    2526                 :             : template <typename ContainerTy>
    2527                 :             : bool hasNItemsOrMore(ContainerTy &&C, unsigned N) {
    2528                 :             :   return hasNItemsOrMore(std::begin(C), std::end(C), N);
    2529                 :             : }
    2530                 :             : 
    2531                 :             : /// Returns true if the given container has N or less items
    2532                 :             : template <typename ContainerTy>
    2533                 :             : bool hasNItemsOrLess(ContainerTy &&C, unsigned N) {
    2534                 :             :   return hasNItemsOrLess(std::begin(C), std::end(C), N);
    2535                 :             : }
    2536                 :             : 
    2537                 :             : /// Returns a raw pointer that represents the same address as the argument.
    2538                 :             : ///
    2539                 :             : /// This implementation can be removed once we move to C++20 where it's defined
    2540                 :             : /// as std::to_address().
    2541                 :             : ///
    2542                 :             : /// The std::pointer_traits<>::to_address(p) variations of these overloads has
    2543                 :             : /// not been implemented.
    2544                 :             : template <class Ptr> auto to_address(const Ptr &P) { return P.operator->(); }
    2545                 :             : template <class T> constexpr T *to_address(T *P) { return P; }
    2546                 :             : 
    2547                 :             : // Detect incomplete types, relying on the fact that their size is unknown.
    2548                 :             : namespace detail {
    2549                 :             : template <typename T> using has_sizeof = decltype(sizeof(T));
    2550                 :             : } // namespace detail
    2551                 :             : 
    2552                 :             : /// Detects when type `T` is incomplete. This is true for forward declarations
    2553                 :             : /// and false for types with a full definition.
    2554                 :             : template <typename T>
    2555                 :             : constexpr bool is_incomplete_v = !is_detected<detail::has_sizeof, T>::value;
    2556                 :             : 
    2557                 :             : } // end namespace llvm
    2558                 :             : 
    2559                 :             : namespace std {
    2560                 :             : template <typename... Refs>
    2561                 :             : struct tuple_size<llvm::detail::enumerator_result<Refs...>>
    2562                 :             :     : std::integral_constant<std::size_t, sizeof...(Refs)> {};
    2563                 :             : 
    2564                 :             : template <std::size_t I, typename... Refs>
    2565                 :             : struct tuple_element<I, llvm::detail::enumerator_result<Refs...>>
    2566                 :             :     : std::tuple_element<I, std::tuple<Refs...>> {};
    2567                 :             : 
    2568                 :             : template <std::size_t I, typename... Refs>
    2569                 :             : struct tuple_element<I, const llvm::detail::enumerator_result<Refs...>>
    2570                 :             :     : std::tuple_element<I, std::tuple<Refs...>> {};
    2571                 :             : 
    2572                 :             : } // namespace std
    2573                 :             : 
    2574                 :             : #endif // LLVM_ADT_STLEXTRAS_H
        

Generated by: LCOV version 2.0-1