diff --git a/llvm/include/llvm/ADT/ArrayRef.h b/llvm/include/llvm/ADT/ArrayRef.h --- a/llvm/include/llvm/ADT/ArrayRef.h +++ b/llvm/include/llvm/ADT/ArrayRef.h @@ -562,6 +562,41 @@ return ArrayRef(Arr); } + /// @name MutableArrayRef Deduction guides + /// @{ + /// Deduction guide to construct a `MutableArrayRef` from a single element + template MutableArrayRef(T &OneElt) -> MutableArrayRef; + + /// Deduction guide to construct a `MutableArrayRef` from a pointer and + /// length. + template + MutableArrayRef(T *data, size_t length) -> MutableArrayRef; + + /// Deduction guide to construct a `MutableArrayRef` from a `SmallVector`. + template + MutableArrayRef(SmallVectorImpl &Vec) -> MutableArrayRef; + + template + MutableArrayRef(SmallVector &Vec) -> MutableArrayRef; + + /// Deduction guide to construct a `MutableArrayRef` from a `std::vector`. + template MutableArrayRef(std::vector &Vec) -> MutableArrayRef; + + /// Deduction guide to construct a `MutableArrayRef` from a `std::array`. + template + MutableArrayRef(std::array &Vec) -> MutableArrayRef; + + /// Deduction guide to construct a `MutableArrayRef` from a `MutableArrayRef` + /// (no-op) (const). + template + MutableArrayRef(const MutableArrayRef &Vec) -> MutableArrayRef; + + /// Deduction guide to construct a `MutableArrayRef` from a C array. + template + MutableArrayRef(T (&Arr)[N]) -> MutableArrayRef; + + /// @} + /// Construct a MutableArrayRef from a single element. template MutableArrayRef makeMutableArrayRef(T &OneElt) { diff --git a/llvm/unittests/ADT/ArrayRefTest.cpp b/llvm/unittests/ADT/ArrayRefTest.cpp --- a/llvm/unittests/ADT/ArrayRefTest.cpp +++ b/llvm/unittests/ADT/ArrayRefTest.cpp @@ -297,4 +297,90 @@ EXPECT_EQ(ER.size(), E.size()); } +TEST(ArrayRefTest, MutableArrayRefDeductionGuides) { + // Single element + { + int x = 0; + auto aref = MutableArrayRef(x); + static_assert(std::is_same_v, decltype(aref)>); + EXPECT_EQ(aref.data(), &x); + EXPECT_EQ(aref.size(), 1u); + + // Make sure it's mutable still + aref[0] = 1; + EXPECT_EQ(x, 1); + } + + // Pointer + length + { + int x[] = {0, 1, 2, 3}; + auto aref = MutableArrayRef(&x[0], 4); + static_assert(std::is_same_v, decltype(aref)>); + EXPECT_EQ(aref.data(), &x[0]); + EXPECT_EQ(aref.size(), 4u); + } + + // // Pointer + pointer + { + int x[] = {0, 1, 2, 3}; + auto aref = MutableArrayRef(std::begin(x), std::end(x)); + static_assert(std::is_same_v, decltype(aref)>); + EXPECT_EQ(aref.data(), &x[0]); + EXPECT_EQ(aref.size(), 4u); + } + + // SmallVector + { + SmallVector sv1; + SmallVectorImpl &sv2 = sv1; + sv1.resize(5); + auto aref1 = MutableArrayRef(sv1); + auto aref2 = MutableArrayRef(sv2); + static_assert(std::is_same_v, decltype(aref1)>); + static_assert(std::is_same_v, decltype(aref2)>); + EXPECT_EQ(aref1.data(), sv1.data()); + EXPECT_EQ(aref1.size(), sv1.size()); + EXPECT_EQ(aref2.data(), sv2.data()); + EXPECT_EQ(aref2.size(), sv2.size()); + } + + // std::vector + { + std::vector x(5); + auto aref = MutableArrayRef(x); + static_assert(std::is_same_v, decltype(aref)>); + EXPECT_EQ(aref.data(), x.data()); + EXPECT_EQ(aref.size(), x.size()); + } + + // std::array + { + std::array x{}; + auto aref = MutableArrayRef(x); + static_assert(std::is_same_v, decltype(aref)>); + EXPECT_EQ(aref.data(), x.data()); + EXPECT_EQ(aref.size(), x.size()); + } + + // MutableArrayRef + { + // needs to be `const`, otherwise it would be an ambiguous deduction with + // the single, non-const element. + const MutableArrayRef x{}; + auto aref = MutableArrayRef(x); + static_assert(std::is_same_v, decltype(aref)>); + EXPECT_EQ(aref.data(), x.data()); + EXPECT_EQ(aref.size(), x.size()); + } + + // C-style array + { + int x[] = {0, 1, 2, 3}; + auto aref = MutableArrayRef(x); + static_assert(std::is_same_v, decltype(aref)>); + EXPECT_EQ(aref.data(), &x[0]); + EXPECT_EQ(aref.size(), 4u); + } +} + } // end anonymous namespace