500 lines · cpp
1//===- llvm/unittest/ADT/ArrayRefTest.cpp - ArrayRef unit tests -----------===//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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/ADT/ArrayRef.h"10#include "llvm/Support/Allocator.h"11#include "gtest/gtest.h"12#include <limits>13#include <vector>14#if __has_include(<version>)15#include <version>16#endif17#ifdef __cpp_lib_span18#include <span>19#endif20 21using namespace llvm;22 23// Check that the ArrayRef-of-pointer converting constructor only allows adding24// cv qualifiers (not removing them, or otherwise changing the type)25static_assert(std::is_convertible_v<ArrayRef<int *>, ArrayRef<const int *>>,26 "Adding const");27static_assert(std::is_convertible_v<ArrayRef<int *>, ArrayRef<volatile int *>>,28 "Adding volatile");29static_assert(!std::is_convertible_v<ArrayRef<int *>, ArrayRef<float *>>,30 "Changing pointer of one type to a pointer of another");31static_assert(!std::is_convertible_v<ArrayRef<const int *>, ArrayRef<int *>>,32 "Removing const");33static_assert(!std::is_convertible_v<ArrayRef<volatile int *>, ArrayRef<int *>>,34 "Removing volatile");35 36// Check that we can't accidentally assign a temporary location to an ArrayRef.37// (Unfortunately we can't make use of the same thing with constructors.)38static_assert(!std::is_assignable_v<ArrayRef<int *> &, int *>,39 "Assigning from single prvalue element");40static_assert(!std::is_assignable_v<ArrayRef<int *> &, int *&&>,41 "Assigning from single xvalue element");42static_assert(std::is_assignable_v<ArrayRef<int *> &, int *&>,43 "Assigning from single lvalue element");44static_assert(45 !std::is_assignable_v<ArrayRef<int *> &, std::initializer_list<int *>>,46 "Assigning from an initializer list");47 48namespace {49 50TEST(ArrayRefTest, AllocatorCopy) {51 BumpPtrAllocator Alloc;52 static const uint16_t Words1[] = { 1, 4, 200, 37 };53 ArrayRef<uint16_t> Array1 = ArrayRef(Words1, 4);54 static const uint16_t Words2[] = { 11, 4003, 67, 64000, 13 };55 ArrayRef<uint16_t> Array2 = ArrayRef(Words2, 5);56 ArrayRef<uint16_t> Array1c = Array1.copy(Alloc);57 ArrayRef<uint16_t> Array2c = Array2.copy(Alloc);58 EXPECT_TRUE(Array1.equals(Array1c));59 EXPECT_NE(Array1.data(), Array1c.data());60 EXPECT_TRUE(Array2.equals(Array2c));61 EXPECT_NE(Array2.data(), Array2c.data());62 63 // Check that copy can cope with uninitialized memory.64 struct NonAssignable {65 const char *Ptr;66 67 NonAssignable(const char *Ptr) : Ptr(Ptr) {}68 NonAssignable(const NonAssignable &RHS) = default;69 void operator=(const NonAssignable &RHS) { assert(RHS.Ptr != nullptr); }70 bool operator==(const NonAssignable &RHS) const { return Ptr == RHS.Ptr; }71 } Array3Src[] = {"hello", "world"};72 ArrayRef<NonAssignable> Array3Copy = ArrayRef(Array3Src).copy(Alloc);73 EXPECT_EQ(ArrayRef(Array3Src), Array3Copy);74 EXPECT_NE(ArrayRef(Array3Src).data(), Array3Copy.data());75}76 77// This test is pure UB given the ArrayRef<> implementation.78// You are not allowed to produce non-null pointers given null base pointer.79TEST(ArrayRefTest, DISABLED_SizeTSizedOperations) {80 ArrayRef<char> AR(nullptr, std::numeric_limits<ptrdiff_t>::max());81 82 // Check that drop_back accepts size_t-sized numbers.83 EXPECT_EQ(1U, AR.drop_back(AR.size() - 1).size());84 85 // Check that drop_front accepts size_t-sized numbers.86 EXPECT_EQ(1U, AR.drop_front(AR.size() - 1).size());87 88 // Check that slice accepts size_t-sized numbers.89 EXPECT_EQ(1U, AR.slice(AR.size() - 1).size());90 EXPECT_EQ(AR.size() - 1, AR.slice(1, AR.size() - 1).size());91}92 93TEST(ArrayRefTest, DropBack) {94 static const int TheNumbers[] = {4, 8, 15, 16, 23, 42};95 ArrayRef<int> AR1(TheNumbers);96 ArrayRef<int> AR2(TheNumbers, AR1.size() - 1);97 EXPECT_TRUE(AR1.drop_back().equals(AR2));98}99 100TEST(ArrayRefTest, DropFront) {101 static const int TheNumbers[] = {4, 8, 15, 16, 23, 42};102 ArrayRef<int> AR1(TheNumbers);103 ArrayRef<int> AR2(&TheNumbers[2], AR1.size() - 2);104 EXPECT_TRUE(AR1.drop_front(2).equals(AR2));105}106 107TEST(ArrayRefTest, ConsumeFront) {108 static const int TheNumbers[] = {4, 8, 15, 16, 23, 42};109 ArrayRef<int> AR1(TheNumbers);110 ArrayRef<int> AR2(&TheNumbers[2], AR1.size() - 2);111 EXPECT_EQ(&AR1.consume_front(), &TheNumbers[0]);112 EXPECT_EQ(&AR1.consume_front(), &TheNumbers[1]);113 EXPECT_TRUE(AR1.equals(AR2));114}115 116TEST(ArrayRefTest, ConsumeBack) {117 static const int TheNumbers[] = {4, 8, 15, 16, 23, 42};118 ArrayRef<int> AR1(TheNumbers);119 ArrayRef<int> AR2(TheNumbers, AR1.size() - 2);120 EXPECT_EQ(&AR1.consume_back(), &TheNumbers[5]);121 EXPECT_EQ(&AR1.consume_back(), &TheNumbers[4]);122 EXPECT_TRUE(AR1.equals(AR2));123}124 125TEST(ArrayRefTest, MutableArryaRefConsumeFront) {126 int TheNumbers[] = {4, 8, 15, 16, 23, 42};127 MutableArrayRef<int> AR1(TheNumbers);128 MutableArrayRef<int> AR2(&TheNumbers[2], AR1.size() - 2);129 EXPECT_EQ(&AR1.consume_front(), &TheNumbers[0]);130 EXPECT_EQ(&AR1.consume_front(), &TheNumbers[1]);131 EXPECT_TRUE(AR1.equals(AR2));132 133 AR1.consume_front() = 33;134 EXPECT_EQ(TheNumbers[2], 33);135}136 137TEST(ArrayRefTest, MutableArryaRefConsumeBack) {138 int TheNumbers[] = {4, 8, 15, 16, 23, 42};139 MutableArrayRef<int> AR1(TheNumbers);140 MutableArrayRef<int> AR2(TheNumbers, AR1.size() - 2);141 EXPECT_EQ(&AR1.consume_back(), &TheNumbers[5]);142 EXPECT_EQ(&AR1.consume_back(), &TheNumbers[4]);143 EXPECT_TRUE(AR1.equals(AR2));144 145 AR1.consume_back() = 33;146 EXPECT_EQ(TheNumbers[3], 33);147}148 149TEST(ArrayRefTest, DropWhile) {150 static const int TheNumbers[] = {1, 3, 5, 8, 10, 11};151 ArrayRef<int> AR1(TheNumbers);152 ArrayRef<int> Expected = AR1.drop_front(3);153 EXPECT_EQ(Expected, AR1.drop_while([](const int &N) { return N % 2 == 1; }));154 155 EXPECT_EQ(AR1, AR1.drop_while([](const int &N) { return N < 0; }));156 EXPECT_EQ(ArrayRef<int>(),157 AR1.drop_while([](const int &N) { return N > 0; }));158}159 160TEST(ArrayRefTest, DropUntil) {161 static const int TheNumbers[] = {1, 3, 5, 8, 10, 11};162 ArrayRef<int> AR1(TheNumbers);163 ArrayRef<int> Expected = AR1.drop_front(3);164 EXPECT_EQ(Expected, AR1.drop_until([](const int &N) { return N % 2 == 0; }));165 166 EXPECT_EQ(ArrayRef<int>(),167 AR1.drop_until([](const int &N) { return N < 0; }));168 EXPECT_EQ(AR1, AR1.drop_until([](const int &N) { return N > 0; }));169}170 171TEST(ArrayRefTest, TakeBack) {172 static const int TheNumbers[] = {4, 8, 15, 16, 23, 42};173 ArrayRef<int> AR1(TheNumbers);174 ArrayRef<int> AR2(AR1.end() - 1, 1);175 EXPECT_TRUE(AR1.take_back().equals(AR2));176}177 178TEST(ArrayRefTest, TakeFront) {179 static const int TheNumbers[] = {4, 8, 15, 16, 23, 42};180 ArrayRef<int> AR1(TheNumbers);181 ArrayRef<int> AR2(AR1.data(), 2);182 EXPECT_TRUE(AR1.take_front(2).equals(AR2));183}184 185TEST(ArrayRefTest, TakeWhile) {186 static const int TheNumbers[] = {1, 3, 5, 8, 10, 11};187 ArrayRef<int> AR1(TheNumbers);188 ArrayRef<int> Expected = AR1.take_front(3);189 EXPECT_EQ(Expected, AR1.take_while([](const int &N) { return N % 2 == 1; }));190 191 EXPECT_EQ(ArrayRef<int>(),192 AR1.take_while([](const int &N) { return N < 0; }));193 EXPECT_EQ(AR1, AR1.take_while([](const int &N) { return N > 0; }));194}195 196TEST(ArrayRefTest, TakeUntil) {197 static const int TheNumbers[] = {1, 3, 5, 8, 10, 11};198 ArrayRef<int> AR1(TheNumbers);199 ArrayRef<int> Expected = AR1.take_front(3);200 EXPECT_EQ(Expected, AR1.take_until([](const int &N) { return N % 2 == 0; }));201 202 EXPECT_EQ(AR1, AR1.take_until([](const int &N) { return N < 0; }));203 EXPECT_EQ(ArrayRef<int>(),204 AR1.take_until([](const int &N) { return N > 0; }));205}206 207TEST(ArrayRefTest, Equals) {208 static const int A1[] = {1, 2, 3, 4, 5, 6, 7, 8};209 ArrayRef<int> AR1(A1);210 EXPECT_TRUE(AR1.equals({1, 2, 3, 4, 5, 6, 7, 8}));211 EXPECT_FALSE(AR1.equals({8, 1, 2, 4, 5, 6, 6, 7}));212 EXPECT_FALSE(AR1.equals({2, 4, 5, 6, 6, 7, 8, 1}));213 EXPECT_FALSE(AR1.equals({0, 1, 2, 4, 5, 6, 6, 7}));214 EXPECT_FALSE(AR1.equals({1, 2, 42, 4, 5, 6, 7, 8}));215 EXPECT_FALSE(AR1.equals({42, 2, 3, 4, 5, 6, 7, 8}));216 EXPECT_FALSE(AR1.equals({1, 2, 3, 4, 5, 6, 7, 42}));217 EXPECT_FALSE(AR1.equals({1, 2, 3, 4, 5, 6, 7}));218 EXPECT_FALSE(AR1.equals({1, 2, 3, 4, 5, 6, 7, 8, 9}));219 220 ArrayRef<int> AR1a = AR1.drop_back();221 EXPECT_TRUE(AR1a.equals({1, 2, 3, 4, 5, 6, 7}));222 EXPECT_FALSE(AR1a.equals({1, 2, 3, 4, 5, 6, 7, 8}));223 224 ArrayRef<int> AR1b = AR1a.slice(2, 4);225 EXPECT_TRUE(AR1b.equals({3, 4, 5, 6}));226 EXPECT_FALSE(AR1b.equals({2, 3, 4, 5, 6}));227 EXPECT_FALSE(AR1b.equals({3, 4, 5, 6, 7}));228}229 230TEST(ArrayRefTest, EmptyEquals) {231 EXPECT_TRUE(ArrayRef<unsigned>() == ArrayRef<unsigned>());232}233 234TEST(ArrayRefTest, Compare) {235 ArrayRef<char> Ban("Ban");236 ArrayRef<char> Banana("Banana");237 ArrayRef<char> Band("Band");238 239 EXPECT_TRUE(Ban < Banana);240 EXPECT_TRUE(Ban <= Banana);241 EXPECT_FALSE(Ban > Banana);242 EXPECT_FALSE(Ban >= Banana);243 244 EXPECT_FALSE(Banana < Banana);245 EXPECT_TRUE(Banana <= Banana);246 EXPECT_FALSE(Banana > Banana);247 EXPECT_TRUE(Banana >= Banana);248 249 EXPECT_TRUE(Banana < Band);250 EXPECT_TRUE(Banana <= Band);251 EXPECT_FALSE(Banana > Band);252 EXPECT_FALSE(Banana >= Band);253}254 255TEST(ArrayRefTest, ConstConvert) {256 int buf[4];257 for (int i = 0; i < 4; ++i)258 buf[i] = i;259 260 static int *A[] = {&buf[0], &buf[1], &buf[2], &buf[3]};261 ArrayRef<const int *> a((ArrayRef<int *>(A)));262 a = ArrayRef<int *>(A);263}264 265static std::vector<int> ReturnTest12() { return {1, 2}; }266static void ArgTest12(ArrayRef<int> A) {267 EXPECT_EQ(2U, A.size());268 EXPECT_EQ(1, A[0]);269 EXPECT_EQ(2, A[1]);270}271 272TEST(ArrayRefTest, InitializerList) {273 std::initializer_list<int> init_list = { 0, 1, 2, 3, 4 };274 ArrayRef<int> A = init_list;275 for (int i = 0; i < 5; ++i)276 EXPECT_EQ(i, A[i]);277 278 std::vector<int> B = ReturnTest12();279 A = B;280 EXPECT_EQ(1, A[0]);281 EXPECT_EQ(2, A[1]);282 283 ArgTest12({1, 2});284}285 286TEST(ArrayRefTest, EmptyInitializerList) {287 ArrayRef<int> A = {};288 EXPECT_TRUE(A.empty());289 290 A = {};291 EXPECT_TRUE(A.empty());292}293 294TEST(ArrayRefTest, ArrayRef) {295 static const int A1[] = {1, 2, 3, 4, 5, 6, 7, 8};296 297 // A copy is expected for non-const ArrayRef (thin copy)298 ArrayRef<int> AR1(A1);299 const ArrayRef<int> &AR1Ref = ArrayRef(AR1);300 EXPECT_NE(&AR1, &AR1Ref);301 EXPECT_TRUE(AR1.equals(AR1Ref));302 303 // A copy is expected for non-const ArrayRef (thin copy)304 const ArrayRef<int> AR2(A1);305 const ArrayRef<int> &AR2Ref = ArrayRef(AR2);306 EXPECT_NE(&AR2Ref, &AR2);307 EXPECT_TRUE(AR2.equals(AR2Ref));308}309 310TEST(ArrayRefTest, OwningArrayRef) {311 static const int A1[] = {0, 1};312 OwningArrayRef<int> A{ArrayRef(A1)};313 OwningArrayRef<int> B(std::move(A));314 EXPECT_EQ(A.data(), nullptr);315}316 317TEST(ArrayRefTest, ArrayRefFromStdArray) {318 std::array<int, 5> A1{{42, -5, 0, 1000000, -1000000}};319 ArrayRef<int> A2 = ArrayRef(A1);320 321 EXPECT_EQ(A1.size(), A2.size());322 for (std::size_t i = 0; i < A1.size(); ++i) {323 EXPECT_EQ(A1[i], A2[i]);324 }325}326 327struct TestRandomAccessIterator {328 using iterator_category = std::random_access_iterator_tag;329};330 331static_assert(!std::is_constructible_v<332 ArrayRef<int>, iterator_range<TestRandomAccessIterator>>,333 "cannot construct from iterator range with non-pointer iterator");334static_assert(!std::is_constructible_v<ArrayRef<int>, iterator_range<int>>,335 "cannot construct from iterator range with non-pointer iterator");336 337class TestBase {};338 339class TestDerived : public TestBase {};340 341static_assert(342 !std::is_constructible_v<ArrayRef<TestDerived>, iterator_range<TestBase *>>,343 "cannot construct ArrayRef with derived type");344static_assert(345 !std::is_constructible_v<ArrayRef<TestBase>, iterator_range<TestDerived *>>,346 "cannot construct ArrayRef base type");347static_assert(!std::is_constructible_v<ArrayRef<TestBase *>,348 iterator_range<TestDerived **>>,349 "cannot construct ArrayRef pointer of base type");350 351static_assert(352 !std::is_constructible_v<ArrayRef<int>, iterator_range<const int *>>,353 "cannot construct ArrayRef with non-const elements from const iterator "354 "range");355static_assert(356 std::is_constructible_v<ArrayRef<char *>, iterator_range<char **>>,357 "should be able to construct ArrayRef from iterator_range over pointers");358static_assert(359 !std::is_constructible_v<ArrayRef<char *>, iterator_range<char *const *>>,360 "should be able to construct ArrayRef from iterator_range over pointers");361 362TEST(ArrayRefTest, ArrayRefFromIteratorRange) {363 int A1[] = {42, -5, 0, 1000000, -1000000, 0};364 ArrayRef<int> A2 = make_range(&A1[0], &A1[5]);365 366 EXPECT_EQ(5ull, A2.size());367 for (std::size_t i = 0; i < A2.size(); ++i)368 EXPECT_EQ(A1[i], A2[i]);369 370 ArrayRef<const int> A3 = make_range(&A1[0], &A1[5]);371 EXPECT_EQ(5ull, A3.size());372 for (std::size_t i = 0; i < A3.size(); ++i)373 EXPECT_EQ(A1[i], A3[i]);374}375 376TEST(ArrayRefTest, ArrayRefFromIteratorConstRange) {377 const int A1[] = {42, -5, 0, 1000000, -1000000, 0};378 ArrayRef<const int> A2 = make_range(&A1[0], &A1[5]);379 380 EXPECT_EQ(5ull, A2.size());381 for (std::size_t i = 0; i < A2.size(); ++i)382 EXPECT_EQ(A1[i], A2[i]);383}384 385static_assert(std::is_trivially_copyable_v<ArrayRef<int>>,386 "trivially copyable");387 388TEST(ArrayRefTest, MutableArrayRefDeductionGuides) {389 // Single element390 {391 int x = 0;392 auto aref = MutableArrayRef(x);393 static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>);394 EXPECT_EQ(aref.data(), &x);395 EXPECT_EQ(aref.size(), 1u);396 397 // Make sure it's mutable still398 aref[0] = 1;399 EXPECT_EQ(x, 1);400 }401 402 // Pointer + length403 {404 int x[] = {0, 1, 2, 3};405 auto aref = MutableArrayRef(&x[0], 4);406 static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>);407 EXPECT_EQ(aref.data(), &x[0]);408 EXPECT_EQ(aref.size(), 4u);409 }410 411 // // Pointer + pointer412 {413 int x[] = {0, 1, 2, 3};414 auto aref = MutableArrayRef(std::begin(x), std::end(x));415 static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>);416 EXPECT_EQ(aref.data(), &x[0]);417 EXPECT_EQ(aref.size(), 4u);418 }419 420 // SmallVector421 {422 SmallVector<int> sv1;423 SmallVectorImpl<int> &sv2 = sv1;424 sv1.resize(5);425 auto aref1 = MutableArrayRef(sv1);426 auto aref2 = MutableArrayRef(sv2);427 static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref1)>);428 static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref2)>);429 EXPECT_EQ(aref1.data(), sv1.data());430 EXPECT_EQ(aref1.size(), sv1.size());431 EXPECT_EQ(aref2.data(), sv2.data());432 EXPECT_EQ(aref2.size(), sv2.size());433 }434 435 // std::vector436 {437 std::vector<int> x(5);438 auto aref = MutableArrayRef(x);439 static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>);440 EXPECT_EQ(aref.data(), x.data());441 EXPECT_EQ(aref.size(), x.size());442 }443 444 // std::array445 {446 std::array<int, 5> x{};447 auto aref = MutableArrayRef(x);448 static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>);449 EXPECT_EQ(aref.data(), x.data());450 EXPECT_EQ(aref.size(), x.size());451 }452 453 // MutableArrayRef454 {455 MutableArrayRef<int> x{};456 auto aref = MutableArrayRef(x);457 static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>);458 EXPECT_EQ(aref.data(), x.data());459 EXPECT_EQ(aref.size(), x.size());460 461 const MutableArrayRef<int> y{};462 auto aref2 = MutableArrayRef(y);463 static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref2)>);464 EXPECT_EQ(aref2.data(), y.data());465 EXPECT_EQ(aref2.size(), y.size());466 }467 468 // C-style array469 {470 int x[] = {0, 1, 2, 3};471 auto aref = MutableArrayRef(x);472 static_assert(std::is_same_v<MutableArrayRef<int>, decltype(aref)>);473 EXPECT_EQ(aref.data(), &x[0]);474 EXPECT_EQ(aref.size(), 4u);475 }476}477 478#ifdef __cpp_lib_span479static_assert(std::is_constructible_v<ArrayRef<int>, std::span<const int>>,480 "should be able to construct ArrayRef from const std::span");481static_assert(std::is_constructible_v<std::span<const int>, ArrayRef<int>>,482 "should be able to construct const std::span from ArrayRef");483static_assert(std::is_constructible_v<ArrayRef<int>, std::span<int>>,484 "should be able to construct ArrayRef from mutable std::span");485static_assert(!std::is_constructible_v<std::span<int>, ArrayRef<int>>,486 "cannot construct mutable std::span from ArrayRef");487 488static_assert(489 !std::is_constructible_v<MutableArrayRef<int>, std::span<const int>>,490 "cannot construct MutableArrayRef from const std::span");491static_assert(492 std::is_constructible_v<std::span<const int>, MutableArrayRef<int>>,493 "should be able to construct const std::span from MutableArrayRef");494static_assert(495 std::is_constructible_v<MutableArrayRef<int>, std::span<int>>,496 "should be able to construct MutableArrayRef from mutable std::span");497#endif498 499} // end anonymous namespace500