[Clang/AMDGPU] Zero sized arrays not allowed in HIP device code. (#113470)
[llvm-project.git] / llvm / unittests / ADT / MappedIteratorTest.cpp
blob8ea3dbc0d5a0933e30f6207163409b6690c2f855
1 //===------ MappedIteratorTest.cpp - Unit tests for mapped_iterator -------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "llvm/ADT/STLExtras.h"
10 #include "gtest/gtest.h"
12 using namespace llvm;
14 namespace {
16 template <typename T> class MappedIteratorTestBasic : public testing::Test {};
18 struct Plus1Lambda {
19 auto operator()() const {
20 return [](int X) { return X + 1; };
24 struct Plus1LambdaWithCapture {
25 const int One = 1;
27 auto operator()() const {
28 return [=](int X) { return X + One; };
32 struct Plus1FunctionRef {
33 static int plus1(int X) { return X + 1; }
35 using FuncT = int (&)(int);
37 FuncT operator()() const { return (FuncT)*plus1; }
40 struct Plus1FunctionPtr {
41 static int plus1(int X) { return X + 1; }
43 using FuncT = int (*)(int);
45 FuncT operator()() const { return plus1; }
48 struct Plus1Functor {
49 struct Plus1 {
50 int operator()(int X) const { return X + 1; }
53 auto operator()() const { return Plus1(); }
56 struct Plus1FunctorNotDefaultConstructible {
57 class PlusN {
58 const int N;
60 public:
61 PlusN(int NArg) : N(NArg) {}
63 int operator()(int X) const { return X + N; }
66 auto operator()() const { return PlusN(1); }
69 // clang-format off
70 using FunctionTypes =
71 ::testing::Types<
72 Plus1Lambda,
73 Plus1LambdaWithCapture,
74 Plus1FunctionRef,
75 Plus1FunctionPtr,
76 Plus1Functor,
77 Plus1FunctorNotDefaultConstructible
79 // clang-format on
81 TYPED_TEST_SUITE(MappedIteratorTestBasic, FunctionTypes, );
83 template <typename T> using GetFuncT = decltype(std::declval<T>().operator()());
85 TYPED_TEST(MappedIteratorTestBasic, DefaultConstruct) {
86 using FuncT = GetFuncT<TypeParam>;
87 using IterT = mapped_iterator<typename std::vector<int>::iterator, FuncT>;
88 TypeParam GetCallable;
90 auto Func = GetCallable();
91 (void)Func;
92 constexpr bool DefaultConstruct =
93 std::is_default_constructible_v<callable_detail::Callable<FuncT>>;
94 EXPECT_TRUE(DefaultConstruct);
95 EXPECT_TRUE(std::is_default_constructible_v<IterT>);
97 if constexpr (std::is_default_constructible_v<IterT>) {
98 IterT I;
99 (void)I;
103 TYPED_TEST(MappedIteratorTestBasic, CopyConstruct) {
104 std::vector<int> V({0});
106 using FuncT = GetFuncT<TypeParam>;
107 using IterT = mapped_iterator<decltype(V)::iterator, FuncT>;
109 EXPECT_TRUE(std::is_copy_constructible_v<IterT>);
111 if constexpr (std::is_copy_constructible_v<IterT>) {
112 TypeParam GetCallable;
114 IterT I1(V.begin(), GetCallable());
115 IterT I2(I1);
117 EXPECT_EQ(I2, I1) << "copy constructed iterator is a different position";
121 TYPED_TEST(MappedIteratorTestBasic, MoveConstruct) {
122 std::vector<int> V({0});
124 using FuncT = GetFuncT<TypeParam>;
125 using IterT = mapped_iterator<decltype(V)::iterator, FuncT>;
127 EXPECT_TRUE(std::is_move_constructible_v<IterT>);
129 if constexpr (std::is_move_constructible_v<IterT>) {
130 TypeParam GetCallable;
132 IterT I1(V.begin(), GetCallable());
133 IterT I2(V.begin(), GetCallable());
134 IterT I3(std::move(I2));
136 EXPECT_EQ(I3, I1) << "move constructed iterator is a different position";
140 TYPED_TEST(MappedIteratorTestBasic, CopyAssign) {
141 std::vector<int> V({0});
143 using FuncT = GetFuncT<TypeParam>;
144 using IterT = mapped_iterator<decltype(V)::iterator, FuncT>;
146 EXPECT_TRUE(std::is_copy_assignable_v<IterT>);
148 if constexpr (std::is_copy_assignable_v<IterT>) {
149 TypeParam GetCallable;
151 IterT I1(V.begin(), GetCallable());
152 IterT I2(V.end(), GetCallable());
154 I2 = I1;
156 EXPECT_EQ(I2, I1) << "copy assigned iterator is a different position";
160 TYPED_TEST(MappedIteratorTestBasic, MoveAssign) {
161 std::vector<int> V({0});
163 using FuncT = GetFuncT<TypeParam>;
164 using IterT = mapped_iterator<decltype(V)::iterator, FuncT>;
166 EXPECT_TRUE(std::is_move_assignable_v<IterT>);
168 if constexpr (std::is_move_assignable_v<IterT>) {
169 TypeParam GetCallable;
171 IterT I1(V.begin(), GetCallable());
172 IterT I2(V.begin(), GetCallable());
173 IterT I3(V.end(), GetCallable());
175 I3 = std::move(I2);
177 EXPECT_EQ(I3, I1) << "move assigned iterator is a different position";
181 TYPED_TEST(MappedIteratorTestBasic, GetFunction) {
182 std::vector<int> V({0});
184 using FuncT = GetFuncT<TypeParam>;
185 using IterT = mapped_iterator<decltype(V)::iterator, FuncT>;
187 TypeParam GetCallable;
188 IterT I(V.begin(), GetCallable());
190 EXPECT_EQ(I.getFunction()(200), 201);
193 TYPED_TEST(MappedIteratorTestBasic, GetCurrent) {
194 std::vector<int> V({0});
196 using FuncT = GetFuncT<TypeParam>;
197 using IterT = mapped_iterator<decltype(V)::iterator, FuncT>;
199 TypeParam GetCallable;
200 IterT I(V.begin(), GetCallable());
202 EXPECT_EQ(I.getCurrent(), V.begin());
203 EXPECT_EQ(std::next(I).getCurrent(), V.end());
206 TYPED_TEST(MappedIteratorTestBasic, ApplyFunctionOnDereference) {
207 std::vector<int> V({0});
208 TypeParam GetCallable;
210 auto I = map_iterator(V.begin(), GetCallable());
212 EXPECT_EQ(*I, 1) << "should have applied function in dereference";
215 TEST(MappedIteratorTest, ApplyFunctionOnArrow) {
216 struct S {
217 int Z = 0;
220 std::vector<int> V({0});
221 S Y;
222 S *P = &Y;
224 auto I = map_iterator(V.begin(), [&](int X) -> S & { return *(P + X); });
226 I->Z = 42;
228 EXPECT_EQ(Y.Z, 42) << "should have applied function during arrow";
231 TEST(MappedIteratorTest, FunctionPreservesReferences) {
232 std::vector<int> V({1});
233 std::map<int, int> M({{1, 1}});
235 auto I = map_iterator(V.begin(), [&](int X) -> int & { return M[X]; });
236 *I = 42;
238 EXPECT_EQ(M[1], 42) << "assignment should have modified M";
241 TEST(MappedIteratorTest, CustomIteratorApplyFunctionOnDereference) {
242 struct CustomMapIterator
243 : public llvm::mapped_iterator_base<CustomMapIterator,
244 std::vector<int>::iterator, int> {
245 using BaseT::BaseT;
247 /// Map the element to the iterator result type.
248 int mapElement(int X) const { return X + 1; }
251 std::vector<int> V({0});
253 CustomMapIterator I(V.begin());
255 EXPECT_EQ(*I, 1) << "should have applied function in dereference";
258 TEST(MappedIteratorTest, CustomIteratorApplyFunctionOnArrow) {
259 struct S {
260 int Z = 0;
262 struct CustomMapIterator
263 : public llvm::mapped_iterator_base<CustomMapIterator,
264 std::vector<int>::iterator, S &> {
265 CustomMapIterator(std::vector<int>::iterator it, S *P) : BaseT(it), P(P) {}
267 /// Map the element to the iterator result type.
268 S &mapElement(int X) const { return *(P + X); }
270 S *P;
273 std::vector<int> V({0});
274 S Y;
276 CustomMapIterator I(V.begin(), &Y);
278 I->Z = 42;
280 EXPECT_EQ(Y.Z, 42) << "should have applied function during arrow";
283 TEST(MappedIteratorTest, CustomIteratorFunctionPreservesReferences) {
284 struct CustomMapIterator
285 : public llvm::mapped_iterator_base<CustomMapIterator,
286 std::vector<int>::iterator, int &> {
287 CustomMapIterator(std::vector<int>::iterator it, std::map<int, int> &M)
288 : BaseT(it), M(M) {}
290 /// Map the element to the iterator result type.
291 int &mapElement(int X) const { return M[X]; }
293 std::map<int, int> &M;
295 std::vector<int> V({1});
296 std::map<int, int> M({{1, 1}});
298 auto I = CustomMapIterator(V.begin(), M);
299 *I = 42;
301 EXPECT_EQ(M[1], 42) << "assignment should have modified M";
304 } // anonymous namespace