llvm/llvm/unittests/ADT/IteratorTest.cpp

//===- IteratorTest.cpp - Unit tests for iterator utilities ---------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/iterator.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/ilist.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <optional>
#include <type_traits>
#include <vector>

usingnamespacellvm;
ElementsAre;

namespace {

template <int> struct Shadow;

struct WeirdIter
    : llvm::iterator_facade_base<WeirdIter, std::input_iterator_tag, Shadow<0>,
                                 Shadow<1>, Shadow<2>, Shadow<3>> {};

struct AdaptedIter : iterator_adaptor_base<AdaptedIter, WeirdIter> {};

// Test that iterator_adaptor_base forwards typedefs, if value_type is
// unchanged.
static_assert;
static_assert;
static_assert;
static_assert;

// Ensure that pointe{e,r}_iterator adaptors correctly forward the category of
// the underlying iterator.

RandomAccessIter;
BidiIter;

pointee_iterator_defaulted;
pointer_iterator_defaulted;

// Ensures that an iterator and its adaptation have the same iterator_category.
IsAdaptedIterCategorySame;

// Check that dereferencing works correctly adapting pointers and proxies.
template <class T>
struct PointerWrapper : public iterator_adaptor_base<PointerWrapper<T>, T *> {};
struct IntProxy {};
struct ConstIntProxy {};
template <class T, class ProxyT>
struct PointerProxyWrapper
    : public iterator_adaptor_base<PointerProxyWrapper<T, ProxyT>, T *,
                                   std::random_access_iterator_tag, T,
                                   ptrdiff_t, T *, ProxyT> {};
IntIterator;
ConstIntIterator;
IntProxyIterator;
ConstIntProxyIterator;

// There should only be a single (const-qualified) operator*, operator->, and
// operator[]. This test confirms that there isn't a non-const overload. Rather
// than adding those, users should double-check that T, PointerT, and ReferenceT
// have the right constness, and/or make fields mutable.
static_assert;
static_assert;
static_assert;

template <class T, std::enable_if_t<std::is_assignable_v<T, int>, bool> = false>
constexpr bool canAssignFromInt(T &&) {}
template <class T,
          std::enable_if_t<!std::is_assignable_v<T, int>, bool> = false>
constexpr bool canAssignFromInt(T &&) {}

TEST(IteratorAdaptorTest, Dereference) {}

// pointeE_iterator
static_assert;
static_assert;
// pointeR_iterator
static_assert;
static_assert;

TEST(PointeeIteratorTest, Basic) {}

TEST(PointeeIteratorTest, SmartPointer) {}

TEST(PointeeIteratorTest, Range) {}

TEST(PointeeIteratorTest, PointeeType) {}

TEST(FilterIteratorTest, Lambda) {}

TEST(FilterIteratorTest, Enumerate) {}

TEST(FilterIteratorTest, CallableObject) {}

TEST(FilterIteratorTest, FunctionPointer) {}

TEST(FilterIteratorTest, Composition) {}

TEST(FilterIteratorTest, InputIterator) {}

TEST(FilterIteratorTest, ReverseFilterRange) {}

TEST(PointerIterator, Basic) {}

TEST(PointerIterator, Const) {}

TEST(PointerIterator, Range) {}

namespace rbegin_detail {
struct WithFreeRBegin {};

auto rbegin(const WithFreeRBegin &X) {}
auto rend(const WithFreeRBegin &X) {}
} // namespace rbegin_detail

TEST(ReverseTest, ADL) {}

TEST(ZipIteratorTest, Basic) {}

TEST(ZipIteratorTest, ZipEqualBasic) {}

IsConstRef;

IsBoolConstRef;

/// Returns a `const` copy of the passed value. The `const` on the returned
/// value is intentional here so that `MakeConst` can be used in range-for
/// loops.
template <typename T> const T MakeConst(T &&value) {}

TEST(ZipIteratorTest, ZipEqualConstCorrectness) {}

TEST(ZipIteratorTest, ZipEqualTemporaries) {}

#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
// Check that an assertion is triggered when ranges passed to `zip_equal` differ
// in length.
TEST(ZipIteratorTest, ZipEqualNotEqual) {
  const SmallVector<unsigned, 6> pi = {3, 1, 4, 1, 5, 8};
  const SmallVector<bool, 2> vals = {1, 1};

  EXPECT_DEATH(zip_equal(pi, vals), "Iteratees do not have equal length");
  EXPECT_DEATH(zip_equal(vals, pi), "Iteratees do not have equal length");
  EXPECT_DEATH(zip_equal(pi, pi, vals), "Iteratees do not have equal length");
  EXPECT_DEATH(zip_equal(vals, vals, pi), "Iteratees do not have equal length");
}
#endif

TEST(ZipIteratorTest, ZipFirstBasic) {}

#if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST
// Make sure that we can detect when the first range is not the shortest.
TEST(ZipIteratorTest, ZipFirstNotShortest) {
  const std::array<unsigned, 6> longer = {};
  const std::array<unsigned, 4> shorter = {};

  EXPECT_DEATH(zip_first(longer, shorter),
               "First iteratee is not the shortest");
  EXPECT_DEATH(zip_first(longer, shorter, longer),
               "First iteratee is not the shortest");
  EXPECT_DEATH(zip_first(longer, longer, shorter),
               "First iteratee is not the shortest");
}
#endif

TEST(ZipIteratorTest, ZipLongestBasic) {}

TEST(ZipIteratorTest, Mutability) {}

TEST(ZipIteratorTest, ZipFirstMutability) {}

TEST(ZipIteratorTest, Filter) {}

TEST(ZipIteratorTest, Reverse) {}

// Int iterator that keeps track of the number of its copies.
struct CountingIntIterator : IntIterator {};

// Check that the iterators do not get copied with each `zippy` iterator
// increment.
TEST(ZipIteratorTest, IteratorCopies) {}

TEST(RangeTest, Distance) {}

TEST(RangeSizeTest, CommonRangeTypes) {}

struct FooWithMemberSize {};

TEST(RangeSizeTest, MemberSize) {}

struct FooWithFreeSize {};

TEST(RangeSizeTest, FreeSize) {}

struct FooWithDistance {};

TEST(RangeSizeTest, Distance) {}
} // anonymous namespace