Chandler Carruth | d319716 | 2016-08-19 02:07:51 +0000 | [diff] [blame] | 1 | //===- STLExtrasTest.cpp - Unit tests for STL extras ----------------------===// |
| 2 | // |
| 3 | // The LLVM Compiler Infrastructure |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | |
| 10 | #include "llvm/ADT/STLExtras.h" |
| 11 | #include "gtest/gtest.h" |
| 12 | |
Chandler Carruth | 1e97630 | 2016-12-25 23:41:14 +0000 | [diff] [blame] | 13 | #include <list> |
Zachary Turner | f216a86 | 2016-09-30 15:43:59 +0000 | [diff] [blame] | 14 | #include <vector> |
| 15 | |
Chandler Carruth | d319716 | 2016-08-19 02:07:51 +0000 | [diff] [blame] | 16 | using namespace llvm; |
| 17 | |
| 18 | namespace { |
| 19 | |
| 20 | int f(rank<0>) { return 0; } |
| 21 | int f(rank<1>) { return 1; } |
| 22 | int f(rank<2>) { return 2; } |
| 23 | int f(rank<4>) { return 4; } |
| 24 | |
| 25 | TEST(STLExtrasTest, Rank) { |
| 26 | // We shouldn't get ambiguities and should select the overload of the same |
| 27 | // rank as the argument. |
| 28 | EXPECT_EQ(0, f(rank<0>())); |
| 29 | EXPECT_EQ(1, f(rank<1>())); |
| 30 | EXPECT_EQ(2, f(rank<2>())); |
| 31 | |
| 32 | // This overload is missing so we end up back at 2. |
| 33 | EXPECT_EQ(2, f(rank<3>())); |
| 34 | |
| 35 | // But going past 3 should work fine. |
| 36 | EXPECT_EQ(4, f(rank<4>())); |
| 37 | |
| 38 | // And we can even go higher and just fall back to the last overload. |
| 39 | EXPECT_EQ(4, f(rank<5>())); |
| 40 | EXPECT_EQ(4, f(rank<6>())); |
| 41 | } |
| 42 | |
Zachary Turner | 5844b06 | 2016-10-05 16:54:09 +0000 | [diff] [blame] | 43 | TEST(STLExtrasTest, EnumerateLValue) { |
| 44 | // Test that a simple LValue can be enumerated and gives correct results with |
| 45 | // multiple types, including the empty container. |
Zachary Turner | f216a86 | 2016-09-30 15:43:59 +0000 | [diff] [blame] | 46 | std::vector<char> foo = {'a', 'b', 'c'}; |
Zachary Turner | e53904e | 2016-10-05 17:04:36 +0000 | [diff] [blame] | 47 | typedef std::pair<std::size_t, char> CharPairType; |
| 48 | std::vector<CharPairType> CharResults; |
Zachary Turner | f216a86 | 2016-09-30 15:43:59 +0000 | [diff] [blame] | 49 | |
| 50 | for (auto X : llvm::enumerate(foo)) { |
Zachary Turner | 39e53ee | 2017-03-13 16:24:10 +0000 | [diff] [blame] | 51 | CharResults.emplace_back(X.index(), X.value()); |
Zachary Turner | f216a86 | 2016-09-30 15:43:59 +0000 | [diff] [blame] | 52 | } |
Zachary Turner | 5844b06 | 2016-10-05 16:54:09 +0000 | [diff] [blame] | 53 | ASSERT_EQ(3u, CharResults.size()); |
Zachary Turner | e53904e | 2016-10-05 17:04:36 +0000 | [diff] [blame] | 54 | EXPECT_EQ(CharPairType(0u, 'a'), CharResults[0]); |
| 55 | EXPECT_EQ(CharPairType(1u, 'b'), CharResults[1]); |
| 56 | EXPECT_EQ(CharPairType(2u, 'c'), CharResults[2]); |
Zachary Turner | f216a86 | 2016-09-30 15:43:59 +0000 | [diff] [blame] | 57 | |
Zachary Turner | 5844b06 | 2016-10-05 16:54:09 +0000 | [diff] [blame] | 58 | // Test a const range of a different type. |
Zachary Turner | e53904e | 2016-10-05 17:04:36 +0000 | [diff] [blame] | 59 | typedef std::pair<std::size_t, int> IntPairType; |
| 60 | std::vector<IntPairType> IntResults; |
Zachary Turner | 5844b06 | 2016-10-05 16:54:09 +0000 | [diff] [blame] | 61 | const std::vector<int> bar = {1, 2, 3}; |
Zachary Turner | f216a86 | 2016-09-30 15:43:59 +0000 | [diff] [blame] | 62 | for (auto X : llvm::enumerate(bar)) { |
Zachary Turner | 39e53ee | 2017-03-13 16:24:10 +0000 | [diff] [blame] | 63 | IntResults.emplace_back(X.index(), X.value()); |
Zachary Turner | f216a86 | 2016-09-30 15:43:59 +0000 | [diff] [blame] | 64 | } |
Zachary Turner | 5844b06 | 2016-10-05 16:54:09 +0000 | [diff] [blame] | 65 | ASSERT_EQ(3u, IntResults.size()); |
Zachary Turner | e53904e | 2016-10-05 17:04:36 +0000 | [diff] [blame] | 66 | EXPECT_EQ(IntPairType(0u, 1), IntResults[0]); |
| 67 | EXPECT_EQ(IntPairType(1u, 2), IntResults[1]); |
| 68 | EXPECT_EQ(IntPairType(2u, 3), IntResults[2]); |
Zachary Turner | f216a86 | 2016-09-30 15:43:59 +0000 | [diff] [blame] | 69 | |
Zachary Turner | 5844b06 | 2016-10-05 16:54:09 +0000 | [diff] [blame] | 70 | // Test an empty range. |
| 71 | IntResults.clear(); |
Davide Italiano | 96acf92 | 2017-03-09 23:48:58 +0000 | [diff] [blame] | 72 | const std::vector<int> baz{}; |
Zachary Turner | f216a86 | 2016-09-30 15:43:59 +0000 | [diff] [blame] | 73 | for (auto X : llvm::enumerate(baz)) { |
Zachary Turner | 39e53ee | 2017-03-13 16:24:10 +0000 | [diff] [blame] | 74 | IntResults.emplace_back(X.index(), X.value()); |
Zachary Turner | f216a86 | 2016-09-30 15:43:59 +0000 | [diff] [blame] | 75 | } |
Zachary Turner | 5844b06 | 2016-10-05 16:54:09 +0000 | [diff] [blame] | 76 | EXPECT_TRUE(IntResults.empty()); |
Zachary Turner | f216a86 | 2016-09-30 15:43:59 +0000 | [diff] [blame] | 77 | } |
| 78 | |
Zachary Turner | 5844b06 | 2016-10-05 16:54:09 +0000 | [diff] [blame] | 79 | TEST(STLExtrasTest, EnumerateModifyLValue) { |
| 80 | // Test that you can modify the underlying entries of an lvalue range through |
| 81 | // the enumeration iterator. |
Zachary Turner | f216a86 | 2016-09-30 15:43:59 +0000 | [diff] [blame] | 82 | std::vector<char> foo = {'a', 'b', 'c'}; |
| 83 | |
| 84 | for (auto X : llvm::enumerate(foo)) { |
Zachary Turner | 39e53ee | 2017-03-13 16:24:10 +0000 | [diff] [blame] | 85 | ++X.value(); |
Zachary Turner | f216a86 | 2016-09-30 15:43:59 +0000 | [diff] [blame] | 86 | } |
Zachary Turner | f216a86 | 2016-09-30 15:43:59 +0000 | [diff] [blame] | 87 | EXPECT_EQ('b', foo[0]); |
| 88 | EXPECT_EQ('c', foo[1]); |
| 89 | EXPECT_EQ('d', foo[2]); |
| 90 | } |
Zachary Turner | 5844b06 | 2016-10-05 16:54:09 +0000 | [diff] [blame] | 91 | |
| 92 | TEST(STLExtrasTest, EnumerateRValueRef) { |
| 93 | // Test that an rvalue can be enumerated. |
Zachary Turner | e53904e | 2016-10-05 17:04:36 +0000 | [diff] [blame] | 94 | typedef std::pair<std::size_t, int> PairType; |
| 95 | std::vector<PairType> Results; |
Zachary Turner | 5844b06 | 2016-10-05 16:54:09 +0000 | [diff] [blame] | 96 | |
| 97 | auto Enumerator = llvm::enumerate(std::vector<int>{1, 2, 3}); |
| 98 | |
| 99 | for (auto X : llvm::enumerate(std::vector<int>{1, 2, 3})) { |
Zachary Turner | 39e53ee | 2017-03-13 16:24:10 +0000 | [diff] [blame] | 100 | Results.emplace_back(X.index(), X.value()); |
Zachary Turner | 5844b06 | 2016-10-05 16:54:09 +0000 | [diff] [blame] | 101 | } |
| 102 | |
| 103 | ASSERT_EQ(3u, Results.size()); |
Zachary Turner | e53904e | 2016-10-05 17:04:36 +0000 | [diff] [blame] | 104 | EXPECT_EQ(PairType(0u, 1), Results[0]); |
| 105 | EXPECT_EQ(PairType(1u, 2), Results[1]); |
| 106 | EXPECT_EQ(PairType(2u, 3), Results[2]); |
Zachary Turner | 5844b06 | 2016-10-05 16:54:09 +0000 | [diff] [blame] | 107 | } |
| 108 | |
| 109 | TEST(STLExtrasTest, EnumerateModifyRValue) { |
| 110 | // Test that when enumerating an rvalue, modification still works (even if |
| 111 | // this isn't terribly useful, it at least shows that we haven't snuck an |
| 112 | // extra const in there somewhere. |
Zachary Turner | e53904e | 2016-10-05 17:04:36 +0000 | [diff] [blame] | 113 | typedef std::pair<std::size_t, char> PairType; |
| 114 | std::vector<PairType> Results; |
Zachary Turner | 5844b06 | 2016-10-05 16:54:09 +0000 | [diff] [blame] | 115 | |
| 116 | for (auto X : llvm::enumerate(std::vector<char>{'1', '2', '3'})) { |
Zachary Turner | 39e53ee | 2017-03-13 16:24:10 +0000 | [diff] [blame] | 117 | ++X.value(); |
| 118 | Results.emplace_back(X.index(), X.value()); |
Zachary Turner | 5844b06 | 2016-10-05 16:54:09 +0000 | [diff] [blame] | 119 | } |
| 120 | |
| 121 | ASSERT_EQ(3u, Results.size()); |
Zachary Turner | e53904e | 2016-10-05 17:04:36 +0000 | [diff] [blame] | 122 | EXPECT_EQ(PairType(0u, '2'), Results[0]); |
| 123 | EXPECT_EQ(PairType(1u, '3'), Results[1]); |
| 124 | EXPECT_EQ(PairType(2u, '4'), Results[2]); |
Zachary Turner | 5844b06 | 2016-10-05 16:54:09 +0000 | [diff] [blame] | 125 | } |
| 126 | |
| 127 | template <bool B> struct CanMove {}; |
| 128 | template <> struct CanMove<false> { |
| 129 | CanMove(CanMove &&) = delete; |
| 130 | |
| 131 | CanMove() = default; |
| 132 | CanMove(const CanMove &) = default; |
| 133 | }; |
| 134 | |
| 135 | template <bool B> struct CanCopy {}; |
| 136 | template <> struct CanCopy<false> { |
| 137 | CanCopy(const CanCopy &) = delete; |
| 138 | |
| 139 | CanCopy() = default; |
Vedant Kumar | 59b2213 | 2016-10-25 18:11:17 +0000 | [diff] [blame] | 140 | CanCopy(CanCopy &&) = default; |
Zachary Turner | 5844b06 | 2016-10-05 16:54:09 +0000 | [diff] [blame] | 141 | }; |
| 142 | |
| 143 | template <bool Moveable, bool Copyable> |
| 144 | struct Range : CanMove<Moveable>, CanCopy<Copyable> { |
| 145 | explicit Range(int &C, int &M, int &D) : C(C), M(M), D(D) {} |
| 146 | Range(const Range &R) : CanCopy<Copyable>(R), C(R.C), M(R.M), D(R.D) { ++C; } |
| 147 | Range(Range &&R) : CanMove<Moveable>(std::move(R)), C(R.C), M(R.M), D(R.D) { |
| 148 | ++M; |
| 149 | } |
| 150 | ~Range() { ++D; } |
| 151 | |
| 152 | int &C; |
| 153 | int &M; |
| 154 | int &D; |
| 155 | |
| 156 | int *begin() { return nullptr; } |
| 157 | int *end() { return nullptr; } |
| 158 | }; |
| 159 | |
| 160 | TEST(STLExtrasTest, EnumerateLifetimeSemantics) { |
| 161 | // Test that when enumerating lvalues and rvalues, there are no surprise |
| 162 | // copies or moves. |
| 163 | |
| 164 | // With an rvalue, it should not be destroyed until the end of the scope. |
| 165 | int Copies = 0; |
| 166 | int Moves = 0; |
| 167 | int Destructors = 0; |
| 168 | { |
| 169 | auto E1 = enumerate(Range<true, false>(Copies, Moves, Destructors)); |
| 170 | // Doesn't compile. rvalue ranges must be moveable. |
| 171 | // auto E2 = enumerate(Range<false, true>(Copies, Moves, Destructors)); |
| 172 | EXPECT_EQ(0, Copies); |
| 173 | EXPECT_EQ(1, Moves); |
| 174 | EXPECT_EQ(1, Destructors); |
| 175 | } |
| 176 | EXPECT_EQ(0, Copies); |
| 177 | EXPECT_EQ(1, Moves); |
| 178 | EXPECT_EQ(2, Destructors); |
| 179 | |
| 180 | Copies = Moves = Destructors = 0; |
| 181 | // With an lvalue, it should not be destroyed even after the end of the scope. |
| 182 | // lvalue ranges need be neither copyable nor moveable. |
| 183 | Range<false, false> R(Copies, Moves, Destructors); |
| 184 | { |
| 185 | auto Enumerator = enumerate(R); |
| 186 | (void)Enumerator; |
| 187 | EXPECT_EQ(0, Copies); |
| 188 | EXPECT_EQ(0, Moves); |
| 189 | EXPECT_EQ(0, Destructors); |
| 190 | } |
| 191 | EXPECT_EQ(0, Copies); |
| 192 | EXPECT_EQ(0, Moves); |
| 193 | EXPECT_EQ(0, Destructors); |
| 194 | } |
Zachary Turner | bd90bcc | 2016-10-10 16:44:09 +0000 | [diff] [blame] | 195 | |
| 196 | TEST(STLExtrasTest, ApplyTuple) { |
| 197 | auto T = std::make_tuple(1, 3, 7); |
Zachary Turner | 1793ab4 | 2016-10-10 21:24:34 +0000 | [diff] [blame] | 198 | auto U = llvm::apply_tuple( |
Zachary Turner | bd90bcc | 2016-10-10 16:44:09 +0000 | [diff] [blame] | 199 | [](int A, int B, int C) { return std::make_tuple(A - B, B - C, C - A); }, |
| 200 | T); |
| 201 | |
| 202 | EXPECT_EQ(-2, std::get<0>(U)); |
| 203 | EXPECT_EQ(-4, std::get<1>(U)); |
| 204 | EXPECT_EQ(6, std::get<2>(U)); |
| 205 | |
Zachary Turner | 1793ab4 | 2016-10-10 21:24:34 +0000 | [diff] [blame] | 206 | auto V = llvm::apply_tuple( |
Zachary Turner | bd90bcc | 2016-10-10 16:44:09 +0000 | [diff] [blame] | 207 | [](int A, int B, int C) { |
| 208 | return std::make_tuple(std::make_pair(A, char('A' + A)), |
| 209 | std::make_pair(B, char('A' + B)), |
| 210 | std::make_pair(C, char('A' + C))); |
| 211 | }, |
| 212 | T); |
| 213 | |
| 214 | EXPECT_EQ(std::make_pair(1, 'B'), std::get<0>(V)); |
| 215 | EXPECT_EQ(std::make_pair(3, 'D'), std::get<1>(V)); |
| 216 | EXPECT_EQ(std::make_pair(7, 'H'), std::get<2>(V)); |
| 217 | } |
| 218 | |
| 219 | class apply_variadic { |
| 220 | static int apply_one(int X) { return X + 1; } |
| 221 | static char apply_one(char C) { return C + 1; } |
| 222 | static StringRef apply_one(StringRef S) { return S.drop_back(); } |
| 223 | |
| 224 | public: |
| 225 | template <typename... Ts> |
| 226 | auto operator()(Ts &&... Items) |
| 227 | -> decltype(std::make_tuple(apply_one(Items)...)) { |
| 228 | return std::make_tuple(apply_one(Items)...); |
| 229 | } |
| 230 | }; |
| 231 | |
| 232 | TEST(STLExtrasTest, ApplyTupleVariadic) { |
| 233 | auto Items = std::make_tuple(1, llvm::StringRef("Test"), 'X'); |
Zachary Turner | 1793ab4 | 2016-10-10 21:24:34 +0000 | [diff] [blame] | 234 | auto Values = apply_tuple(apply_variadic(), Items); |
Zachary Turner | bd90bcc | 2016-10-10 16:44:09 +0000 | [diff] [blame] | 235 | |
| 236 | EXPECT_EQ(2, std::get<0>(Values)); |
| 237 | EXPECT_EQ("Tes", std::get<1>(Values)); |
| 238 | EXPECT_EQ('Y', std::get<2>(Values)); |
| 239 | } |
Michael Gottesman | 6a2af3e | 2016-12-04 10:26:53 +0000 | [diff] [blame] | 240 | |
| 241 | TEST(STLExtrasTest, CountAdaptor) { |
| 242 | std::vector<int> v; |
| 243 | |
| 244 | v.push_back(1); |
| 245 | v.push_back(2); |
| 246 | v.push_back(1); |
| 247 | v.push_back(4); |
| 248 | v.push_back(3); |
| 249 | v.push_back(2); |
| 250 | v.push_back(1); |
| 251 | |
| 252 | EXPECT_EQ(3, count(v, 1)); |
| 253 | EXPECT_EQ(2, count(v, 2)); |
| 254 | EXPECT_EQ(1, count(v, 3)); |
David Blaikie | 3f395b6 | 2017-11-20 22:12:55 +0000 | [diff] [blame] | 255 | EXPECT_EQ(1, count(v, 4)); |
| 256 | } |
| 257 | |
| 258 | TEST(STLExtrasTest, for_each) { |
| 259 | std::vector<int> v{0, 1, 2, 3, 4}; |
| 260 | int count = 0; |
| 261 | |
| 262 | llvm::for_each(v, [&count](int) { ++count; }); |
| 263 | EXPECT_EQ(5, count); |
| 264 | } |
| 265 | |
| 266 | TEST(STLExtrasTest, ToVector) { |
| 267 | std::vector<char> v = {'a', 'b', 'c'}; |
| 268 | auto Enumerated = to_vector<4>(enumerate(v)); |
David Blaikie | 9812b90 | 2017-03-13 21:46:12 +0000 | [diff] [blame] | 269 | ASSERT_EQ(3u, Enumerated.size()); |
Zachary Turner | 39e53ee | 2017-03-13 16:24:10 +0000 | [diff] [blame] | 270 | for (size_t I = 0; I < v.size(); ++I) { |
| 271 | EXPECT_EQ(I, Enumerated[I].index()); |
| 272 | EXPECT_EQ(v[I], Enumerated[I].value()); |
| 273 | } |
| 274 | } |
| 275 | |
Chandler Carruth | 1e97630 | 2016-12-25 23:41:14 +0000 | [diff] [blame] | 276 | TEST(STLExtrasTest, ConcatRange) { |
| 277 | std::vector<int> Expected = {1, 2, 3, 4, 5, 6, 7, 8}; |
| 278 | std::vector<int> Test; |
| 279 | |
| 280 | std::vector<int> V1234 = {1, 2, 3, 4}; |
| 281 | std::list<int> L56 = {5, 6}; |
| 282 | SmallVector<int, 2> SV78 = {7, 8}; |
| 283 | |
| 284 | // Use concat across different sized ranges of different types with different |
| 285 | // iterators. |
| 286 | for (int &i : concat<int>(V1234, L56, SV78)) |
| 287 | Test.push_back(i); |
| 288 | EXPECT_EQ(Expected, Test); |
| 289 | |
| 290 | // Use concat between a temporary, an L-value, and an R-value to make sure |
| 291 | // complex lifetimes work well. |
| 292 | Test.clear(); |
| 293 | for (int &i : concat<int>(std::vector<int>(V1234), L56, std::move(SV78))) |
| 294 | Test.push_back(i); |
| 295 | EXPECT_EQ(Expected, Test); |
| 296 | } |
Chandler Carruth | 8541911 | 2016-12-26 23:10:40 +0000 | [diff] [blame] | 297 | |
| 298 | TEST(STLExtrasTest, PartitionAdaptor) { |
| 299 | std::vector<int> V = {1, 2, 3, 4, 5, 6, 7, 8}; |
| 300 | |
| 301 | auto I = partition(V, [](int i) { return i % 2 == 0; }); |
| 302 | ASSERT_EQ(V.begin() + 4, I); |
| 303 | |
| 304 | // Sort the two halves as partition may have messed with the order. |
Mandeep Singh Grang | 77a1dcd | 2018-04-07 01:29:45 +0000 | [diff] [blame] | 305 | llvm::sort(V.begin(), I); |
| 306 | llvm::sort(I, V.end()); |
Chandler Carruth | 8541911 | 2016-12-26 23:10:40 +0000 | [diff] [blame] | 307 | |
| 308 | EXPECT_EQ(2, V[0]); |
| 309 | EXPECT_EQ(4, V[1]); |
| 310 | EXPECT_EQ(6, V[2]); |
| 311 | EXPECT_EQ(8, V[3]); |
| 312 | EXPECT_EQ(1, V[4]); |
| 313 | EXPECT_EQ(3, V[5]); |
| 314 | EXPECT_EQ(5, V[6]); |
| 315 | EXPECT_EQ(7, V[7]); |
| 316 | } |
| 317 | |
Chandler Carruth | 5c40baf | 2016-12-26 23:30:44 +0000 | [diff] [blame] | 318 | TEST(STLExtrasTest, EraseIf) { |
| 319 | std::vector<int> V = {1, 2, 3, 4, 5, 6, 7, 8}; |
| 320 | |
| 321 | erase_if(V, [](int i) { return i % 2 == 0; }); |
| 322 | EXPECT_EQ(4u, V.size()); |
| 323 | EXPECT_EQ(1, V[0]); |
| 324 | EXPECT_EQ(3, V[1]); |
| 325 | EXPECT_EQ(5, V[2]); |
| 326 | EXPECT_EQ(7, V[3]); |
| 327 | } |
| 328 | |
David Blaikie | 3f395b6 | 2017-11-20 22:12:55 +0000 | [diff] [blame] | 329 | namespace some_namespace { |
| 330 | struct some_struct { |
| 331 | std::vector<int> data; |
| 332 | std::string swap_val; |
| 333 | }; |
| 334 | |
| 335 | std::vector<int>::const_iterator begin(const some_struct &s) { |
| 336 | return s.data.begin(); |
Chandler Carruth | d319716 | 2016-08-19 02:07:51 +0000 | [diff] [blame] | 337 | } |
David Blaikie | 3f395b6 | 2017-11-20 22:12:55 +0000 | [diff] [blame] | 338 | |
| 339 | std::vector<int>::const_iterator end(const some_struct &s) { |
| 340 | return s.data.end(); |
| 341 | } |
| 342 | |
| 343 | void swap(some_struct &lhs, some_struct &rhs) { |
| 344 | // make swap visible as non-adl swap would even seem to |
| 345 | // work with std::swap which defaults to moving |
| 346 | lhs.swap_val = "lhs"; |
| 347 | rhs.swap_val = "rhs"; |
| 348 | } |
| 349 | } // namespace some_namespace |
| 350 | |
| 351 | TEST(STLExtrasTest, ADLTest) { |
| 352 | some_namespace::some_struct s{{1, 2, 3, 4, 5}, ""}; |
| 353 | some_namespace::some_struct s2{{2, 4, 6, 8, 10}, ""}; |
| 354 | |
| 355 | EXPECT_EQ(*adl_begin(s), 1); |
| 356 | EXPECT_EQ(*(adl_end(s) - 1), 5); |
| 357 | |
| 358 | adl_swap(s, s2); |
| 359 | EXPECT_EQ(s.swap_val, "lhs"); |
| 360 | EXPECT_EQ(s2.swap_val, "rhs"); |
| 361 | |
| 362 | int count = 0; |
| 363 | llvm::for_each(s, [&count](int) { ++count; }); |
| 364 | EXPECT_EQ(5, count); |
| 365 | } |
| 366 | |
Matthias Braun | b3bc958 | 2018-10-31 00:23:23 +0000 | [diff] [blame] | 367 | TEST(STLExtrasTest, EmptyTest) { |
| 368 | std::vector<void*> V; |
Matthias Braun | 4f27756 | 2018-10-31 01:58:00 +0000 | [diff] [blame] | 369 | EXPECT_TRUE(llvm::empty(V)); |
Matthias Braun | b3bc958 | 2018-10-31 00:23:23 +0000 | [diff] [blame] | 370 | V.push_back(nullptr); |
Matthias Braun | 4f27756 | 2018-10-31 01:58:00 +0000 | [diff] [blame] | 371 | EXPECT_FALSE(llvm::empty(V)); |
Matthias Braun | b3bc958 | 2018-10-31 00:23:23 +0000 | [diff] [blame] | 372 | |
| 373 | std::initializer_list<int> E = {}; |
| 374 | std::initializer_list<int> NotE = {7, 13, 42}; |
Matthias Braun | 4f27756 | 2018-10-31 01:58:00 +0000 | [diff] [blame] | 375 | EXPECT_TRUE(llvm::empty(E)); |
| 376 | EXPECT_FALSE(llvm::empty(NotE)); |
Matthias Braun | b3bc958 | 2018-10-31 00:23:23 +0000 | [diff] [blame] | 377 | |
| 378 | auto R0 = make_range(V.begin(), V.begin()); |
Matthias Braun | 4f27756 | 2018-10-31 01:58:00 +0000 | [diff] [blame] | 379 | EXPECT_TRUE(llvm::empty(R0)); |
Matthias Braun | b3bc958 | 2018-10-31 00:23:23 +0000 | [diff] [blame] | 380 | auto R1 = make_range(V.begin(), V.end()); |
Matthias Braun | 4f27756 | 2018-10-31 01:58:00 +0000 | [diff] [blame] | 381 | EXPECT_FALSE(llvm::empty(R1)); |
Matthias Braun | b3bc958 | 2018-10-31 00:23:23 +0000 | [diff] [blame] | 382 | } |
| 383 | |
Chandler Carruth | b2e6802 | 2018-08-04 08:17:26 +0000 | [diff] [blame] | 384 | TEST(STLExtrasTest, EarlyIncrementTest) { |
| 385 | std::list<int> L = {1, 2, 3, 4}; |
| 386 | |
| 387 | auto EIR = make_early_inc_range(L); |
| 388 | |
| 389 | auto I = EIR.begin(); |
| 390 | auto EI = EIR.end(); |
| 391 | EXPECT_NE(I, EI); |
| 392 | |
| 393 | EXPECT_EQ(1, *I); |
| 394 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS |
| 395 | #ifndef NDEBUG |
| 396 | // Repeated dereferences are not allowed. |
| 397 | EXPECT_DEATH(*I, "Cannot dereference"); |
| 398 | // Comparison after dereference is not allowed. |
| 399 | EXPECT_DEATH((void)(I == EI), "Cannot compare"); |
| 400 | EXPECT_DEATH((void)(I != EI), "Cannot compare"); |
| 401 | #endif |
| 402 | #endif |
| 403 | |
| 404 | ++I; |
| 405 | EXPECT_NE(I, EI); |
| 406 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS |
| 407 | #ifndef NDEBUG |
| 408 | // You cannot increment prior to dereference. |
| 409 | EXPECT_DEATH(++I, "Cannot increment"); |
| 410 | #endif |
| 411 | #endif |
| 412 | EXPECT_EQ(2, *I); |
| 413 | #if LLVM_ENABLE_ABI_BREAKING_CHECKS |
| 414 | #ifndef NDEBUG |
| 415 | // Repeated dereferences are not allowed. |
| 416 | EXPECT_DEATH(*I, "Cannot dereference"); |
| 417 | #endif |
| 418 | #endif |
| 419 | |
| 420 | // Inserting shouldn't break anything. We should be able to keep dereferencing |
| 421 | // the currrent iterator and increment. The increment to go to the "next" |
| 422 | // iterator from before we inserted. |
| 423 | L.insert(std::next(L.begin(), 2), -1); |
| 424 | ++I; |
| 425 | EXPECT_EQ(3, *I); |
| 426 | |
| 427 | // Erasing the front including the current doesn't break incrementing. |
| 428 | L.erase(L.begin(), std::prev(L.end())); |
| 429 | ++I; |
| 430 | EXPECT_EQ(4, *I); |
| 431 | ++I; |
| 432 | EXPECT_EQ(EIR.end(), I); |
| 433 | } |
| 434 | |
Chen Zheng | 12061ae | 2018-08-17 07:51:01 +0000 | [diff] [blame] | 435 | TEST(STLExtrasTest, splat) { |
| 436 | std::vector<int> V; |
| 437 | EXPECT_FALSE(is_splat(V)); |
| 438 | |
| 439 | V.push_back(1); |
| 440 | EXPECT_TRUE(is_splat(V)); |
| 441 | |
| 442 | V.push_back(1); |
| 443 | V.push_back(1); |
| 444 | EXPECT_TRUE(is_splat(V)); |
| 445 | |
| 446 | V.push_back(2); |
| 447 | EXPECT_FALSE(is_splat(V)); |
| 448 | } |
| 449 | |
David Blaikie | 3f395b6 | 2017-11-20 22:12:55 +0000 | [diff] [blame] | 450 | } // namespace |