diff --git a/llvm/include/llvm/Support/Casting.h b/llvm/include/llvm/Support/Casting.h --- a/llvm/include/llvm/Support/Casting.h +++ b/llvm/include/llvm/Support/Casting.h @@ -192,6 +192,12 @@ To, From, typename simplify_type::SimpleType>::ret_type; }; +template struct cast_retty { + // Casting T to itself, but have to use a ref if so we don't get a copy if + // it's not a pointer. + using ret_type = std::conditional_t::value, T, T &>; +}; + //===----------------------------------------------------------------------===// // cast_convert_val //===----------------------------------------------------------------------===// @@ -276,7 +282,8 @@ /// always be possible. template struct CastIsPossible::value>> { + std::enable_if_t::value || + std::is_base_of::value>> { static inline bool isPossible(const From &f) { return true; } }; diff --git a/llvm/unittests/Support/Casting.cpp b/llvm/unittests/Support/Casting.cpp --- a/llvm/unittests/Support/Casting.cpp +++ b/llvm/unittests/Support/Casting.cpp @@ -144,6 +144,7 @@ // test various configurations of const const bar &B3 = B1; const bar *const B4 = B2; +bar *B5 = &B; TEST(CastingTest, isa) { EXPECT_TRUE(isa(B1)); @@ -175,6 +176,17 @@ foo *F8 = B1.baz(); EXPECT_NE(F8, null_foo); + // Ensure cast-to-self works (with the type in the template verbatim + // equivalent to the type in the input). + auto B9 = cast(B5); + static_assert(std::is_same::value, + "Inccorrect return type!"); + EXPECT_EQ(B9, B5); + auto B10 = cast(B2); + static_assert(std::is_same::value, + "Inccorrect return type!"); + EXPECT_EQ(B10, B2); + std::unique_ptr BP(B2); auto FP = cast(std::move(BP)); static_assert(std::is_same, decltype(FP)>::value, @@ -212,6 +224,17 @@ // EXPECT_EQ(F4, null_foo); foo *F5 = B1.daz(); EXPECT_NE(F5, null_foo); + + // Ensure cast-to-self works (with the type in the template verbatim + // equivalent to the type in the input). + auto B9 = dyn_cast(B5); + static_assert(std::is_same::value, + "Inccorrect return type!"); + EXPECT_EQ(B9, B5); + auto B10 = dyn_cast(B2); + static_assert(std::is_same::value, + "Inccorrect return type!"); + EXPECT_EQ(B10, B2); } // All these tests forward to dyn_cast_if_present, so they also provde an