diff --git a/llvm/include/llvm/ADT/SmallVector.h b/llvm/include/llvm/ADT/SmallVector.h index ca0b918f56c46..51109d1f416f2 100644 --- a/llvm/include/llvm/ADT/SmallVector.h +++ b/llvm/include/llvm/ADT/SmallVector.h @@ -14,6 +14,7 @@ #ifndef LLVM_ADT_SMALLVECTOR_H #define LLVM_ADT_SMALLVECTOR_H +#include "llvm/ADT/ADL.h" #include "llvm/ADT/DenseMapInfo.h" #include "llvm/Support/Compiler.h" #include @@ -1295,28 +1296,27 @@ inline size_t capacity_in_bytes(const SmallVector &X) { template using ValueTypeFromRangeType = - std::remove_const_t()))>>; + std::remove_const_t>; /// Given a range of type R, iterate the entire range and return a /// SmallVector with elements of the vector. This is useful, for example, /// when you want to iterate a range and then sort the results. template SmallVector, Size> to_vector(R &&Range) { - return {std::begin(Range), std::end(Range)}; + return {adl_begin(Range), adl_end(Range)}; } template SmallVector> to_vector(R &&Range) { - return {std::begin(Range), std::end(Range)}; + return {adl_begin(Range), adl_end(Range)}; } template SmallVector to_vector_of(R &&Range) { - return {std::begin(Range), std::end(Range)}; + return {adl_begin(Range), adl_end(Range)}; } template SmallVector to_vector_of(R &&Range) { - return {std::begin(Range), std::end(Range)}; + return {adl_begin(Range), adl_end(Range)}; } // Explicit instantiations diff --git a/llvm/unittests/ADT/SmallVectorTest.cpp b/llvm/unittests/ADT/SmallVectorTest.cpp index b216359ffd31c..1a01f30e8dd35 100644 --- a/llvm/unittests/ADT/SmallVectorTest.cpp +++ b/llvm/unittests/ADT/SmallVectorTest.cpp @@ -13,6 +13,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/Support/Compiler.h" +#include "gmock/gmock.h" #include "gtest/gtest.h" #include #include @@ -1156,6 +1157,17 @@ TEST(SmallVectorTest, InitializerList) { EXPECT_TRUE(ArrayRef(V2).equals({4, 5, 3, 2})); } +namespace namespace_with_adl { +struct MyVector { + std::vector data; +}; + +std::vector::const_iterator begin(const MyVector &V) { + return V.data.begin(); +} +std::vector::const_iterator end(const MyVector &V) { return V.data.end(); } +} // namespace namespace_with_adl + TEST(SmallVectorTest, ToVector) { { std::vector v = {'a', 'b', 'c'}; @@ -1173,6 +1185,15 @@ TEST(SmallVectorTest, ToVector) { for (size_t I = 0; I < v.size(); ++I) EXPECT_EQ(v[I], Vector[I]); } + { + // Check that to_vector and to_vector_of work with types that require ADL + // for being/end iterators. + namespace_with_adl::MyVector V = {{1, 2, 3}}; + auto IntVector = to_vector(V); + EXPECT_THAT(IntVector, testing::ElementsAre(1, 2, 3)); + IntVector = to_vector<3>(V); + EXPECT_THAT(IntVector, testing::ElementsAre(1, 2, 3)); + } } struct To { @@ -1231,6 +1252,15 @@ TEST(SmallVectorTest, ToVectorOf) { for (size_t I = 0; I < StdVector.size(); ++I) EXPECT_EQ(StdVector[I], Vector[I]); } + { + // Check that to_vector works with types that require ADL for being/end + // iterators. + namespace_with_adl::MyVector V = {{1, 2, 3}}; + auto UnsignedVector = to_vector_of(V); + EXPECT_THAT(UnsignedVector, testing::ElementsAre(1u, 2u, 3u)); + UnsignedVector = to_vector_of(V); + EXPECT_THAT(UnsignedVector, testing::ElementsAre(1u, 2u, 3u)); + } } template