xref: /freebsd/contrib/llvm-project/llvm/include/llvm/ADT/STLExtras.h (revision 8bcb0991864975618c09697b1aca10683346d9f0)
10b57cec5SDimitry Andric //===- llvm/ADT/STLExtras.h - Useful STL related functions ------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file contains some templates that are useful if you are working with the
100b57cec5SDimitry Andric // STL at all.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric // No library is required when using these functions.
130b57cec5SDimitry Andric //
140b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric #ifndef LLVM_ADT_STLEXTRAS_H
170b57cec5SDimitry Andric #define LLVM_ADT_STLEXTRAS_H
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #include "llvm/ADT/Optional.h"
200b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
210b57cec5SDimitry Andric #include "llvm/ADT/iterator.h"
220b57cec5SDimitry Andric #include "llvm/ADT/iterator_range.h"
230b57cec5SDimitry Andric #include "llvm/Config/abi-breaking.h"
240b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
250b57cec5SDimitry Andric #include <algorithm>
260b57cec5SDimitry Andric #include <cassert>
270b57cec5SDimitry Andric #include <cstddef>
280b57cec5SDimitry Andric #include <cstdint>
290b57cec5SDimitry Andric #include <cstdlib>
300b57cec5SDimitry Andric #include <functional>
310b57cec5SDimitry Andric #include <initializer_list>
320b57cec5SDimitry Andric #include <iterator>
330b57cec5SDimitry Andric #include <limits>
340b57cec5SDimitry Andric #include <memory>
350b57cec5SDimitry Andric #include <tuple>
360b57cec5SDimitry Andric #include <type_traits>
370b57cec5SDimitry Andric #include <utility>
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
400b57cec5SDimitry Andric #include <random> // for std::mt19937
410b57cec5SDimitry Andric #endif
420b57cec5SDimitry Andric 
430b57cec5SDimitry Andric namespace llvm {
440b57cec5SDimitry Andric 
450b57cec5SDimitry Andric // Only used by compiler if both template types are the same.  Useful when
460b57cec5SDimitry Andric // using SFINAE to test for the existence of member functions.
470b57cec5SDimitry Andric template <typename T, T> struct SameType;
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric namespace detail {
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric template <typename RangeT>
520b57cec5SDimitry Andric using IterOfRange = decltype(std::begin(std::declval<RangeT &>()));
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric template <typename RangeT>
550b57cec5SDimitry Andric using ValueOfRange = typename std::remove_reference<decltype(
560b57cec5SDimitry Andric     *std::begin(std::declval<RangeT &>()))>::type;
570b57cec5SDimitry Andric 
580b57cec5SDimitry Andric } // end namespace detail
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
610b57cec5SDimitry Andric //     Extra additions to <type_traits>
620b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric template <typename T>
650b57cec5SDimitry Andric struct negation : std::integral_constant<bool, !bool(T::value)> {};
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric template <typename...> struct conjunction : std::true_type {};
680b57cec5SDimitry Andric template <typename B1> struct conjunction<B1> : B1 {};
690b57cec5SDimitry Andric template <typename B1, typename... Bn>
700b57cec5SDimitry Andric struct conjunction<B1, Bn...>
710b57cec5SDimitry Andric     : std::conditional<bool(B1::value), conjunction<Bn...>, B1>::type {};
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric template <typename T> struct make_const_ptr {
740b57cec5SDimitry Andric   using type =
750b57cec5SDimitry Andric       typename std::add_pointer<typename std::add_const<T>::type>::type;
760b57cec5SDimitry Andric };
770b57cec5SDimitry Andric 
780b57cec5SDimitry Andric template <typename T> struct make_const_ref {
790b57cec5SDimitry Andric   using type = typename std::add_lvalue_reference<
800b57cec5SDimitry Andric       typename std::add_const<T>::type>::type;
810b57cec5SDimitry Andric };
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
840b57cec5SDimitry Andric //     Extra additions to <functional>
850b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric template <class Ty> struct identity {
880b57cec5SDimitry Andric   using argument_type = Ty;
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   Ty &operator()(Ty &self) const {
910b57cec5SDimitry Andric     return self;
920b57cec5SDimitry Andric   }
930b57cec5SDimitry Andric   const Ty &operator()(const Ty &self) const {
940b57cec5SDimitry Andric     return self;
950b57cec5SDimitry Andric   }
960b57cec5SDimitry Andric };
970b57cec5SDimitry Andric 
980b57cec5SDimitry Andric /// An efficient, type-erasing, non-owning reference to a callable. This is
990b57cec5SDimitry Andric /// intended for use as the type of a function parameter that is not used
1000b57cec5SDimitry Andric /// after the function in question returns.
1010b57cec5SDimitry Andric ///
1020b57cec5SDimitry Andric /// This class does not own the callable, so it is not in general safe to store
1030b57cec5SDimitry Andric /// a function_ref.
1040b57cec5SDimitry Andric template<typename Fn> class function_ref;
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric template<typename Ret, typename ...Params>
1070b57cec5SDimitry Andric class function_ref<Ret(Params...)> {
1080b57cec5SDimitry Andric   Ret (*callback)(intptr_t callable, Params ...params) = nullptr;
1090b57cec5SDimitry Andric   intptr_t callable;
1100b57cec5SDimitry Andric 
1110b57cec5SDimitry Andric   template<typename Callable>
1120b57cec5SDimitry Andric   static Ret callback_fn(intptr_t callable, Params ...params) {
1130b57cec5SDimitry Andric     return (*reinterpret_cast<Callable*>(callable))(
1140b57cec5SDimitry Andric         std::forward<Params>(params)...);
1150b57cec5SDimitry Andric   }
1160b57cec5SDimitry Andric 
1170b57cec5SDimitry Andric public:
1180b57cec5SDimitry Andric   function_ref() = default;
1190b57cec5SDimitry Andric   function_ref(std::nullptr_t) {}
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric   template <typename Callable>
1220b57cec5SDimitry Andric   function_ref(Callable &&callable,
1230b57cec5SDimitry Andric                typename std::enable_if<
1240b57cec5SDimitry Andric                    !std::is_same<typename std::remove_reference<Callable>::type,
1250b57cec5SDimitry Andric                                  function_ref>::value>::type * = nullptr)
1260b57cec5SDimitry Andric       : callback(callback_fn<typename std::remove_reference<Callable>::type>),
1270b57cec5SDimitry Andric         callable(reinterpret_cast<intptr_t>(&callable)) {}
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   Ret operator()(Params ...params) const {
1300b57cec5SDimitry Andric     return callback(callable, std::forward<Params>(params)...);
1310b57cec5SDimitry Andric   }
1320b57cec5SDimitry Andric 
1330b57cec5SDimitry Andric   operator bool() const { return callback; }
1340b57cec5SDimitry Andric };
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric // deleter - Very very very simple method that is used to invoke operator
1370b57cec5SDimitry Andric // delete on something.  It is used like this:
1380b57cec5SDimitry Andric //
1390b57cec5SDimitry Andric //   for_each(V.begin(), B.end(), deleter<Interval>);
1400b57cec5SDimitry Andric template <class T>
1410b57cec5SDimitry Andric inline void deleter(T *Ptr) {
1420b57cec5SDimitry Andric   delete Ptr;
1430b57cec5SDimitry Andric }
1440b57cec5SDimitry Andric 
1450b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1460b57cec5SDimitry Andric //     Extra additions to <iterator>
1470b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric namespace adl_detail {
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric using std::begin;
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric template <typename ContainerTy>
1540b57cec5SDimitry Andric auto adl_begin(ContainerTy &&container)
1550b57cec5SDimitry Andric     -> decltype(begin(std::forward<ContainerTy>(container))) {
1560b57cec5SDimitry Andric   return begin(std::forward<ContainerTy>(container));
1570b57cec5SDimitry Andric }
1580b57cec5SDimitry Andric 
1590b57cec5SDimitry Andric using std::end;
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric template <typename ContainerTy>
1620b57cec5SDimitry Andric auto adl_end(ContainerTy &&container)
1630b57cec5SDimitry Andric     -> decltype(end(std::forward<ContainerTy>(container))) {
1640b57cec5SDimitry Andric   return end(std::forward<ContainerTy>(container));
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric using std::swap;
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric template <typename T>
1700b57cec5SDimitry Andric void adl_swap(T &&lhs, T &&rhs) noexcept(noexcept(swap(std::declval<T>(),
1710b57cec5SDimitry Andric                                                        std::declval<T>()))) {
1720b57cec5SDimitry Andric   swap(std::forward<T>(lhs), std::forward<T>(rhs));
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric 
1750b57cec5SDimitry Andric } // end namespace adl_detail
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric template <typename ContainerTy>
1780b57cec5SDimitry Andric auto adl_begin(ContainerTy &&container)
1790b57cec5SDimitry Andric     -> decltype(adl_detail::adl_begin(std::forward<ContainerTy>(container))) {
1800b57cec5SDimitry Andric   return adl_detail::adl_begin(std::forward<ContainerTy>(container));
1810b57cec5SDimitry Andric }
1820b57cec5SDimitry Andric 
1830b57cec5SDimitry Andric template <typename ContainerTy>
1840b57cec5SDimitry Andric auto adl_end(ContainerTy &&container)
1850b57cec5SDimitry Andric     -> decltype(adl_detail::adl_end(std::forward<ContainerTy>(container))) {
1860b57cec5SDimitry Andric   return adl_detail::adl_end(std::forward<ContainerTy>(container));
1870b57cec5SDimitry Andric }
1880b57cec5SDimitry Andric 
1890b57cec5SDimitry Andric template <typename T>
1900b57cec5SDimitry Andric void adl_swap(T &&lhs, T &&rhs) noexcept(
1910b57cec5SDimitry Andric     noexcept(adl_detail::adl_swap(std::declval<T>(), std::declval<T>()))) {
1920b57cec5SDimitry Andric   adl_detail::adl_swap(std::forward<T>(lhs), std::forward<T>(rhs));
1930b57cec5SDimitry Andric }
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric /// Test whether \p RangeOrContainer is empty. Similar to C++17 std::empty.
1960b57cec5SDimitry Andric template <typename T>
1970b57cec5SDimitry Andric constexpr bool empty(const T &RangeOrContainer) {
1980b57cec5SDimitry Andric   return adl_begin(RangeOrContainer) == adl_end(RangeOrContainer);
1990b57cec5SDimitry Andric }
2000b57cec5SDimitry Andric 
2010b57cec5SDimitry Andric // mapped_iterator - This is a simple iterator adapter that causes a function to
2020b57cec5SDimitry Andric // be applied whenever operator* is invoked on the iterator.
2030b57cec5SDimitry Andric 
2040b57cec5SDimitry Andric template <typename ItTy, typename FuncTy,
2050b57cec5SDimitry Andric           typename FuncReturnTy =
2060b57cec5SDimitry Andric             decltype(std::declval<FuncTy>()(*std::declval<ItTy>()))>
2070b57cec5SDimitry Andric class mapped_iterator
2080b57cec5SDimitry Andric     : public iterator_adaptor_base<
2090b57cec5SDimitry Andric              mapped_iterator<ItTy, FuncTy>, ItTy,
2100b57cec5SDimitry Andric              typename std::iterator_traits<ItTy>::iterator_category,
2110b57cec5SDimitry Andric              typename std::remove_reference<FuncReturnTy>::type> {
2120b57cec5SDimitry Andric public:
2130b57cec5SDimitry Andric   mapped_iterator(ItTy U, FuncTy F)
2140b57cec5SDimitry Andric     : mapped_iterator::iterator_adaptor_base(std::move(U)), F(std::move(F)) {}
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   ItTy getCurrent() { return this->I; }
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric   FuncReturnTy operator*() { return F(*this->I); }
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric private:
2210b57cec5SDimitry Andric   FuncTy F;
2220b57cec5SDimitry Andric };
2230b57cec5SDimitry Andric 
2240b57cec5SDimitry Andric // map_iterator - Provide a convenient way to create mapped_iterators, just like
2250b57cec5SDimitry Andric // make_pair is useful for creating pairs...
2260b57cec5SDimitry Andric template <class ItTy, class FuncTy>
2270b57cec5SDimitry Andric inline mapped_iterator<ItTy, FuncTy> map_iterator(ItTy I, FuncTy F) {
2280b57cec5SDimitry Andric   return mapped_iterator<ItTy, FuncTy>(std::move(I), std::move(F));
2290b57cec5SDimitry Andric }
2300b57cec5SDimitry Andric 
2310b57cec5SDimitry Andric template <class ContainerTy, class FuncTy>
2320b57cec5SDimitry Andric auto map_range(ContainerTy &&C, FuncTy F)
2330b57cec5SDimitry Andric     -> decltype(make_range(map_iterator(C.begin(), F),
2340b57cec5SDimitry Andric                            map_iterator(C.end(), F))) {
2350b57cec5SDimitry Andric   return make_range(map_iterator(C.begin(), F), map_iterator(C.end(), F));
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric 
2380b57cec5SDimitry Andric /// Helper to determine if type T has a member called rbegin().
2390b57cec5SDimitry Andric template <typename Ty> class has_rbegin_impl {
2400b57cec5SDimitry Andric   using yes = char[1];
2410b57cec5SDimitry Andric   using no = char[2];
2420b57cec5SDimitry Andric 
2430b57cec5SDimitry Andric   template <typename Inner>
2440b57cec5SDimitry Andric   static yes& test(Inner *I, decltype(I->rbegin()) * = nullptr);
2450b57cec5SDimitry Andric 
2460b57cec5SDimitry Andric   template <typename>
2470b57cec5SDimitry Andric   static no& test(...);
2480b57cec5SDimitry Andric 
2490b57cec5SDimitry Andric public:
2500b57cec5SDimitry Andric   static const bool value = sizeof(test<Ty>(nullptr)) == sizeof(yes);
2510b57cec5SDimitry Andric };
2520b57cec5SDimitry Andric 
2530b57cec5SDimitry Andric /// Metafunction to determine if T& or T has a member called rbegin().
2540b57cec5SDimitry Andric template <typename Ty>
2550b57cec5SDimitry Andric struct has_rbegin : has_rbegin_impl<typename std::remove_reference<Ty>::type> {
2560b57cec5SDimitry Andric };
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric // Returns an iterator_range over the given container which iterates in reverse.
2590b57cec5SDimitry Andric // Note that the container must have rbegin()/rend() methods for this to work.
2600b57cec5SDimitry Andric template <typename ContainerTy>
2610b57cec5SDimitry Andric auto reverse(ContainerTy &&C,
2620b57cec5SDimitry Andric              typename std::enable_if<has_rbegin<ContainerTy>::value>::type * =
2630b57cec5SDimitry Andric                  nullptr) -> decltype(make_range(C.rbegin(), C.rend())) {
2640b57cec5SDimitry Andric   return make_range(C.rbegin(), C.rend());
2650b57cec5SDimitry Andric }
2660b57cec5SDimitry Andric 
2670b57cec5SDimitry Andric // Returns a std::reverse_iterator wrapped around the given iterator.
2680b57cec5SDimitry Andric template <typename IteratorTy>
2690b57cec5SDimitry Andric std::reverse_iterator<IteratorTy> make_reverse_iterator(IteratorTy It) {
2700b57cec5SDimitry Andric   return std::reverse_iterator<IteratorTy>(It);
2710b57cec5SDimitry Andric }
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric // Returns an iterator_range over the given container which iterates in reverse.
2740b57cec5SDimitry Andric // Note that the container must have begin()/end() methods which return
2750b57cec5SDimitry Andric // bidirectional iterators for this to work.
2760b57cec5SDimitry Andric template <typename ContainerTy>
2770b57cec5SDimitry Andric auto reverse(
2780b57cec5SDimitry Andric     ContainerTy &&C,
2790b57cec5SDimitry Andric     typename std::enable_if<!has_rbegin<ContainerTy>::value>::type * = nullptr)
2800b57cec5SDimitry Andric     -> decltype(make_range(llvm::make_reverse_iterator(std::end(C)),
2810b57cec5SDimitry Andric                            llvm::make_reverse_iterator(std::begin(C)))) {
2820b57cec5SDimitry Andric   return make_range(llvm::make_reverse_iterator(std::end(C)),
2830b57cec5SDimitry Andric                     llvm::make_reverse_iterator(std::begin(C)));
2840b57cec5SDimitry Andric }
2850b57cec5SDimitry Andric 
2860b57cec5SDimitry Andric /// An iterator adaptor that filters the elements of given inner iterators.
2870b57cec5SDimitry Andric ///
2880b57cec5SDimitry Andric /// The predicate parameter should be a callable object that accepts the wrapped
2890b57cec5SDimitry Andric /// iterator's reference type and returns a bool. When incrementing or
2900b57cec5SDimitry Andric /// decrementing the iterator, it will call the predicate on each element and
2910b57cec5SDimitry Andric /// skip any where it returns false.
2920b57cec5SDimitry Andric ///
2930b57cec5SDimitry Andric /// \code
2940b57cec5SDimitry Andric ///   int A[] = { 1, 2, 3, 4 };
2950b57cec5SDimitry Andric ///   auto R = make_filter_range(A, [](int N) { return N % 2 == 1; });
2960b57cec5SDimitry Andric ///   // R contains { 1, 3 }.
2970b57cec5SDimitry Andric /// \endcode
2980b57cec5SDimitry Andric ///
2990b57cec5SDimitry Andric /// Note: filter_iterator_base implements support for forward iteration.
3000b57cec5SDimitry Andric /// filter_iterator_impl exists to provide support for bidirectional iteration,
3010b57cec5SDimitry Andric /// conditional on whether the wrapped iterator supports it.
3020b57cec5SDimitry Andric template <typename WrappedIteratorT, typename PredicateT, typename IterTag>
3030b57cec5SDimitry Andric class filter_iterator_base
3040b57cec5SDimitry Andric     : public iterator_adaptor_base<
3050b57cec5SDimitry Andric           filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>,
3060b57cec5SDimitry Andric           WrappedIteratorT,
3070b57cec5SDimitry Andric           typename std::common_type<
3080b57cec5SDimitry Andric               IterTag, typename std::iterator_traits<
3090b57cec5SDimitry Andric                            WrappedIteratorT>::iterator_category>::type> {
3100b57cec5SDimitry Andric   using BaseT = iterator_adaptor_base<
3110b57cec5SDimitry Andric       filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>,
3120b57cec5SDimitry Andric       WrappedIteratorT,
3130b57cec5SDimitry Andric       typename std::common_type<
3140b57cec5SDimitry Andric           IterTag, typename std::iterator_traits<
3150b57cec5SDimitry Andric                        WrappedIteratorT>::iterator_category>::type>;
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric protected:
3180b57cec5SDimitry Andric   WrappedIteratorT End;
3190b57cec5SDimitry Andric   PredicateT Pred;
3200b57cec5SDimitry Andric 
3210b57cec5SDimitry Andric   void findNextValid() {
3220b57cec5SDimitry Andric     while (this->I != End && !Pred(*this->I))
3230b57cec5SDimitry Andric       BaseT::operator++();
3240b57cec5SDimitry Andric   }
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric   // Construct the iterator. The begin iterator needs to know where the end
3270b57cec5SDimitry Andric   // is, so that it can properly stop when it gets there. The end iterator only
3280b57cec5SDimitry Andric   // needs the predicate to support bidirectional iteration.
3290b57cec5SDimitry Andric   filter_iterator_base(WrappedIteratorT Begin, WrappedIteratorT End,
3300b57cec5SDimitry Andric                        PredicateT Pred)
3310b57cec5SDimitry Andric       : BaseT(Begin), End(End), Pred(Pred) {
3320b57cec5SDimitry Andric     findNextValid();
3330b57cec5SDimitry Andric   }
3340b57cec5SDimitry Andric 
3350b57cec5SDimitry Andric public:
3360b57cec5SDimitry Andric   using BaseT::operator++;
3370b57cec5SDimitry Andric 
3380b57cec5SDimitry Andric   filter_iterator_base &operator++() {
3390b57cec5SDimitry Andric     BaseT::operator++();
3400b57cec5SDimitry Andric     findNextValid();
3410b57cec5SDimitry Andric     return *this;
3420b57cec5SDimitry Andric   }
3430b57cec5SDimitry Andric };
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric /// Specialization of filter_iterator_base for forward iteration only.
3460b57cec5SDimitry Andric template <typename WrappedIteratorT, typename PredicateT,
3470b57cec5SDimitry Andric           typename IterTag = std::forward_iterator_tag>
3480b57cec5SDimitry Andric class filter_iterator_impl
3490b57cec5SDimitry Andric     : public filter_iterator_base<WrappedIteratorT, PredicateT, IterTag> {
3500b57cec5SDimitry Andric   using BaseT = filter_iterator_base<WrappedIteratorT, PredicateT, IterTag>;
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric public:
3530b57cec5SDimitry Andric   filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End,
3540b57cec5SDimitry Andric                        PredicateT Pred)
3550b57cec5SDimitry Andric       : BaseT(Begin, End, Pred) {}
3560b57cec5SDimitry Andric };
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric /// Specialization of filter_iterator_base for bidirectional iteration.
3590b57cec5SDimitry Andric template <typename WrappedIteratorT, typename PredicateT>
3600b57cec5SDimitry Andric class filter_iterator_impl<WrappedIteratorT, PredicateT,
3610b57cec5SDimitry Andric                            std::bidirectional_iterator_tag>
3620b57cec5SDimitry Andric     : public filter_iterator_base<WrappedIteratorT, PredicateT,
3630b57cec5SDimitry Andric                                   std::bidirectional_iterator_tag> {
3640b57cec5SDimitry Andric   using BaseT = filter_iterator_base<WrappedIteratorT, PredicateT,
3650b57cec5SDimitry Andric                                      std::bidirectional_iterator_tag>;
3660b57cec5SDimitry Andric   void findPrevValid() {
3670b57cec5SDimitry Andric     while (!this->Pred(*this->I))
3680b57cec5SDimitry Andric       BaseT::operator--();
3690b57cec5SDimitry Andric   }
3700b57cec5SDimitry Andric 
3710b57cec5SDimitry Andric public:
3720b57cec5SDimitry Andric   using BaseT::operator--;
3730b57cec5SDimitry Andric 
3740b57cec5SDimitry Andric   filter_iterator_impl(WrappedIteratorT Begin, WrappedIteratorT End,
3750b57cec5SDimitry Andric                        PredicateT Pred)
3760b57cec5SDimitry Andric       : BaseT(Begin, End, Pred) {}
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric   filter_iterator_impl &operator--() {
3790b57cec5SDimitry Andric     BaseT::operator--();
3800b57cec5SDimitry Andric     findPrevValid();
3810b57cec5SDimitry Andric     return *this;
3820b57cec5SDimitry Andric   }
3830b57cec5SDimitry Andric };
3840b57cec5SDimitry Andric 
3850b57cec5SDimitry Andric namespace detail {
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric template <bool is_bidirectional> struct fwd_or_bidi_tag_impl {
3880b57cec5SDimitry Andric   using type = std::forward_iterator_tag;
3890b57cec5SDimitry Andric };
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric template <> struct fwd_or_bidi_tag_impl<true> {
3920b57cec5SDimitry Andric   using type = std::bidirectional_iterator_tag;
3930b57cec5SDimitry Andric };
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric /// Helper which sets its type member to forward_iterator_tag if the category
3960b57cec5SDimitry Andric /// of \p IterT does not derive from bidirectional_iterator_tag, and to
3970b57cec5SDimitry Andric /// bidirectional_iterator_tag otherwise.
3980b57cec5SDimitry Andric template <typename IterT> struct fwd_or_bidi_tag {
3990b57cec5SDimitry Andric   using type = typename fwd_or_bidi_tag_impl<std::is_base_of<
4000b57cec5SDimitry Andric       std::bidirectional_iterator_tag,
4010b57cec5SDimitry Andric       typename std::iterator_traits<IterT>::iterator_category>::value>::type;
4020b57cec5SDimitry Andric };
4030b57cec5SDimitry Andric 
4040b57cec5SDimitry Andric } // namespace detail
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric /// Defines filter_iterator to a suitable specialization of
4070b57cec5SDimitry Andric /// filter_iterator_impl, based on the underlying iterator's category.
4080b57cec5SDimitry Andric template <typename WrappedIteratorT, typename PredicateT>
4090b57cec5SDimitry Andric using filter_iterator = filter_iterator_impl<
4100b57cec5SDimitry Andric     WrappedIteratorT, PredicateT,
4110b57cec5SDimitry Andric     typename detail::fwd_or_bidi_tag<WrappedIteratorT>::type>;
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric /// Convenience function that takes a range of elements and a predicate,
4140b57cec5SDimitry Andric /// and return a new filter_iterator range.
4150b57cec5SDimitry Andric ///
4160b57cec5SDimitry Andric /// FIXME: Currently if RangeT && is a rvalue reference to a temporary, the
4170b57cec5SDimitry Andric /// lifetime of that temporary is not kept by the returned range object, and the
4180b57cec5SDimitry Andric /// temporary is going to be dropped on the floor after the make_iterator_range
4190b57cec5SDimitry Andric /// full expression that contains this function call.
4200b57cec5SDimitry Andric template <typename RangeT, typename PredicateT>
4210b57cec5SDimitry Andric iterator_range<filter_iterator<detail::IterOfRange<RangeT>, PredicateT>>
4220b57cec5SDimitry Andric make_filter_range(RangeT &&Range, PredicateT Pred) {
4230b57cec5SDimitry Andric   using FilterIteratorT =
4240b57cec5SDimitry Andric       filter_iterator<detail::IterOfRange<RangeT>, PredicateT>;
4250b57cec5SDimitry Andric   return make_range(
4260b57cec5SDimitry Andric       FilterIteratorT(std::begin(std::forward<RangeT>(Range)),
4270b57cec5SDimitry Andric                       std::end(std::forward<RangeT>(Range)), Pred),
4280b57cec5SDimitry Andric       FilterIteratorT(std::end(std::forward<RangeT>(Range)),
4290b57cec5SDimitry Andric                       std::end(std::forward<RangeT>(Range)), Pred));
4300b57cec5SDimitry Andric }
4310b57cec5SDimitry Andric 
4320b57cec5SDimitry Andric /// A pseudo-iterator adaptor that is designed to implement "early increment"
4330b57cec5SDimitry Andric /// style loops.
4340b57cec5SDimitry Andric ///
4350b57cec5SDimitry Andric /// This is *not a normal iterator* and should almost never be used directly. It
4360b57cec5SDimitry Andric /// is intended primarily to be used with range based for loops and some range
4370b57cec5SDimitry Andric /// algorithms.
4380b57cec5SDimitry Andric ///
4390b57cec5SDimitry Andric /// The iterator isn't quite an `OutputIterator` or an `InputIterator` but
4400b57cec5SDimitry Andric /// somewhere between them. The constraints of these iterators are:
4410b57cec5SDimitry Andric ///
4420b57cec5SDimitry Andric /// - On construction or after being incremented, it is comparable and
4430b57cec5SDimitry Andric ///   dereferencable. It is *not* incrementable.
4440b57cec5SDimitry Andric /// - After being dereferenced, it is neither comparable nor dereferencable, it
4450b57cec5SDimitry Andric ///   is only incrementable.
4460b57cec5SDimitry Andric ///
4470b57cec5SDimitry Andric /// This means you can only dereference the iterator once, and you can only
4480b57cec5SDimitry Andric /// increment it once between dereferences.
4490b57cec5SDimitry Andric template <typename WrappedIteratorT>
4500b57cec5SDimitry Andric class early_inc_iterator_impl
4510b57cec5SDimitry Andric     : public iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>,
4520b57cec5SDimitry Andric                                    WrappedIteratorT, std::input_iterator_tag> {
4530b57cec5SDimitry Andric   using BaseT =
4540b57cec5SDimitry Andric       iterator_adaptor_base<early_inc_iterator_impl<WrappedIteratorT>,
4550b57cec5SDimitry Andric                             WrappedIteratorT, std::input_iterator_tag>;
4560b57cec5SDimitry Andric 
4570b57cec5SDimitry Andric   using PointerT = typename std::iterator_traits<WrappedIteratorT>::pointer;
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric protected:
4600b57cec5SDimitry Andric #if LLVM_ENABLE_ABI_BREAKING_CHECKS
4610b57cec5SDimitry Andric   bool IsEarlyIncremented = false;
4620b57cec5SDimitry Andric #endif
4630b57cec5SDimitry Andric 
4640b57cec5SDimitry Andric public:
4650b57cec5SDimitry Andric   early_inc_iterator_impl(WrappedIteratorT I) : BaseT(I) {}
4660b57cec5SDimitry Andric 
4670b57cec5SDimitry Andric   using BaseT::operator*;
4680b57cec5SDimitry Andric   typename BaseT::reference operator*() {
4690b57cec5SDimitry Andric #if LLVM_ENABLE_ABI_BREAKING_CHECKS
4700b57cec5SDimitry Andric     assert(!IsEarlyIncremented && "Cannot dereference twice!");
4710b57cec5SDimitry Andric     IsEarlyIncremented = true;
4720b57cec5SDimitry Andric #endif
4730b57cec5SDimitry Andric     return *(this->I)++;
4740b57cec5SDimitry Andric   }
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric   using BaseT::operator++;
4770b57cec5SDimitry Andric   early_inc_iterator_impl &operator++() {
4780b57cec5SDimitry Andric #if LLVM_ENABLE_ABI_BREAKING_CHECKS
4790b57cec5SDimitry Andric     assert(IsEarlyIncremented && "Cannot increment before dereferencing!");
4800b57cec5SDimitry Andric     IsEarlyIncremented = false;
4810b57cec5SDimitry Andric #endif
4820b57cec5SDimitry Andric     return *this;
4830b57cec5SDimitry Andric   }
4840b57cec5SDimitry Andric 
4850b57cec5SDimitry Andric   using BaseT::operator==;
4860b57cec5SDimitry Andric   bool operator==(const early_inc_iterator_impl &RHS) const {
4870b57cec5SDimitry Andric #if LLVM_ENABLE_ABI_BREAKING_CHECKS
4880b57cec5SDimitry Andric     assert(!IsEarlyIncremented && "Cannot compare after dereferencing!");
4890b57cec5SDimitry Andric #endif
4900b57cec5SDimitry Andric     return BaseT::operator==(RHS);
4910b57cec5SDimitry Andric   }
4920b57cec5SDimitry Andric };
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric /// Make a range that does early increment to allow mutation of the underlying
4950b57cec5SDimitry Andric /// range without disrupting iteration.
4960b57cec5SDimitry Andric ///
4970b57cec5SDimitry Andric /// The underlying iterator will be incremented immediately after it is
4980b57cec5SDimitry Andric /// dereferenced, allowing deletion of the current node or insertion of nodes to
4990b57cec5SDimitry Andric /// not disrupt iteration provided they do not invalidate the *next* iterator --
5000b57cec5SDimitry Andric /// the current iterator can be invalidated.
5010b57cec5SDimitry Andric ///
5020b57cec5SDimitry Andric /// This requires a very exact pattern of use that is only really suitable to
5030b57cec5SDimitry Andric /// range based for loops and other range algorithms that explicitly guarantee
5040b57cec5SDimitry Andric /// to dereference exactly once each element, and to increment exactly once each
5050b57cec5SDimitry Andric /// element.
5060b57cec5SDimitry Andric template <typename RangeT>
5070b57cec5SDimitry Andric iterator_range<early_inc_iterator_impl<detail::IterOfRange<RangeT>>>
5080b57cec5SDimitry Andric make_early_inc_range(RangeT &&Range) {
5090b57cec5SDimitry Andric   using EarlyIncIteratorT =
5100b57cec5SDimitry Andric       early_inc_iterator_impl<detail::IterOfRange<RangeT>>;
5110b57cec5SDimitry Andric   return make_range(EarlyIncIteratorT(std::begin(std::forward<RangeT>(Range))),
5120b57cec5SDimitry Andric                     EarlyIncIteratorT(std::end(std::forward<RangeT>(Range))));
5130b57cec5SDimitry Andric }
5140b57cec5SDimitry Andric 
5150b57cec5SDimitry Andric // forward declarations required by zip_shortest/zip_first/zip_longest
5160b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
5170b57cec5SDimitry Andric bool all_of(R &&range, UnaryPredicate P);
5180b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
5190b57cec5SDimitry Andric bool any_of(R &&range, UnaryPredicate P);
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric namespace detail {
5220b57cec5SDimitry Andric 
5230b57cec5SDimitry Andric using std::declval;
5240b57cec5SDimitry Andric 
5250b57cec5SDimitry Andric // We have to alias this since inlining the actual type at the usage site
5260b57cec5SDimitry Andric // in the parameter list of iterator_facade_base<> below ICEs MSVC 2017.
5270b57cec5SDimitry Andric template<typename... Iters> struct ZipTupleType {
5280b57cec5SDimitry Andric   using type = std::tuple<decltype(*declval<Iters>())...>;
5290b57cec5SDimitry Andric };
5300b57cec5SDimitry Andric 
5310b57cec5SDimitry Andric template <typename ZipType, typename... Iters>
5320b57cec5SDimitry Andric using zip_traits = iterator_facade_base<
5330b57cec5SDimitry Andric     ZipType, typename std::common_type<std::bidirectional_iterator_tag,
5340b57cec5SDimitry Andric                                        typename std::iterator_traits<
5350b57cec5SDimitry Andric                                            Iters>::iterator_category...>::type,
5360b57cec5SDimitry Andric     // ^ TODO: Implement random access methods.
5370b57cec5SDimitry Andric     typename ZipTupleType<Iters...>::type,
5380b57cec5SDimitry Andric     typename std::iterator_traits<typename std::tuple_element<
5390b57cec5SDimitry Andric         0, std::tuple<Iters...>>::type>::difference_type,
5400b57cec5SDimitry Andric     // ^ FIXME: This follows boost::make_zip_iterator's assumption that all
5410b57cec5SDimitry Andric     // inner iterators have the same difference_type. It would fail if, for
5420b57cec5SDimitry Andric     // instance, the second field's difference_type were non-numeric while the
5430b57cec5SDimitry Andric     // first is.
5440b57cec5SDimitry Andric     typename ZipTupleType<Iters...>::type *,
5450b57cec5SDimitry Andric     typename ZipTupleType<Iters...>::type>;
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric template <typename ZipType, typename... Iters>
5480b57cec5SDimitry Andric struct zip_common : public zip_traits<ZipType, Iters...> {
5490b57cec5SDimitry Andric   using Base = zip_traits<ZipType, Iters...>;
5500b57cec5SDimitry Andric   using value_type = typename Base::value_type;
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric   std::tuple<Iters...> iterators;
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric protected:
555*8bcb0991SDimitry Andric   template <size_t... Ns> value_type deref(std::index_sequence<Ns...>) const {
5560b57cec5SDimitry Andric     return value_type(*std::get<Ns>(iterators)...);
5570b57cec5SDimitry Andric   }
5580b57cec5SDimitry Andric 
5590b57cec5SDimitry Andric   template <size_t... Ns>
560*8bcb0991SDimitry Andric   decltype(iterators) tup_inc(std::index_sequence<Ns...>) const {
5610b57cec5SDimitry Andric     return std::tuple<Iters...>(std::next(std::get<Ns>(iterators))...);
5620b57cec5SDimitry Andric   }
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric   template <size_t... Ns>
565*8bcb0991SDimitry Andric   decltype(iterators) tup_dec(std::index_sequence<Ns...>) const {
5660b57cec5SDimitry Andric     return std::tuple<Iters...>(std::prev(std::get<Ns>(iterators))...);
5670b57cec5SDimitry Andric   }
5680b57cec5SDimitry Andric 
5690b57cec5SDimitry Andric public:
5700b57cec5SDimitry Andric   zip_common(Iters &&... ts) : iterators(std::forward<Iters>(ts)...) {}
5710b57cec5SDimitry Andric 
572*8bcb0991SDimitry Andric   value_type operator*() { return deref(std::index_sequence_for<Iters...>{}); }
5730b57cec5SDimitry Andric 
5740b57cec5SDimitry Andric   const value_type operator*() const {
575*8bcb0991SDimitry Andric     return deref(std::index_sequence_for<Iters...>{});
5760b57cec5SDimitry Andric   }
5770b57cec5SDimitry Andric 
5780b57cec5SDimitry Andric   ZipType &operator++() {
579*8bcb0991SDimitry Andric     iterators = tup_inc(std::index_sequence_for<Iters...>{});
5800b57cec5SDimitry Andric     return *reinterpret_cast<ZipType *>(this);
5810b57cec5SDimitry Andric   }
5820b57cec5SDimitry Andric 
5830b57cec5SDimitry Andric   ZipType &operator--() {
5840b57cec5SDimitry Andric     static_assert(Base::IsBidirectional,
5850b57cec5SDimitry Andric                   "All inner iterators must be at least bidirectional.");
586*8bcb0991SDimitry Andric     iterators = tup_dec(std::index_sequence_for<Iters...>{});
5870b57cec5SDimitry Andric     return *reinterpret_cast<ZipType *>(this);
5880b57cec5SDimitry Andric   }
5890b57cec5SDimitry Andric };
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric template <typename... Iters>
5920b57cec5SDimitry Andric struct zip_first : public zip_common<zip_first<Iters...>, Iters...> {
5930b57cec5SDimitry Andric   using Base = zip_common<zip_first<Iters...>, Iters...>;
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   bool operator==(const zip_first<Iters...> &other) const {
5960b57cec5SDimitry Andric     return std::get<0>(this->iterators) == std::get<0>(other.iterators);
5970b57cec5SDimitry Andric   }
5980b57cec5SDimitry Andric 
5990b57cec5SDimitry Andric   zip_first(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {}
6000b57cec5SDimitry Andric };
6010b57cec5SDimitry Andric 
6020b57cec5SDimitry Andric template <typename... Iters>
6030b57cec5SDimitry Andric class zip_shortest : public zip_common<zip_shortest<Iters...>, Iters...> {
6040b57cec5SDimitry Andric   template <size_t... Ns>
605*8bcb0991SDimitry Andric   bool test(const zip_shortest<Iters...> &other,
606*8bcb0991SDimitry Andric             std::index_sequence<Ns...>) const {
6070b57cec5SDimitry Andric     return all_of(std::initializer_list<bool>{std::get<Ns>(this->iterators) !=
6080b57cec5SDimitry Andric                                               std::get<Ns>(other.iterators)...},
6090b57cec5SDimitry Andric                   identity<bool>{});
6100b57cec5SDimitry Andric   }
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric public:
6130b57cec5SDimitry Andric   using Base = zip_common<zip_shortest<Iters...>, Iters...>;
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric   zip_shortest(Iters &&... ts) : Base(std::forward<Iters>(ts)...) {}
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric   bool operator==(const zip_shortest<Iters...> &other) const {
618*8bcb0991SDimitry Andric     return !test(other, std::index_sequence_for<Iters...>{});
6190b57cec5SDimitry Andric   }
6200b57cec5SDimitry Andric };
6210b57cec5SDimitry Andric 
6220b57cec5SDimitry Andric template <template <typename...> class ItType, typename... Args> class zippy {
6230b57cec5SDimitry Andric public:
6240b57cec5SDimitry Andric   using iterator = ItType<decltype(std::begin(std::declval<Args>()))...>;
6250b57cec5SDimitry Andric   using iterator_category = typename iterator::iterator_category;
6260b57cec5SDimitry Andric   using value_type = typename iterator::value_type;
6270b57cec5SDimitry Andric   using difference_type = typename iterator::difference_type;
6280b57cec5SDimitry Andric   using pointer = typename iterator::pointer;
6290b57cec5SDimitry Andric   using reference = typename iterator::reference;
6300b57cec5SDimitry Andric 
6310b57cec5SDimitry Andric private:
6320b57cec5SDimitry Andric   std::tuple<Args...> ts;
6330b57cec5SDimitry Andric 
634*8bcb0991SDimitry Andric   template <size_t... Ns>
635*8bcb0991SDimitry Andric   iterator begin_impl(std::index_sequence<Ns...>) const {
6360b57cec5SDimitry Andric     return iterator(std::begin(std::get<Ns>(ts))...);
6370b57cec5SDimitry Andric   }
638*8bcb0991SDimitry Andric   template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) const {
6390b57cec5SDimitry Andric     return iterator(std::end(std::get<Ns>(ts))...);
6400b57cec5SDimitry Andric   }
6410b57cec5SDimitry Andric 
6420b57cec5SDimitry Andric public:
6430b57cec5SDimitry Andric   zippy(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {}
6440b57cec5SDimitry Andric 
645*8bcb0991SDimitry Andric   iterator begin() const {
646*8bcb0991SDimitry Andric     return begin_impl(std::index_sequence_for<Args...>{});
647*8bcb0991SDimitry Andric   }
648*8bcb0991SDimitry Andric   iterator end() const { return end_impl(std::index_sequence_for<Args...>{}); }
6490b57cec5SDimitry Andric };
6500b57cec5SDimitry Andric 
6510b57cec5SDimitry Andric } // end namespace detail
6520b57cec5SDimitry Andric 
6530b57cec5SDimitry Andric /// zip iterator for two or more iteratable types.
6540b57cec5SDimitry Andric template <typename T, typename U, typename... Args>
6550b57cec5SDimitry Andric detail::zippy<detail::zip_shortest, T, U, Args...> zip(T &&t, U &&u,
6560b57cec5SDimitry Andric                                                        Args &&... args) {
6570b57cec5SDimitry Andric   return detail::zippy<detail::zip_shortest, T, U, Args...>(
6580b57cec5SDimitry Andric       std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
6590b57cec5SDimitry Andric }
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric /// zip iterator that, for the sake of efficiency, assumes the first iteratee to
6620b57cec5SDimitry Andric /// be the shortest.
6630b57cec5SDimitry Andric template <typename T, typename U, typename... Args>
6640b57cec5SDimitry Andric detail::zippy<detail::zip_first, T, U, Args...> zip_first(T &&t, U &&u,
6650b57cec5SDimitry Andric                                                           Args &&... args) {
6660b57cec5SDimitry Andric   return detail::zippy<detail::zip_first, T, U, Args...>(
6670b57cec5SDimitry Andric       std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
6680b57cec5SDimitry Andric }
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric namespace detail {
6710b57cec5SDimitry Andric template <typename Iter>
6720b57cec5SDimitry Andric static Iter next_or_end(const Iter &I, const Iter &End) {
6730b57cec5SDimitry Andric   if (I == End)
6740b57cec5SDimitry Andric     return End;
6750b57cec5SDimitry Andric   return std::next(I);
6760b57cec5SDimitry Andric }
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric template <typename Iter>
6790b57cec5SDimitry Andric static auto deref_or_none(const Iter &I, const Iter &End)
6800b57cec5SDimitry Andric     -> llvm::Optional<typename std::remove_const<
6810b57cec5SDimitry Andric         typename std::remove_reference<decltype(*I)>::type>::type> {
6820b57cec5SDimitry Andric   if (I == End)
6830b57cec5SDimitry Andric     return None;
6840b57cec5SDimitry Andric   return *I;
6850b57cec5SDimitry Andric }
6860b57cec5SDimitry Andric 
6870b57cec5SDimitry Andric template <typename Iter> struct ZipLongestItemType {
6880b57cec5SDimitry Andric   using type =
6890b57cec5SDimitry Andric       llvm::Optional<typename std::remove_const<typename std::remove_reference<
6900b57cec5SDimitry Andric           decltype(*std::declval<Iter>())>::type>::type>;
6910b57cec5SDimitry Andric };
6920b57cec5SDimitry Andric 
6930b57cec5SDimitry Andric template <typename... Iters> struct ZipLongestTupleType {
6940b57cec5SDimitry Andric   using type = std::tuple<typename ZipLongestItemType<Iters>::type...>;
6950b57cec5SDimitry Andric };
6960b57cec5SDimitry Andric 
6970b57cec5SDimitry Andric template <typename... Iters>
6980b57cec5SDimitry Andric class zip_longest_iterator
6990b57cec5SDimitry Andric     : public iterator_facade_base<
7000b57cec5SDimitry Andric           zip_longest_iterator<Iters...>,
7010b57cec5SDimitry Andric           typename std::common_type<
7020b57cec5SDimitry Andric               std::forward_iterator_tag,
7030b57cec5SDimitry Andric               typename std::iterator_traits<Iters>::iterator_category...>::type,
7040b57cec5SDimitry Andric           typename ZipLongestTupleType<Iters...>::type,
7050b57cec5SDimitry Andric           typename std::iterator_traits<typename std::tuple_element<
7060b57cec5SDimitry Andric               0, std::tuple<Iters...>>::type>::difference_type,
7070b57cec5SDimitry Andric           typename ZipLongestTupleType<Iters...>::type *,
7080b57cec5SDimitry Andric           typename ZipLongestTupleType<Iters...>::type> {
7090b57cec5SDimitry Andric public:
7100b57cec5SDimitry Andric   using value_type = typename ZipLongestTupleType<Iters...>::type;
7110b57cec5SDimitry Andric 
7120b57cec5SDimitry Andric private:
7130b57cec5SDimitry Andric   std::tuple<Iters...> iterators;
7140b57cec5SDimitry Andric   std::tuple<Iters...> end_iterators;
7150b57cec5SDimitry Andric 
7160b57cec5SDimitry Andric   template <size_t... Ns>
7170b57cec5SDimitry Andric   bool test(const zip_longest_iterator<Iters...> &other,
718*8bcb0991SDimitry Andric             std::index_sequence<Ns...>) const {
7190b57cec5SDimitry Andric     return llvm::any_of(
7200b57cec5SDimitry Andric         std::initializer_list<bool>{std::get<Ns>(this->iterators) !=
7210b57cec5SDimitry Andric                                     std::get<Ns>(other.iterators)...},
7220b57cec5SDimitry Andric         identity<bool>{});
7230b57cec5SDimitry Andric   }
7240b57cec5SDimitry Andric 
725*8bcb0991SDimitry Andric   template <size_t... Ns> value_type deref(std::index_sequence<Ns...>) const {
7260b57cec5SDimitry Andric     return value_type(
7270b57cec5SDimitry Andric         deref_or_none(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
7280b57cec5SDimitry Andric   }
7290b57cec5SDimitry Andric 
7300b57cec5SDimitry Andric   template <size_t... Ns>
731*8bcb0991SDimitry Andric   decltype(iterators) tup_inc(std::index_sequence<Ns...>) const {
7320b57cec5SDimitry Andric     return std::tuple<Iters...>(
7330b57cec5SDimitry Andric         next_or_end(std::get<Ns>(iterators), std::get<Ns>(end_iterators))...);
7340b57cec5SDimitry Andric   }
7350b57cec5SDimitry Andric 
7360b57cec5SDimitry Andric public:
7370b57cec5SDimitry Andric   zip_longest_iterator(std::pair<Iters &&, Iters &&>... ts)
7380b57cec5SDimitry Andric       : iterators(std::forward<Iters>(ts.first)...),
7390b57cec5SDimitry Andric         end_iterators(std::forward<Iters>(ts.second)...) {}
7400b57cec5SDimitry Andric 
741*8bcb0991SDimitry Andric   value_type operator*() { return deref(std::index_sequence_for<Iters...>{}); }
7420b57cec5SDimitry Andric 
743*8bcb0991SDimitry Andric   value_type operator*() const {
744*8bcb0991SDimitry Andric     return deref(std::index_sequence_for<Iters...>{});
745*8bcb0991SDimitry Andric   }
7460b57cec5SDimitry Andric 
7470b57cec5SDimitry Andric   zip_longest_iterator<Iters...> &operator++() {
748*8bcb0991SDimitry Andric     iterators = tup_inc(std::index_sequence_for<Iters...>{});
7490b57cec5SDimitry Andric     return *this;
7500b57cec5SDimitry Andric   }
7510b57cec5SDimitry Andric 
7520b57cec5SDimitry Andric   bool operator==(const zip_longest_iterator<Iters...> &other) const {
753*8bcb0991SDimitry Andric     return !test(other, std::index_sequence_for<Iters...>{});
7540b57cec5SDimitry Andric   }
7550b57cec5SDimitry Andric };
7560b57cec5SDimitry Andric 
7570b57cec5SDimitry Andric template <typename... Args> class zip_longest_range {
7580b57cec5SDimitry Andric public:
7590b57cec5SDimitry Andric   using iterator =
7600b57cec5SDimitry Andric       zip_longest_iterator<decltype(adl_begin(std::declval<Args>()))...>;
7610b57cec5SDimitry Andric   using iterator_category = typename iterator::iterator_category;
7620b57cec5SDimitry Andric   using value_type = typename iterator::value_type;
7630b57cec5SDimitry Andric   using difference_type = typename iterator::difference_type;
7640b57cec5SDimitry Andric   using pointer = typename iterator::pointer;
7650b57cec5SDimitry Andric   using reference = typename iterator::reference;
7660b57cec5SDimitry Andric 
7670b57cec5SDimitry Andric private:
7680b57cec5SDimitry Andric   std::tuple<Args...> ts;
7690b57cec5SDimitry Andric 
770*8bcb0991SDimitry Andric   template <size_t... Ns>
771*8bcb0991SDimitry Andric   iterator begin_impl(std::index_sequence<Ns...>) const {
7720b57cec5SDimitry Andric     return iterator(std::make_pair(adl_begin(std::get<Ns>(ts)),
7730b57cec5SDimitry Andric                                    adl_end(std::get<Ns>(ts)))...);
7740b57cec5SDimitry Andric   }
7750b57cec5SDimitry Andric 
776*8bcb0991SDimitry Andric   template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) const {
7770b57cec5SDimitry Andric     return iterator(std::make_pair(adl_end(std::get<Ns>(ts)),
7780b57cec5SDimitry Andric                                    adl_end(std::get<Ns>(ts)))...);
7790b57cec5SDimitry Andric   }
7800b57cec5SDimitry Andric 
7810b57cec5SDimitry Andric public:
7820b57cec5SDimitry Andric   zip_longest_range(Args &&... ts_) : ts(std::forward<Args>(ts_)...) {}
7830b57cec5SDimitry Andric 
784*8bcb0991SDimitry Andric   iterator begin() const {
785*8bcb0991SDimitry Andric     return begin_impl(std::index_sequence_for<Args...>{});
786*8bcb0991SDimitry Andric   }
787*8bcb0991SDimitry Andric   iterator end() const { return end_impl(std::index_sequence_for<Args...>{}); }
7880b57cec5SDimitry Andric };
7890b57cec5SDimitry Andric } // namespace detail
7900b57cec5SDimitry Andric 
7910b57cec5SDimitry Andric /// Iterate over two or more iterators at the same time. Iteration continues
7920b57cec5SDimitry Andric /// until all iterators reach the end. The llvm::Optional only contains a value
7930b57cec5SDimitry Andric /// if the iterator has not reached the end.
7940b57cec5SDimitry Andric template <typename T, typename U, typename... Args>
7950b57cec5SDimitry Andric detail::zip_longest_range<T, U, Args...> zip_longest(T &&t, U &&u,
7960b57cec5SDimitry Andric                                                      Args &&... args) {
7970b57cec5SDimitry Andric   return detail::zip_longest_range<T, U, Args...>(
7980b57cec5SDimitry Andric       std::forward<T>(t), std::forward<U>(u), std::forward<Args>(args)...);
7990b57cec5SDimitry Andric }
8000b57cec5SDimitry Andric 
8010b57cec5SDimitry Andric /// Iterator wrapper that concatenates sequences together.
8020b57cec5SDimitry Andric ///
8030b57cec5SDimitry Andric /// This can concatenate different iterators, even with different types, into
8040b57cec5SDimitry Andric /// a single iterator provided the value types of all the concatenated
8050b57cec5SDimitry Andric /// iterators expose `reference` and `pointer` types that can be converted to
8060b57cec5SDimitry Andric /// `ValueT &` and `ValueT *` respectively. It doesn't support more
8070b57cec5SDimitry Andric /// interesting/customized pointer or reference types.
8080b57cec5SDimitry Andric ///
8090b57cec5SDimitry Andric /// Currently this only supports forward or higher iterator categories as
8100b57cec5SDimitry Andric /// inputs and always exposes a forward iterator interface.
8110b57cec5SDimitry Andric template <typename ValueT, typename... IterTs>
8120b57cec5SDimitry Andric class concat_iterator
8130b57cec5SDimitry Andric     : public iterator_facade_base<concat_iterator<ValueT, IterTs...>,
8140b57cec5SDimitry Andric                                   std::forward_iterator_tag, ValueT> {
8150b57cec5SDimitry Andric   using BaseT = typename concat_iterator::iterator_facade_base;
8160b57cec5SDimitry Andric 
8170b57cec5SDimitry Andric   /// We store both the current and end iterators for each concatenated
8180b57cec5SDimitry Andric   /// sequence in a tuple of pairs.
8190b57cec5SDimitry Andric   ///
8200b57cec5SDimitry Andric   /// Note that something like iterator_range seems nice at first here, but the
8210b57cec5SDimitry Andric   /// range properties are of little benefit and end up getting in the way
8220b57cec5SDimitry Andric   /// because we need to do mutation on the current iterators.
8230b57cec5SDimitry Andric   std::tuple<IterTs...> Begins;
8240b57cec5SDimitry Andric   std::tuple<IterTs...> Ends;
8250b57cec5SDimitry Andric 
8260b57cec5SDimitry Andric   /// Attempts to increment a specific iterator.
8270b57cec5SDimitry Andric   ///
8280b57cec5SDimitry Andric   /// Returns true if it was able to increment the iterator. Returns false if
8290b57cec5SDimitry Andric   /// the iterator is already at the end iterator.
8300b57cec5SDimitry Andric   template <size_t Index> bool incrementHelper() {
8310b57cec5SDimitry Andric     auto &Begin = std::get<Index>(Begins);
8320b57cec5SDimitry Andric     auto &End = std::get<Index>(Ends);
8330b57cec5SDimitry Andric     if (Begin == End)
8340b57cec5SDimitry Andric       return false;
8350b57cec5SDimitry Andric 
8360b57cec5SDimitry Andric     ++Begin;
8370b57cec5SDimitry Andric     return true;
8380b57cec5SDimitry Andric   }
8390b57cec5SDimitry Andric 
8400b57cec5SDimitry Andric   /// Increments the first non-end iterator.
8410b57cec5SDimitry Andric   ///
8420b57cec5SDimitry Andric   /// It is an error to call this with all iterators at the end.
843*8bcb0991SDimitry Andric   template <size_t... Ns> void increment(std::index_sequence<Ns...>) {
8440b57cec5SDimitry Andric     // Build a sequence of functions to increment each iterator if possible.
8450b57cec5SDimitry Andric     bool (concat_iterator::*IncrementHelperFns[])() = {
8460b57cec5SDimitry Andric         &concat_iterator::incrementHelper<Ns>...};
8470b57cec5SDimitry Andric 
8480b57cec5SDimitry Andric     // Loop over them, and stop as soon as we succeed at incrementing one.
8490b57cec5SDimitry Andric     for (auto &IncrementHelperFn : IncrementHelperFns)
8500b57cec5SDimitry Andric       if ((this->*IncrementHelperFn)())
8510b57cec5SDimitry Andric         return;
8520b57cec5SDimitry Andric 
8530b57cec5SDimitry Andric     llvm_unreachable("Attempted to increment an end concat iterator!");
8540b57cec5SDimitry Andric   }
8550b57cec5SDimitry Andric 
8560b57cec5SDimitry Andric   /// Returns null if the specified iterator is at the end. Otherwise,
8570b57cec5SDimitry Andric   /// dereferences the iterator and returns the address of the resulting
8580b57cec5SDimitry Andric   /// reference.
8590b57cec5SDimitry Andric   template <size_t Index> ValueT *getHelper() const {
8600b57cec5SDimitry Andric     auto &Begin = std::get<Index>(Begins);
8610b57cec5SDimitry Andric     auto &End = std::get<Index>(Ends);
8620b57cec5SDimitry Andric     if (Begin == End)
8630b57cec5SDimitry Andric       return nullptr;
8640b57cec5SDimitry Andric 
8650b57cec5SDimitry Andric     return &*Begin;
8660b57cec5SDimitry Andric   }
8670b57cec5SDimitry Andric 
8680b57cec5SDimitry Andric   /// Finds the first non-end iterator, dereferences, and returns the resulting
8690b57cec5SDimitry Andric   /// reference.
8700b57cec5SDimitry Andric   ///
8710b57cec5SDimitry Andric   /// It is an error to call this with all iterators at the end.
872*8bcb0991SDimitry Andric   template <size_t... Ns> ValueT &get(std::index_sequence<Ns...>) const {
8730b57cec5SDimitry Andric     // Build a sequence of functions to get from iterator if possible.
8740b57cec5SDimitry Andric     ValueT *(concat_iterator::*GetHelperFns[])() const = {
8750b57cec5SDimitry Andric         &concat_iterator::getHelper<Ns>...};
8760b57cec5SDimitry Andric 
8770b57cec5SDimitry Andric     // Loop over them, and return the first result we find.
8780b57cec5SDimitry Andric     for (auto &GetHelperFn : GetHelperFns)
8790b57cec5SDimitry Andric       if (ValueT *P = (this->*GetHelperFn)())
8800b57cec5SDimitry Andric         return *P;
8810b57cec5SDimitry Andric 
8820b57cec5SDimitry Andric     llvm_unreachable("Attempted to get a pointer from an end concat iterator!");
8830b57cec5SDimitry Andric   }
8840b57cec5SDimitry Andric 
8850b57cec5SDimitry Andric public:
8860b57cec5SDimitry Andric   /// Constructs an iterator from a squence of ranges.
8870b57cec5SDimitry Andric   ///
8880b57cec5SDimitry Andric   /// We need the full range to know how to switch between each of the
8890b57cec5SDimitry Andric   /// iterators.
8900b57cec5SDimitry Andric   template <typename... RangeTs>
8910b57cec5SDimitry Andric   explicit concat_iterator(RangeTs &&... Ranges)
8920b57cec5SDimitry Andric       : Begins(std::begin(Ranges)...), Ends(std::end(Ranges)...) {}
8930b57cec5SDimitry Andric 
8940b57cec5SDimitry Andric   using BaseT::operator++;
8950b57cec5SDimitry Andric 
8960b57cec5SDimitry Andric   concat_iterator &operator++() {
897*8bcb0991SDimitry Andric     increment(std::index_sequence_for<IterTs...>());
8980b57cec5SDimitry Andric     return *this;
8990b57cec5SDimitry Andric   }
9000b57cec5SDimitry Andric 
901*8bcb0991SDimitry Andric   ValueT &operator*() const {
902*8bcb0991SDimitry Andric     return get(std::index_sequence_for<IterTs...>());
903*8bcb0991SDimitry Andric   }
9040b57cec5SDimitry Andric 
9050b57cec5SDimitry Andric   bool operator==(const concat_iterator &RHS) const {
9060b57cec5SDimitry Andric     return Begins == RHS.Begins && Ends == RHS.Ends;
9070b57cec5SDimitry Andric   }
9080b57cec5SDimitry Andric };
9090b57cec5SDimitry Andric 
9100b57cec5SDimitry Andric namespace detail {
9110b57cec5SDimitry Andric 
9120b57cec5SDimitry Andric /// Helper to store a sequence of ranges being concatenated and access them.
9130b57cec5SDimitry Andric ///
9140b57cec5SDimitry Andric /// This is designed to facilitate providing actual storage when temporaries
9150b57cec5SDimitry Andric /// are passed into the constructor such that we can use it as part of range
9160b57cec5SDimitry Andric /// based for loops.
9170b57cec5SDimitry Andric template <typename ValueT, typename... RangeTs> class concat_range {
9180b57cec5SDimitry Andric public:
9190b57cec5SDimitry Andric   using iterator =
9200b57cec5SDimitry Andric       concat_iterator<ValueT,
9210b57cec5SDimitry Andric                       decltype(std::begin(std::declval<RangeTs &>()))...>;
9220b57cec5SDimitry Andric 
9230b57cec5SDimitry Andric private:
9240b57cec5SDimitry Andric   std::tuple<RangeTs...> Ranges;
9250b57cec5SDimitry Andric 
926*8bcb0991SDimitry Andric   template <size_t... Ns> iterator begin_impl(std::index_sequence<Ns...>) {
9270b57cec5SDimitry Andric     return iterator(std::get<Ns>(Ranges)...);
9280b57cec5SDimitry Andric   }
929*8bcb0991SDimitry Andric   template <size_t... Ns> iterator end_impl(std::index_sequence<Ns...>) {
9300b57cec5SDimitry Andric     return iterator(make_range(std::end(std::get<Ns>(Ranges)),
9310b57cec5SDimitry Andric                                std::end(std::get<Ns>(Ranges)))...);
9320b57cec5SDimitry Andric   }
9330b57cec5SDimitry Andric 
9340b57cec5SDimitry Andric public:
9350b57cec5SDimitry Andric   concat_range(RangeTs &&... Ranges)
9360b57cec5SDimitry Andric       : Ranges(std::forward<RangeTs>(Ranges)...) {}
9370b57cec5SDimitry Andric 
938*8bcb0991SDimitry Andric   iterator begin() { return begin_impl(std::index_sequence_for<RangeTs...>{}); }
939*8bcb0991SDimitry Andric   iterator end() { return end_impl(std::index_sequence_for<RangeTs...>{}); }
9400b57cec5SDimitry Andric };
9410b57cec5SDimitry Andric 
9420b57cec5SDimitry Andric } // end namespace detail
9430b57cec5SDimitry Andric 
9440b57cec5SDimitry Andric /// Concatenated range across two or more ranges.
9450b57cec5SDimitry Andric ///
9460b57cec5SDimitry Andric /// The desired value type must be explicitly specified.
9470b57cec5SDimitry Andric template <typename ValueT, typename... RangeTs>
9480b57cec5SDimitry Andric detail::concat_range<ValueT, RangeTs...> concat(RangeTs &&... Ranges) {
9490b57cec5SDimitry Andric   static_assert(sizeof...(RangeTs) > 1,
9500b57cec5SDimitry Andric                 "Need more than one range to concatenate!");
9510b57cec5SDimitry Andric   return detail::concat_range<ValueT, RangeTs...>(
9520b57cec5SDimitry Andric       std::forward<RangeTs>(Ranges)...);
9530b57cec5SDimitry Andric }
9540b57cec5SDimitry Andric 
9550b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
9560b57cec5SDimitry Andric //     Extra additions to <utility>
9570b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
9580b57cec5SDimitry Andric 
9590b57cec5SDimitry Andric /// Function object to check whether the first component of a std::pair
9600b57cec5SDimitry Andric /// compares less than the first component of another std::pair.
9610b57cec5SDimitry Andric struct less_first {
9620b57cec5SDimitry Andric   template <typename T> bool operator()(const T &lhs, const T &rhs) const {
9630b57cec5SDimitry Andric     return lhs.first < rhs.first;
9640b57cec5SDimitry Andric   }
9650b57cec5SDimitry Andric };
9660b57cec5SDimitry Andric 
9670b57cec5SDimitry Andric /// Function object to check whether the second component of a std::pair
9680b57cec5SDimitry Andric /// compares less than the second component of another std::pair.
9690b57cec5SDimitry Andric struct less_second {
9700b57cec5SDimitry Andric   template <typename T> bool operator()(const T &lhs, const T &rhs) const {
9710b57cec5SDimitry Andric     return lhs.second < rhs.second;
9720b57cec5SDimitry Andric   }
9730b57cec5SDimitry Andric };
9740b57cec5SDimitry Andric 
9750b57cec5SDimitry Andric /// \brief Function object to apply a binary function to the first component of
9760b57cec5SDimitry Andric /// a std::pair.
9770b57cec5SDimitry Andric template<typename FuncTy>
9780b57cec5SDimitry Andric struct on_first {
9790b57cec5SDimitry Andric   FuncTy func;
9800b57cec5SDimitry Andric 
9810b57cec5SDimitry Andric   template <typename T>
9820b57cec5SDimitry Andric   auto operator()(const T &lhs, const T &rhs) const
9830b57cec5SDimitry Andric       -> decltype(func(lhs.first, rhs.first)) {
9840b57cec5SDimitry Andric     return func(lhs.first, rhs.first);
9850b57cec5SDimitry Andric   }
9860b57cec5SDimitry Andric };
9870b57cec5SDimitry Andric 
9880b57cec5SDimitry Andric /// Utility type to build an inheritance chain that makes it easy to rank
9890b57cec5SDimitry Andric /// overload candidates.
9900b57cec5SDimitry Andric template <int N> struct rank : rank<N - 1> {};
9910b57cec5SDimitry Andric template <> struct rank<0> {};
9920b57cec5SDimitry Andric 
9930b57cec5SDimitry Andric /// traits class for checking whether type T is one of any of the given
9940b57cec5SDimitry Andric /// types in the variadic list.
9950b57cec5SDimitry Andric template <typename T, typename... Ts> struct is_one_of {
9960b57cec5SDimitry Andric   static const bool value = false;
9970b57cec5SDimitry Andric };
9980b57cec5SDimitry Andric 
9990b57cec5SDimitry Andric template <typename T, typename U, typename... Ts>
10000b57cec5SDimitry Andric struct is_one_of<T, U, Ts...> {
10010b57cec5SDimitry Andric   static const bool value =
10020b57cec5SDimitry Andric       std::is_same<T, U>::value || is_one_of<T, Ts...>::value;
10030b57cec5SDimitry Andric };
10040b57cec5SDimitry Andric 
10050b57cec5SDimitry Andric /// traits class for checking whether type T is a base class for all
10060b57cec5SDimitry Andric ///  the given types in the variadic list.
10070b57cec5SDimitry Andric template <typename T, typename... Ts> struct are_base_of {
10080b57cec5SDimitry Andric   static const bool value = true;
10090b57cec5SDimitry Andric };
10100b57cec5SDimitry Andric 
10110b57cec5SDimitry Andric template <typename T, typename U, typename... Ts>
10120b57cec5SDimitry Andric struct are_base_of<T, U, Ts...> {
10130b57cec5SDimitry Andric   static const bool value =
10140b57cec5SDimitry Andric       std::is_base_of<T, U>::value && are_base_of<T, Ts...>::value;
10150b57cec5SDimitry Andric };
10160b57cec5SDimitry Andric 
10170b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
10180b57cec5SDimitry Andric //     Extra additions for arrays
10190b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
10200b57cec5SDimitry Andric 
10210b57cec5SDimitry Andric /// Find the length of an array.
10220b57cec5SDimitry Andric template <class T, std::size_t N>
10230b57cec5SDimitry Andric constexpr inline size_t array_lengthof(T (&)[N]) {
10240b57cec5SDimitry Andric   return N;
10250b57cec5SDimitry Andric }
10260b57cec5SDimitry Andric 
10270b57cec5SDimitry Andric /// Adapt std::less<T> for array_pod_sort.
10280b57cec5SDimitry Andric template<typename T>
10290b57cec5SDimitry Andric inline int array_pod_sort_comparator(const void *P1, const void *P2) {
10300b57cec5SDimitry Andric   if (std::less<T>()(*reinterpret_cast<const T*>(P1),
10310b57cec5SDimitry Andric                      *reinterpret_cast<const T*>(P2)))
10320b57cec5SDimitry Andric     return -1;
10330b57cec5SDimitry Andric   if (std::less<T>()(*reinterpret_cast<const T*>(P2),
10340b57cec5SDimitry Andric                      *reinterpret_cast<const T*>(P1)))
10350b57cec5SDimitry Andric     return 1;
10360b57cec5SDimitry Andric   return 0;
10370b57cec5SDimitry Andric }
10380b57cec5SDimitry Andric 
10390b57cec5SDimitry Andric /// get_array_pod_sort_comparator - This is an internal helper function used to
10400b57cec5SDimitry Andric /// get type deduction of T right.
10410b57cec5SDimitry Andric template<typename T>
10420b57cec5SDimitry Andric inline int (*get_array_pod_sort_comparator(const T &))
10430b57cec5SDimitry Andric              (const void*, const void*) {
10440b57cec5SDimitry Andric   return array_pod_sort_comparator<T>;
10450b57cec5SDimitry Andric }
10460b57cec5SDimitry Andric 
10470b57cec5SDimitry Andric /// array_pod_sort - This sorts an array with the specified start and end
10480b57cec5SDimitry Andric /// extent.  This is just like std::sort, except that it calls qsort instead of
10490b57cec5SDimitry Andric /// using an inlined template.  qsort is slightly slower than std::sort, but
10500b57cec5SDimitry Andric /// most sorts are not performance critical in LLVM and std::sort has to be
10510b57cec5SDimitry Andric /// template instantiated for each type, leading to significant measured code
10520b57cec5SDimitry Andric /// bloat.  This function should generally be used instead of std::sort where
10530b57cec5SDimitry Andric /// possible.
10540b57cec5SDimitry Andric ///
10550b57cec5SDimitry Andric /// This function assumes that you have simple POD-like types that can be
10560b57cec5SDimitry Andric /// compared with std::less and can be moved with memcpy.  If this isn't true,
10570b57cec5SDimitry Andric /// you should use std::sort.
10580b57cec5SDimitry Andric ///
10590b57cec5SDimitry Andric /// NOTE: If qsort_r were portable, we could allow a custom comparator and
10600b57cec5SDimitry Andric /// default to std::less.
10610b57cec5SDimitry Andric template<class IteratorTy>
10620b57cec5SDimitry Andric inline void array_pod_sort(IteratorTy Start, IteratorTy End) {
10630b57cec5SDimitry Andric   // Don't inefficiently call qsort with one element or trigger undefined
10640b57cec5SDimitry Andric   // behavior with an empty sequence.
10650b57cec5SDimitry Andric   auto NElts = End - Start;
10660b57cec5SDimitry Andric   if (NElts <= 1) return;
10670b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
10680b57cec5SDimitry Andric   std::mt19937 Generator(std::random_device{}());
10690b57cec5SDimitry Andric   std::shuffle(Start, End, Generator);
10700b57cec5SDimitry Andric #endif
10710b57cec5SDimitry Andric   qsort(&*Start, NElts, sizeof(*Start), get_array_pod_sort_comparator(*Start));
10720b57cec5SDimitry Andric }
10730b57cec5SDimitry Andric 
10740b57cec5SDimitry Andric template <class IteratorTy>
10750b57cec5SDimitry Andric inline void array_pod_sort(
10760b57cec5SDimitry Andric     IteratorTy Start, IteratorTy End,
10770b57cec5SDimitry Andric     int (*Compare)(
10780b57cec5SDimitry Andric         const typename std::iterator_traits<IteratorTy>::value_type *,
10790b57cec5SDimitry Andric         const typename std::iterator_traits<IteratorTy>::value_type *)) {
10800b57cec5SDimitry Andric   // Don't inefficiently call qsort with one element or trigger undefined
10810b57cec5SDimitry Andric   // behavior with an empty sequence.
10820b57cec5SDimitry Andric   auto NElts = End - Start;
10830b57cec5SDimitry Andric   if (NElts <= 1) return;
10840b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
10850b57cec5SDimitry Andric   std::mt19937 Generator(std::random_device{}());
10860b57cec5SDimitry Andric   std::shuffle(Start, End, Generator);
10870b57cec5SDimitry Andric #endif
10880b57cec5SDimitry Andric   qsort(&*Start, NElts, sizeof(*Start),
10890b57cec5SDimitry Andric         reinterpret_cast<int (*)(const void *, const void *)>(Compare));
10900b57cec5SDimitry Andric }
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric // Provide wrappers to std::sort which shuffle the elements before sorting
10930b57cec5SDimitry Andric // to help uncover non-deterministic behavior (PR35135).
10940b57cec5SDimitry Andric template <typename IteratorTy>
10950b57cec5SDimitry Andric inline void sort(IteratorTy Start, IteratorTy End) {
10960b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
10970b57cec5SDimitry Andric   std::mt19937 Generator(std::random_device{}());
10980b57cec5SDimitry Andric   std::shuffle(Start, End, Generator);
10990b57cec5SDimitry Andric #endif
11000b57cec5SDimitry Andric   std::sort(Start, End);
11010b57cec5SDimitry Andric }
11020b57cec5SDimitry Andric 
11030b57cec5SDimitry Andric template <typename Container> inline void sort(Container &&C) {
11040b57cec5SDimitry Andric   llvm::sort(adl_begin(C), adl_end(C));
11050b57cec5SDimitry Andric }
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric template <typename IteratorTy, typename Compare>
11080b57cec5SDimitry Andric inline void sort(IteratorTy Start, IteratorTy End, Compare Comp) {
11090b57cec5SDimitry Andric #ifdef EXPENSIVE_CHECKS
11100b57cec5SDimitry Andric   std::mt19937 Generator(std::random_device{}());
11110b57cec5SDimitry Andric   std::shuffle(Start, End, Generator);
11120b57cec5SDimitry Andric #endif
11130b57cec5SDimitry Andric   std::sort(Start, End, Comp);
11140b57cec5SDimitry Andric }
11150b57cec5SDimitry Andric 
11160b57cec5SDimitry Andric template <typename Container, typename Compare>
11170b57cec5SDimitry Andric inline void sort(Container &&C, Compare Comp) {
11180b57cec5SDimitry Andric   llvm::sort(adl_begin(C), adl_end(C), Comp);
11190b57cec5SDimitry Andric }
11200b57cec5SDimitry Andric 
11210b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
11220b57cec5SDimitry Andric //     Extra additions to <algorithm>
11230b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
11240b57cec5SDimitry Andric 
11250b57cec5SDimitry Andric /// For a container of pointers, deletes the pointers and then clears the
11260b57cec5SDimitry Andric /// container.
11270b57cec5SDimitry Andric template<typename Container>
11280b57cec5SDimitry Andric void DeleteContainerPointers(Container &C) {
11290b57cec5SDimitry Andric   for (auto V : C)
11300b57cec5SDimitry Andric     delete V;
11310b57cec5SDimitry Andric   C.clear();
11320b57cec5SDimitry Andric }
11330b57cec5SDimitry Andric 
11340b57cec5SDimitry Andric /// In a container of pairs (usually a map) whose second element is a pointer,
11350b57cec5SDimitry Andric /// deletes the second elements and then clears the container.
11360b57cec5SDimitry Andric template<typename Container>
11370b57cec5SDimitry Andric void DeleteContainerSeconds(Container &C) {
11380b57cec5SDimitry Andric   for (auto &V : C)
11390b57cec5SDimitry Andric     delete V.second;
11400b57cec5SDimitry Andric   C.clear();
11410b57cec5SDimitry Andric }
11420b57cec5SDimitry Andric 
11430b57cec5SDimitry Andric /// Get the size of a range. This is a wrapper function around std::distance
11440b57cec5SDimitry Andric /// which is only enabled when the operation is O(1).
11450b57cec5SDimitry Andric template <typename R>
11460b57cec5SDimitry Andric auto size(R &&Range, typename std::enable_if<
11470b57cec5SDimitry Andric                          std::is_same<typename std::iterator_traits<decltype(
11480b57cec5SDimitry Andric                                           Range.begin())>::iterator_category,
11490b57cec5SDimitry Andric                                       std::random_access_iterator_tag>::value,
11500b57cec5SDimitry Andric                          void>::type * = nullptr)
11510b57cec5SDimitry Andric     -> decltype(std::distance(Range.begin(), Range.end())) {
11520b57cec5SDimitry Andric   return std::distance(Range.begin(), Range.end());
11530b57cec5SDimitry Andric }
11540b57cec5SDimitry Andric 
11550b57cec5SDimitry Andric /// Provide wrappers to std::for_each which take ranges instead of having to
11560b57cec5SDimitry Andric /// pass begin/end explicitly.
11570b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
11580b57cec5SDimitry Andric UnaryPredicate for_each(R &&Range, UnaryPredicate P) {
11590b57cec5SDimitry Andric   return std::for_each(adl_begin(Range), adl_end(Range), P);
11600b57cec5SDimitry Andric }
11610b57cec5SDimitry Andric 
11620b57cec5SDimitry Andric /// Provide wrappers to std::all_of which take ranges instead of having to pass
11630b57cec5SDimitry Andric /// begin/end explicitly.
11640b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
11650b57cec5SDimitry Andric bool all_of(R &&Range, UnaryPredicate P) {
11660b57cec5SDimitry Andric   return std::all_of(adl_begin(Range), adl_end(Range), P);
11670b57cec5SDimitry Andric }
11680b57cec5SDimitry Andric 
11690b57cec5SDimitry Andric /// Provide wrappers to std::any_of which take ranges instead of having to pass
11700b57cec5SDimitry Andric /// begin/end explicitly.
11710b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
11720b57cec5SDimitry Andric bool any_of(R &&Range, UnaryPredicate P) {
11730b57cec5SDimitry Andric   return std::any_of(adl_begin(Range), adl_end(Range), P);
11740b57cec5SDimitry Andric }
11750b57cec5SDimitry Andric 
11760b57cec5SDimitry Andric /// Provide wrappers to std::none_of which take ranges instead of having to pass
11770b57cec5SDimitry Andric /// begin/end explicitly.
11780b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
11790b57cec5SDimitry Andric bool none_of(R &&Range, UnaryPredicate P) {
11800b57cec5SDimitry Andric   return std::none_of(adl_begin(Range), adl_end(Range), P);
11810b57cec5SDimitry Andric }
11820b57cec5SDimitry Andric 
11830b57cec5SDimitry Andric /// Provide wrappers to std::find which take ranges instead of having to pass
11840b57cec5SDimitry Andric /// begin/end explicitly.
11850b57cec5SDimitry Andric template <typename R, typename T>
11860b57cec5SDimitry Andric auto find(R &&Range, const T &Val) -> decltype(adl_begin(Range)) {
11870b57cec5SDimitry Andric   return std::find(adl_begin(Range), adl_end(Range), Val);
11880b57cec5SDimitry Andric }
11890b57cec5SDimitry Andric 
11900b57cec5SDimitry Andric /// Provide wrappers to std::find_if which take ranges instead of having to pass
11910b57cec5SDimitry Andric /// begin/end explicitly.
11920b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
11930b57cec5SDimitry Andric auto find_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) {
11940b57cec5SDimitry Andric   return std::find_if(adl_begin(Range), adl_end(Range), P);
11950b57cec5SDimitry Andric }
11960b57cec5SDimitry Andric 
11970b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
11980b57cec5SDimitry Andric auto find_if_not(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) {
11990b57cec5SDimitry Andric   return std::find_if_not(adl_begin(Range), adl_end(Range), P);
12000b57cec5SDimitry Andric }
12010b57cec5SDimitry Andric 
12020b57cec5SDimitry Andric /// Provide wrappers to std::remove_if which take ranges instead of having to
12030b57cec5SDimitry Andric /// pass begin/end explicitly.
12040b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
12050b57cec5SDimitry Andric auto remove_if(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) {
12060b57cec5SDimitry Andric   return std::remove_if(adl_begin(Range), adl_end(Range), P);
12070b57cec5SDimitry Andric }
12080b57cec5SDimitry Andric 
12090b57cec5SDimitry Andric /// Provide wrappers to std::copy_if which take ranges instead of having to
12100b57cec5SDimitry Andric /// pass begin/end explicitly.
12110b57cec5SDimitry Andric template <typename R, typename OutputIt, typename UnaryPredicate>
12120b57cec5SDimitry Andric OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P) {
12130b57cec5SDimitry Andric   return std::copy_if(adl_begin(Range), adl_end(Range), Out, P);
12140b57cec5SDimitry Andric }
12150b57cec5SDimitry Andric 
12160b57cec5SDimitry Andric template <typename R, typename OutputIt>
12170b57cec5SDimitry Andric OutputIt copy(R &&Range, OutputIt Out) {
12180b57cec5SDimitry Andric   return std::copy(adl_begin(Range), adl_end(Range), Out);
12190b57cec5SDimitry Andric }
12200b57cec5SDimitry Andric 
12210b57cec5SDimitry Andric /// Wrapper function around std::find to detect if an element exists
12220b57cec5SDimitry Andric /// in a container.
12230b57cec5SDimitry Andric template <typename R, typename E>
12240b57cec5SDimitry Andric bool is_contained(R &&Range, const E &Element) {
12250b57cec5SDimitry Andric   return std::find(adl_begin(Range), adl_end(Range), Element) != adl_end(Range);
12260b57cec5SDimitry Andric }
12270b57cec5SDimitry Andric 
12280b57cec5SDimitry Andric /// Wrapper function around std::count to count the number of times an element
12290b57cec5SDimitry Andric /// \p Element occurs in the given range \p Range.
12300b57cec5SDimitry Andric template <typename R, typename E>
12310b57cec5SDimitry Andric auto count(R &&Range, const E &Element) ->
12320b57cec5SDimitry Andric     typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type {
12330b57cec5SDimitry Andric   return std::count(adl_begin(Range), adl_end(Range), Element);
12340b57cec5SDimitry Andric }
12350b57cec5SDimitry Andric 
12360b57cec5SDimitry Andric /// Wrapper function around std::count_if to count the number of times an
12370b57cec5SDimitry Andric /// element satisfying a given predicate occurs in a range.
12380b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
12390b57cec5SDimitry Andric auto count_if(R &&Range, UnaryPredicate P) ->
12400b57cec5SDimitry Andric     typename std::iterator_traits<decltype(adl_begin(Range))>::difference_type {
12410b57cec5SDimitry Andric   return std::count_if(adl_begin(Range), adl_end(Range), P);
12420b57cec5SDimitry Andric }
12430b57cec5SDimitry Andric 
12440b57cec5SDimitry Andric /// Wrapper function around std::transform to apply a function to a range and
12450b57cec5SDimitry Andric /// store the result elsewhere.
12460b57cec5SDimitry Andric template <typename R, typename OutputIt, typename UnaryPredicate>
12470b57cec5SDimitry Andric OutputIt transform(R &&Range, OutputIt d_first, UnaryPredicate P) {
12480b57cec5SDimitry Andric   return std::transform(adl_begin(Range), adl_end(Range), d_first, P);
12490b57cec5SDimitry Andric }
12500b57cec5SDimitry Andric 
12510b57cec5SDimitry Andric /// Provide wrappers to std::partition which take ranges instead of having to
12520b57cec5SDimitry Andric /// pass begin/end explicitly.
12530b57cec5SDimitry Andric template <typename R, typename UnaryPredicate>
12540b57cec5SDimitry Andric auto partition(R &&Range, UnaryPredicate P) -> decltype(adl_begin(Range)) {
12550b57cec5SDimitry Andric   return std::partition(adl_begin(Range), adl_end(Range), P);
12560b57cec5SDimitry Andric }
12570b57cec5SDimitry Andric 
12580b57cec5SDimitry Andric /// Provide wrappers to std::lower_bound which take ranges instead of having to
12590b57cec5SDimitry Andric /// pass begin/end explicitly.
12600b57cec5SDimitry Andric template <typename R, typename T>
12610b57cec5SDimitry Andric auto lower_bound(R &&Range, T &&Value) -> decltype(adl_begin(Range)) {
12620b57cec5SDimitry Andric   return std::lower_bound(adl_begin(Range), adl_end(Range),
12630b57cec5SDimitry Andric                           std::forward<T>(Value));
12640b57cec5SDimitry Andric }
12650b57cec5SDimitry Andric 
12660b57cec5SDimitry Andric template <typename R, typename T, typename Compare>
12670b57cec5SDimitry Andric auto lower_bound(R &&Range, T &&Value, Compare C)
12680b57cec5SDimitry Andric     -> decltype(adl_begin(Range)) {
12690b57cec5SDimitry Andric   return std::lower_bound(adl_begin(Range), adl_end(Range),
12700b57cec5SDimitry Andric                           std::forward<T>(Value), C);
12710b57cec5SDimitry Andric }
12720b57cec5SDimitry Andric 
12730b57cec5SDimitry Andric /// Provide wrappers to std::upper_bound which take ranges instead of having to
12740b57cec5SDimitry Andric /// pass begin/end explicitly.
12750b57cec5SDimitry Andric template <typename R, typename T>
12760b57cec5SDimitry Andric auto upper_bound(R &&Range, T &&Value) -> decltype(adl_begin(Range)) {
12770b57cec5SDimitry Andric   return std::upper_bound(adl_begin(Range), adl_end(Range),
12780b57cec5SDimitry Andric                           std::forward<T>(Value));
12790b57cec5SDimitry Andric }
12800b57cec5SDimitry Andric 
12810b57cec5SDimitry Andric template <typename R, typename T, typename Compare>
12820b57cec5SDimitry Andric auto upper_bound(R &&Range, T &&Value, Compare C)
12830b57cec5SDimitry Andric     -> decltype(adl_begin(Range)) {
12840b57cec5SDimitry Andric   return std::upper_bound(adl_begin(Range), adl_end(Range),
12850b57cec5SDimitry Andric                           std::forward<T>(Value), C);
12860b57cec5SDimitry Andric }
12870b57cec5SDimitry Andric 
12880b57cec5SDimitry Andric template <typename R>
12890b57cec5SDimitry Andric void stable_sort(R &&Range) {
12900b57cec5SDimitry Andric   std::stable_sort(adl_begin(Range), adl_end(Range));
12910b57cec5SDimitry Andric }
12920b57cec5SDimitry Andric 
12930b57cec5SDimitry Andric template <typename R, typename Compare>
12940b57cec5SDimitry Andric void stable_sort(R &&Range, Compare C) {
12950b57cec5SDimitry Andric   std::stable_sort(adl_begin(Range), adl_end(Range), C);
12960b57cec5SDimitry Andric }
12970b57cec5SDimitry Andric 
12980b57cec5SDimitry Andric /// Binary search for the first iterator in a range where a predicate is false.
12990b57cec5SDimitry Andric /// Requires that C is always true below some limit, and always false above it.
13000b57cec5SDimitry Andric template <typename R, typename Predicate,
13010b57cec5SDimitry Andric           typename Val = decltype(*adl_begin(std::declval<R>()))>
13020b57cec5SDimitry Andric auto partition_point(R &&Range, Predicate P) -> decltype(adl_begin(Range)) {
13030b57cec5SDimitry Andric   return std::partition_point(adl_begin(Range), adl_end(Range), P);
13040b57cec5SDimitry Andric }
13050b57cec5SDimitry Andric 
13060b57cec5SDimitry Andric /// Wrapper function around std::equal to detect if all elements
13070b57cec5SDimitry Andric /// in a container are same.
13080b57cec5SDimitry Andric template <typename R>
13090b57cec5SDimitry Andric bool is_splat(R &&Range) {
13100b57cec5SDimitry Andric   size_t range_size = size(Range);
13110b57cec5SDimitry Andric   return range_size != 0 && (range_size == 1 ||
13120b57cec5SDimitry Andric          std::equal(adl_begin(Range) + 1, adl_end(Range), adl_begin(Range)));
13130b57cec5SDimitry Andric }
13140b57cec5SDimitry Andric 
13150b57cec5SDimitry Andric /// Given a range of type R, iterate the entire range and return a
13160b57cec5SDimitry Andric /// SmallVector with elements of the vector.  This is useful, for example,
13170b57cec5SDimitry Andric /// when you want to iterate a range and then sort the results.
13180b57cec5SDimitry Andric template <unsigned Size, typename R>
13190b57cec5SDimitry Andric SmallVector<typename std::remove_const<detail::ValueOfRange<R>>::type, Size>
13200b57cec5SDimitry Andric to_vector(R &&Range) {
13210b57cec5SDimitry Andric   return {adl_begin(Range), adl_end(Range)};
13220b57cec5SDimitry Andric }
13230b57cec5SDimitry Andric 
13240b57cec5SDimitry Andric /// Provide a container algorithm similar to C++ Library Fundamentals v2's
13250b57cec5SDimitry Andric /// `erase_if` which is equivalent to:
13260b57cec5SDimitry Andric ///
13270b57cec5SDimitry Andric ///   C.erase(remove_if(C, pred), C.end());
13280b57cec5SDimitry Andric ///
13290b57cec5SDimitry Andric /// This version works for any container with an erase method call accepting
13300b57cec5SDimitry Andric /// two iterators.
13310b57cec5SDimitry Andric template <typename Container, typename UnaryPredicate>
13320b57cec5SDimitry Andric void erase_if(Container &C, UnaryPredicate P) {
13330b57cec5SDimitry Andric   C.erase(remove_if(C, P), C.end());
13340b57cec5SDimitry Andric }
13350b57cec5SDimitry Andric 
13360b57cec5SDimitry Andric /// Given a sequence container Cont, replace the range [ContIt, ContEnd) with
13370b57cec5SDimitry Andric /// the range [ValIt, ValEnd) (which is not from the same container).
13380b57cec5SDimitry Andric template<typename Container, typename RandomAccessIterator>
13390b57cec5SDimitry Andric void replace(Container &Cont, typename Container::iterator ContIt,
13400b57cec5SDimitry Andric              typename Container::iterator ContEnd, RandomAccessIterator ValIt,
13410b57cec5SDimitry Andric              RandomAccessIterator ValEnd) {
13420b57cec5SDimitry Andric   while (true) {
13430b57cec5SDimitry Andric     if (ValIt == ValEnd) {
13440b57cec5SDimitry Andric       Cont.erase(ContIt, ContEnd);
13450b57cec5SDimitry Andric       return;
13460b57cec5SDimitry Andric     } else if (ContIt == ContEnd) {
13470b57cec5SDimitry Andric       Cont.insert(ContIt, ValIt, ValEnd);
13480b57cec5SDimitry Andric       return;
13490b57cec5SDimitry Andric     }
13500b57cec5SDimitry Andric     *ContIt++ = *ValIt++;
13510b57cec5SDimitry Andric   }
13520b57cec5SDimitry Andric }
13530b57cec5SDimitry Andric 
13540b57cec5SDimitry Andric /// Given a sequence container Cont, replace the range [ContIt, ContEnd) with
13550b57cec5SDimitry Andric /// the range R.
13560b57cec5SDimitry Andric template<typename Container, typename Range = std::initializer_list<
13570b57cec5SDimitry Andric                                  typename Container::value_type>>
13580b57cec5SDimitry Andric void replace(Container &Cont, typename Container::iterator ContIt,
13590b57cec5SDimitry Andric              typename Container::iterator ContEnd, Range R) {
13600b57cec5SDimitry Andric   replace(Cont, ContIt, ContEnd, R.begin(), R.end());
13610b57cec5SDimitry Andric }
13620b57cec5SDimitry Andric 
13630b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13640b57cec5SDimitry Andric //     Extra additions to <memory>
13650b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
13660b57cec5SDimitry Andric 
13670b57cec5SDimitry Andric struct FreeDeleter {
13680b57cec5SDimitry Andric   void operator()(void* v) {
13690b57cec5SDimitry Andric     ::free(v);
13700b57cec5SDimitry Andric   }
13710b57cec5SDimitry Andric };
13720b57cec5SDimitry Andric 
13730b57cec5SDimitry Andric template<typename First, typename Second>
13740b57cec5SDimitry Andric struct pair_hash {
13750b57cec5SDimitry Andric   size_t operator()(const std::pair<First, Second> &P) const {
13760b57cec5SDimitry Andric     return std::hash<First>()(P.first) * 31 + std::hash<Second>()(P.second);
13770b57cec5SDimitry Andric   }
13780b57cec5SDimitry Andric };
13790b57cec5SDimitry Andric 
13800b57cec5SDimitry Andric /// Binary functor that adapts to any other binary functor after dereferencing
13810b57cec5SDimitry Andric /// operands.
13820b57cec5SDimitry Andric template <typename T> struct deref {
13830b57cec5SDimitry Andric   T func;
13840b57cec5SDimitry Andric 
13850b57cec5SDimitry Andric   // Could be further improved to cope with non-derivable functors and
13860b57cec5SDimitry Andric   // non-binary functors (should be a variadic template member function
13870b57cec5SDimitry Andric   // operator()).
13880b57cec5SDimitry Andric   template <typename A, typename B>
13890b57cec5SDimitry Andric   auto operator()(A &lhs, B &rhs) const -> decltype(func(*lhs, *rhs)) {
13900b57cec5SDimitry Andric     assert(lhs);
13910b57cec5SDimitry Andric     assert(rhs);
13920b57cec5SDimitry Andric     return func(*lhs, *rhs);
13930b57cec5SDimitry Andric   }
13940b57cec5SDimitry Andric };
13950b57cec5SDimitry Andric 
13960b57cec5SDimitry Andric namespace detail {
13970b57cec5SDimitry Andric 
13980b57cec5SDimitry Andric template <typename R> class enumerator_iter;
13990b57cec5SDimitry Andric 
14000b57cec5SDimitry Andric template <typename R> struct result_pair {
14010b57cec5SDimitry Andric   using value_reference =
14020b57cec5SDimitry Andric       typename std::iterator_traits<IterOfRange<R>>::reference;
14030b57cec5SDimitry Andric 
14040b57cec5SDimitry Andric   friend class enumerator_iter<R>;
14050b57cec5SDimitry Andric 
14060b57cec5SDimitry Andric   result_pair() = default;
14070b57cec5SDimitry Andric   result_pair(std::size_t Index, IterOfRange<R> Iter)
14080b57cec5SDimitry Andric       : Index(Index), Iter(Iter) {}
14090b57cec5SDimitry Andric 
14100b57cec5SDimitry Andric   result_pair<R> &operator=(const result_pair<R> &Other) {
14110b57cec5SDimitry Andric     Index = Other.Index;
14120b57cec5SDimitry Andric     Iter = Other.Iter;
14130b57cec5SDimitry Andric     return *this;
14140b57cec5SDimitry Andric   }
14150b57cec5SDimitry Andric 
14160b57cec5SDimitry Andric   std::size_t index() const { return Index; }
14170b57cec5SDimitry Andric   const value_reference value() const { return *Iter; }
14180b57cec5SDimitry Andric   value_reference value() { return *Iter; }
14190b57cec5SDimitry Andric 
14200b57cec5SDimitry Andric private:
14210b57cec5SDimitry Andric   std::size_t Index = std::numeric_limits<std::size_t>::max();
14220b57cec5SDimitry Andric   IterOfRange<R> Iter;
14230b57cec5SDimitry Andric };
14240b57cec5SDimitry Andric 
14250b57cec5SDimitry Andric template <typename R>
14260b57cec5SDimitry Andric class enumerator_iter
14270b57cec5SDimitry Andric     : public iterator_facade_base<
14280b57cec5SDimitry Andric           enumerator_iter<R>, std::forward_iterator_tag, result_pair<R>,
14290b57cec5SDimitry Andric           typename std::iterator_traits<IterOfRange<R>>::difference_type,
14300b57cec5SDimitry Andric           typename std::iterator_traits<IterOfRange<R>>::pointer,
14310b57cec5SDimitry Andric           typename std::iterator_traits<IterOfRange<R>>::reference> {
14320b57cec5SDimitry Andric   using result_type = result_pair<R>;
14330b57cec5SDimitry Andric 
14340b57cec5SDimitry Andric public:
14350b57cec5SDimitry Andric   explicit enumerator_iter(IterOfRange<R> EndIter)
14360b57cec5SDimitry Andric       : Result(std::numeric_limits<size_t>::max(), EndIter) {}
14370b57cec5SDimitry Andric 
14380b57cec5SDimitry Andric   enumerator_iter(std::size_t Index, IterOfRange<R> Iter)
14390b57cec5SDimitry Andric       : Result(Index, Iter) {}
14400b57cec5SDimitry Andric 
14410b57cec5SDimitry Andric   result_type &operator*() { return Result; }
14420b57cec5SDimitry Andric   const result_type &operator*() const { return Result; }
14430b57cec5SDimitry Andric 
14440b57cec5SDimitry Andric   enumerator_iter<R> &operator++() {
14450b57cec5SDimitry Andric     assert(Result.Index != std::numeric_limits<size_t>::max());
14460b57cec5SDimitry Andric     ++Result.Iter;
14470b57cec5SDimitry Andric     ++Result.Index;
14480b57cec5SDimitry Andric     return *this;
14490b57cec5SDimitry Andric   }
14500b57cec5SDimitry Andric 
14510b57cec5SDimitry Andric   bool operator==(const enumerator_iter<R> &RHS) const {
14520b57cec5SDimitry Andric     // Don't compare indices here, only iterators.  It's possible for an end
14530b57cec5SDimitry Andric     // iterator to have different indices depending on whether it was created
14540b57cec5SDimitry Andric     // by calling std::end() versus incrementing a valid iterator.
14550b57cec5SDimitry Andric     return Result.Iter == RHS.Result.Iter;
14560b57cec5SDimitry Andric   }
14570b57cec5SDimitry Andric 
14580b57cec5SDimitry Andric   enumerator_iter<R> &operator=(const enumerator_iter<R> &Other) {
14590b57cec5SDimitry Andric     Result = Other.Result;
14600b57cec5SDimitry Andric     return *this;
14610b57cec5SDimitry Andric   }
14620b57cec5SDimitry Andric 
14630b57cec5SDimitry Andric private:
14640b57cec5SDimitry Andric   result_type Result;
14650b57cec5SDimitry Andric };
14660b57cec5SDimitry Andric 
14670b57cec5SDimitry Andric template <typename R> class enumerator {
14680b57cec5SDimitry Andric public:
14690b57cec5SDimitry Andric   explicit enumerator(R &&Range) : TheRange(std::forward<R>(Range)) {}
14700b57cec5SDimitry Andric 
14710b57cec5SDimitry Andric   enumerator_iter<R> begin() {
14720b57cec5SDimitry Andric     return enumerator_iter<R>(0, std::begin(TheRange));
14730b57cec5SDimitry Andric   }
14740b57cec5SDimitry Andric 
14750b57cec5SDimitry Andric   enumerator_iter<R> end() {
14760b57cec5SDimitry Andric     return enumerator_iter<R>(std::end(TheRange));
14770b57cec5SDimitry Andric   }
14780b57cec5SDimitry Andric 
14790b57cec5SDimitry Andric private:
14800b57cec5SDimitry Andric   R TheRange;
14810b57cec5SDimitry Andric };
14820b57cec5SDimitry Andric 
14830b57cec5SDimitry Andric } // end namespace detail
14840b57cec5SDimitry Andric 
14850b57cec5SDimitry Andric /// Given an input range, returns a new range whose values are are pair (A,B)
14860b57cec5SDimitry Andric /// such that A is the 0-based index of the item in the sequence, and B is
14870b57cec5SDimitry Andric /// the value from the original sequence.  Example:
14880b57cec5SDimitry Andric ///
14890b57cec5SDimitry Andric /// std::vector<char> Items = {'A', 'B', 'C', 'D'};
14900b57cec5SDimitry Andric /// for (auto X : enumerate(Items)) {
14910b57cec5SDimitry Andric ///   printf("Item %d - %c\n", X.index(), X.value());
14920b57cec5SDimitry Andric /// }
14930b57cec5SDimitry Andric ///
14940b57cec5SDimitry Andric /// Output:
14950b57cec5SDimitry Andric ///   Item 0 - A
14960b57cec5SDimitry Andric ///   Item 1 - B
14970b57cec5SDimitry Andric ///   Item 2 - C
14980b57cec5SDimitry Andric ///   Item 3 - D
14990b57cec5SDimitry Andric ///
15000b57cec5SDimitry Andric template <typename R> detail::enumerator<R> enumerate(R &&TheRange) {
15010b57cec5SDimitry Andric   return detail::enumerator<R>(std::forward<R>(TheRange));
15020b57cec5SDimitry Andric }
15030b57cec5SDimitry Andric 
15040b57cec5SDimitry Andric namespace detail {
15050b57cec5SDimitry Andric 
15060b57cec5SDimitry Andric template <typename F, typename Tuple, std::size_t... I>
1507*8bcb0991SDimitry Andric auto apply_tuple_impl(F &&f, Tuple &&t, std::index_sequence<I...>)
15080b57cec5SDimitry Andric     -> decltype(std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...)) {
15090b57cec5SDimitry Andric   return std::forward<F>(f)(std::get<I>(std::forward<Tuple>(t))...);
15100b57cec5SDimitry Andric }
15110b57cec5SDimitry Andric 
15120b57cec5SDimitry Andric } // end namespace detail
15130b57cec5SDimitry Andric 
15140b57cec5SDimitry Andric /// Given an input tuple (a1, a2, ..., an), pass the arguments of the
15150b57cec5SDimitry Andric /// tuple variadically to f as if by calling f(a1, a2, ..., an) and
15160b57cec5SDimitry Andric /// return the result.
15170b57cec5SDimitry Andric template <typename F, typename Tuple>
15180b57cec5SDimitry Andric auto apply_tuple(F &&f, Tuple &&t) -> decltype(detail::apply_tuple_impl(
15190b57cec5SDimitry Andric     std::forward<F>(f), std::forward<Tuple>(t),
1520*8bcb0991SDimitry Andric     std::make_index_sequence<
15210b57cec5SDimitry Andric         std::tuple_size<typename std::decay<Tuple>::type>::value>{})) {
1522*8bcb0991SDimitry Andric   using Indices = std::make_index_sequence<
15230b57cec5SDimitry Andric       std::tuple_size<typename std::decay<Tuple>::type>::value>;
15240b57cec5SDimitry Andric 
15250b57cec5SDimitry Andric   return detail::apply_tuple_impl(std::forward<F>(f), std::forward<Tuple>(t),
15260b57cec5SDimitry Andric                                   Indices{});
15270b57cec5SDimitry Andric }
15280b57cec5SDimitry Andric 
15290b57cec5SDimitry Andric /// Return true if the sequence [Begin, End) has exactly N items. Runs in O(N)
15300b57cec5SDimitry Andric /// time. Not meant for use with random-access iterators.
15310b57cec5SDimitry Andric template <typename IterTy>
15320b57cec5SDimitry Andric bool hasNItems(
15330b57cec5SDimitry Andric     IterTy &&Begin, IterTy &&End, unsigned N,
15340b57cec5SDimitry Andric     typename std::enable_if<
15350b57cec5SDimitry Andric         !std::is_same<
15360b57cec5SDimitry Andric             typename std::iterator_traits<typename std::remove_reference<
15370b57cec5SDimitry Andric                 decltype(Begin)>::type>::iterator_category,
15380b57cec5SDimitry Andric             std::random_access_iterator_tag>::value,
15390b57cec5SDimitry Andric         void>::type * = nullptr) {
15400b57cec5SDimitry Andric   for (; N; --N, ++Begin)
15410b57cec5SDimitry Andric     if (Begin == End)
15420b57cec5SDimitry Andric       return false; // Too few.
15430b57cec5SDimitry Andric   return Begin == End;
15440b57cec5SDimitry Andric }
15450b57cec5SDimitry Andric 
15460b57cec5SDimitry Andric /// Return true if the sequence [Begin, End) has N or more items. Runs in O(N)
15470b57cec5SDimitry Andric /// time. Not meant for use with random-access iterators.
15480b57cec5SDimitry Andric template <typename IterTy>
15490b57cec5SDimitry Andric bool hasNItemsOrMore(
15500b57cec5SDimitry Andric     IterTy &&Begin, IterTy &&End, unsigned N,
15510b57cec5SDimitry Andric     typename std::enable_if<
15520b57cec5SDimitry Andric         !std::is_same<
15530b57cec5SDimitry Andric             typename std::iterator_traits<typename std::remove_reference<
15540b57cec5SDimitry Andric                 decltype(Begin)>::type>::iterator_category,
15550b57cec5SDimitry Andric             std::random_access_iterator_tag>::value,
15560b57cec5SDimitry Andric         void>::type * = nullptr) {
15570b57cec5SDimitry Andric   for (; N; --N, ++Begin)
15580b57cec5SDimitry Andric     if (Begin == End)
15590b57cec5SDimitry Andric       return false; // Too few.
15600b57cec5SDimitry Andric   return true;
15610b57cec5SDimitry Andric }
15620b57cec5SDimitry Andric 
15630b57cec5SDimitry Andric /// Returns a raw pointer that represents the same address as the argument.
15640b57cec5SDimitry Andric ///
15650b57cec5SDimitry Andric /// The late bound return should be removed once we move to C++14 to better
15660b57cec5SDimitry Andric /// align with the C++20 declaration. Also, this implementation can be removed
15670b57cec5SDimitry Andric /// once we move to C++20 where it's defined as std::to_addres()
15680b57cec5SDimitry Andric ///
15690b57cec5SDimitry Andric /// The std::pointer_traits<>::to_address(p) variations of these overloads has
15700b57cec5SDimitry Andric /// not been implemented.
15710b57cec5SDimitry Andric template <class Ptr> auto to_address(const Ptr &P) -> decltype(P.operator->()) {
15720b57cec5SDimitry Andric   return P.operator->();
15730b57cec5SDimitry Andric }
15740b57cec5SDimitry Andric template <class T> constexpr T *to_address(T *P) { return P; }
15750b57cec5SDimitry Andric 
15760b57cec5SDimitry Andric } // end namespace llvm
15770b57cec5SDimitry Andric 
15780b57cec5SDimitry Andric #endif // LLVM_ADT_STLEXTRAS_H
1579