From: Michael Gottesman Date: Wed, 31 Dec 2014 23:33:18 +0000 (+0000) Subject: Add an ArrayRef upcasting constructor from ArrayRef -> ArrayRef where T is... X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=77b1aa98ed886df65c294d711eb2ca31f39eeee3;p=platform%2Fupstream%2Fllvm.git Add an ArrayRef upcasting constructor from ArrayRef -> ArrayRef where T is a base of U. llvm-svn: 225053 --- diff --git a/llvm/include/llvm/ADT/ArrayRef.h b/llvm/include/llvm/ADT/ArrayRef.h index 8c14a42..b93142d 100644 --- a/llvm/include/llvm/ADT/ArrayRef.h +++ b/llvm/include/llvm/ADT/ArrayRef.h @@ -112,6 +112,16 @@ namespace llvm { std::is_convertible::value>::type* = 0) : Data(A.data()), Length(A.size()) {} + /// Construct an ArrayRef from an ArrayRef where T is a super class + /// of U. This uses SFINAE to ensure that only ArrayRefs with this property + /// can be converted. This is an upcasting constructor. + template + ArrayRef(const ArrayRef &A, + typename std::enable_if::type, + typename std::remove_pointer::type>::value>::type * = 0) + : Data(reinterpret_cast(A.data())), Length(A.size()) {} + /// @} /// @name Simple Operations /// @{ diff --git a/llvm/unittests/ADT/ArrayRefTest.cpp b/llvm/unittests/ADT/ArrayRefTest.cpp index f9c98a5..9cd17f0 100644 --- a/llvm/unittests/ADT/ArrayRefTest.cpp +++ b/llvm/unittests/ADT/ArrayRefTest.cpp @@ -90,4 +90,39 @@ TEST(ArrayRefTest, ConstConvert) { a = ArrayRef(A); } +struct A { + int data; + + A() : data(0) {} +}; + +struct B : A { + int data2; + + B() : A(), data2(0) {} +}; + +TEST(ArrayRefTest, UpcastConvert) { + B Data[5]; + + for (unsigned i = 0, e = 5; i != e; ++i) { + Data[i].data = i + 5; + Data[i].data2 = i + 30; + } + + B *DataPtrs[5]; + for (unsigned i = 0, e = 5; i != e; ++i) { + DataPtrs[i] = &Data[i]; + } + + ArrayRef BArray(DataPtrs, 5); + ArrayRef AArray(BArray); + + EXPECT_TRUE(AArray.size() == 5); + for (unsigned i = 0, e = 5; i != e; ++i) { + A *a = AArray[i]; + EXPECT_TRUE(a->data == int(i + 5)); + } +} + } // end anonymous namespace