diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h --- a/llvm/include/llvm/ADT/SmallVector.h +++ b/llvm/include/llvm/ADT/SmallVector.h @@ -1289,6 +1289,15 @@ return {std::begin(Range), std::end(Range)}; } +template +SmallVector to_vector_of(R &&Range) { + return {std::begin(Range), std::end(Range)}; +} + +template SmallVector to_vector_of(R &&Range) { + return {std::begin(Range), std::end(Range)}; +} + } // end namespace llvm namespace std { diff --git a/llvm/unittests/ADT/SmallVectorTest.cpp b/llvm/unittests/ADT/SmallVectorTest.cpp --- a/llvm/unittests/ADT/SmallVectorTest.cpp +++ b/llvm/unittests/ADT/SmallVectorTest.cpp @@ -862,14 +862,16 @@ template class DualSmallVectorsTest; +template +static unsigned NumBuiltinElts(const SmallVector &) { + return N; +} + template class DualSmallVectorsTest> : public SmallVectorTestBase { protected: VectorT1 theVector; VectorT2 otherVector; - - template - static unsigned NumBuiltinElts(const SmallVector&) { return N; } }; typedef ::testing::Types< @@ -909,7 +911,7 @@ // If the source vector (otherVector) was in small-mode, assert that we just // moved the data pointer over. - EXPECT_TRUE(this->NumBuiltinElts(this->otherVector) == 4 || + EXPECT_TRUE(NumBuiltinElts(this->otherVector) == 4 || this->theVector.data() == OrigDataPtr); // There shouldn't be any live objects any more. @@ -1134,6 +1136,91 @@ EXPECT_TRUE(makeArrayRef(V2).equals({4, 5, 3, 2})); } +TEST(SmallVectorTest, ToVector) { + { + std::vector v = {'a', 'b', 'c'}; + auto Vector = to_vector<4>(v); + ASSERT_EQ(4u, NumBuiltinElts(Vector)); + ASSERT_EQ(3u, Vector.size()); + for (size_t I = 0; I < v.size(); ++I) { + EXPECT_EQ(v[I], Vector[I]); + } + } + { + std::vector v = {'a', 'b', 'c'}; + auto Vector = to_vector(v); + ASSERT_NE(4u, NumBuiltinElts(Vector)); + ASSERT_EQ(3u, Vector.size()); + for (size_t I = 0; I < v.size(); ++I) { + EXPECT_EQ(v[I], Vector[I]); + } + } +} + +TEST(SmallVectorTest, ToVectorOf) { + struct From { + int Content; + friend bool operator==(const From &LHS, const From &RHS) { + return LHS.Content == RHS.Content; + } + }; + + class To { + public: + To() = default; + To(From *M) { F = M; } + operator From *() const { return get(); } + From &operator*() const { return *get(); } + + private: + From *get() const { return F; } + From *F = nullptr; + }; + + From from1{1}, from2{2}, from3{3}; + std::vector StdVector = {To(&from1), To(&from2), To(&from3)}; + { + llvm::SmallVector Vector = llvm::to_vector_of(StdVector); + + ASSERT_EQ(StdVector.size(), Vector.size()); + for (size_t I = 0; I < StdVector.size(); ++I) { + EXPECT_EQ(StdVector[I], Vector[I]); + EXPECT_EQ(*StdVector[I], *Vector[I]); + } + } + { + ArrayRef Array = StdVector; + llvm::SmallVector Vector = llvm::to_vector_of(Array); + + ASSERT_EQ(Array.size(), Vector.size()); + for (size_t I = 0; I < Array.size(); ++I) { + EXPECT_EQ(Array[I], Vector[I]); + EXPECT_EQ(*Array[I], *Vector[I]); + } + } + { + auto Vector = llvm::to_vector_of(StdVector); + + ASSERT_EQ(StdVector.size(), Vector.size()); + ASSERT_EQ(4u, NumBuiltinElts(Vector)); + for (size_t I = 0; I < StdVector.size(); ++I) { + EXPECT_EQ(StdVector[I], Vector[I]); + EXPECT_EQ(*StdVector[I], *Vector[I]); + } + } + { + ArrayRef Array = StdVector; + auto Vector = llvm::to_vector_of(Array); + + ASSERT_EQ(Array.size(), Vector.size()); + ASSERT_EQ(4u, NumBuiltinElts(Vector)); + for (size_t I = 0; I < Array.size(); ++I) { + EXPECT_EQ(Array[I], Vector[I]); + EXPECT_EQ(*Array[I], *Vector[I]); + } + } +} + template class SmallVectorReferenceInvalidationTest : public SmallVectorTestBase { protected: @@ -1143,11 +1230,6 @@ VectorT V; - template - static unsigned NumBuiltinElts(const SmallVector &) { - return N; - } - template static bool isValueType() { return std::is_same::value; } @@ -1173,7 +1255,7 @@ TYPED_TEST(SmallVectorReferenceInvalidationTest, PushBack) { // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode. auto &V = this->V; - int N = this->NumBuiltinElts(V); + int N = NumBuiltinElts(V); // Push back a reference to last element when growing from small storage. V.push_back(V.back()); @@ -1195,7 +1277,7 @@ TYPED_TEST(SmallVectorReferenceInvalidationTest, PushBackMoved) { // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode. auto &V = this->V; - int N = this->NumBuiltinElts(V); + int N = NumBuiltinElts(V); // Push back a reference to last element when growing from small storage. V.push_back(std::move(V.back())); @@ -1224,7 +1306,7 @@ TYPED_TEST(SmallVectorReferenceInvalidationTest, Resize) { auto &V = this->V; (void)V; - int N = this->NumBuiltinElts(V); + int N = NumBuiltinElts(V); V.resize(N + 1, V.back()); EXPECT_EQ(N, V.back()); @@ -1239,7 +1321,7 @@ auto &V = this->V; (void)V; V.append(1, V.back()); - int N = this->NumBuiltinElts(V); + int N = NumBuiltinElts(V); EXPECT_EQ(N, V[N - 1]); // Append enough more elements that V will grow again. This tests growing @@ -1257,7 +1339,7 @@ #if !defined(NDEBUG) && GTEST_HAS_DEATH_TEST EXPECT_DEATH(V.append(V.begin(), V.begin() + 1), this->AssertionMessage); - ASSERT_EQ(3u, this->NumBuiltinElts(V)); + ASSERT_EQ(3u, NumBuiltinElts(V)); ASSERT_EQ(3u, V.size()); V.pop_back(); ASSERT_EQ(2u, V.size()); @@ -1272,7 +1354,7 @@ // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode. auto &V = this->V; (void)V; - int N = this->NumBuiltinElts(V); + int N = NumBuiltinElts(V); ASSERT_EQ(unsigned(N), V.size()); ASSERT_EQ(unsigned(N), V.capacity()); @@ -1372,7 +1454,7 @@ // Cover NumToInsert <= this->end() - I. V.insert(V.begin() + 1, 1, V.back()); - int N = this->NumBuiltinElts(V); + int N = NumBuiltinElts(V); EXPECT_EQ(N, V[1]); // Cover NumToInsert > this->end() - I, inserting enough elements that V will @@ -1392,7 +1474,7 @@ EXPECT_DEATH(V.insert(V.begin(), V.begin(), V.begin() + 1), this->AssertionMessage); - ASSERT_EQ(3u, this->NumBuiltinElts(V)); + ASSERT_EQ(3u, NumBuiltinElts(V)); ASSERT_EQ(3u, V.size()); V.pop_back(); ASSERT_EQ(2u, V.size()); @@ -1406,7 +1488,7 @@ TYPED_TEST(SmallVectorReferenceInvalidationTest, EmplaceBack) { // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode. auto &V = this->V; - int N = this->NumBuiltinElts(V); + int N = NumBuiltinElts(V); // Push back a reference to last element when growing from small storage. V.emplace_back(V.back()); @@ -1435,11 +1517,6 @@ VectorT V; - template - static unsigned NumBuiltinElts(const SmallVector &) { - return N; - } - void SetUp() override { SmallVectorTestBase::SetUp(); @@ -1460,7 +1537,7 @@ TYPED_TEST(SmallVectorInternalReferenceInvalidationTest, EmplaceBack) { // Note: setup adds [1, 2, ...] to V until it's at capacity in small mode. auto &V = this->V; - int N = this->NumBuiltinElts(V); + int N = NumBuiltinElts(V); // Push back a reference to last element when growing from small storage. V.emplace_back(V.back().first, V.back().second);