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 @@ -1286,6 +1286,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 +constexpr 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,67 @@ EXPECT_TRUE(makeArrayRef(V2).equals({4, 5, 3, 2})); } +TEST(SmallVectorTest, ToVector) { + { + std::vector v = {'a', 'b', 'c'}; + auto Vector = to_vector<4>(v); + static_assert(NumBuiltinElts(Vector) == 4u, + "Wrong built-in elements number"); + 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); + static_assert(NumBuiltinElts(Vector) != 4u, + "Wrong built-in elements number"); + ASSERT_EQ(3u, Vector.size()); + for (size_t I = 0; I < v.size(); ++I) { + EXPECT_EQ(v[I], Vector[I]); + } + } +} + +struct To { + int Content; + friend bool operator==(const To &LHS, const To &RHS) { + return LHS.Content == RHS.Content; + } +}; + +class From { +public: + From() = default; + From(To M) { T = M; } + operator To() const { return T; } + +private: + To T; +}; + +TEST(SmallVectorTest, ToVectorOf) { + To to1{1}, to2{2}, to3{3}; + std::vector StdVector = {From(to1), From(to2), From(to3)}; + { + 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]); + } + { + auto Vector = llvm::to_vector_of(StdVector); + + ASSERT_EQ(StdVector.size(), Vector.size()); + static_assert(NumBuiltinElts(Vector) == 4u, + "Wrong built-in elements number"); + for (size_t I = 0; I < StdVector.size(); ++I) + EXPECT_EQ(StdVector[I], Vector[I]); + } +} + template class SmallVectorReferenceInvalidationTest : public SmallVectorTestBase { protected: @@ -1143,11 +1206,6 @@ VectorT V; - template - static unsigned NumBuiltinElts(const SmallVector &) { - return N; - } - template static bool isValueType() { return std::is_same::value; } @@ -1173,7 +1231,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 +1253,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 +1282,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 +1297,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 +1315,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 +1330,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 +1430,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 +1450,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 +1464,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 +1493,6 @@ VectorT V; - template - static unsigned NumBuiltinElts(const SmallVector &) { - return N; - } - void SetUp() override { SmallVectorTestBase::SetUp(); @@ -1460,7 +1513,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);