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 @@ -209,11 +209,19 @@ }; template struct cast_convert_val { - // This _is_ a simple type, just cast it. + // If it's a reference, switch to a pointer to do the cast and then deref it. static typename cast_retty::ret_type doit(const FromTy &Val) { - typename cast_retty::ret_type Res2 = - (typename cast_retty::ret_type) const_cast(Val); - return Res2; + return *(std::remove_reference_t::ret_type> + *)&const_cast(Val); + } +}; + +template +struct cast_convert_val { + // If it's a pointer, we can use c-style casting directly. + static typename cast_retty::ret_type doit(const FromTy *Val) { + return (typename cast_retty::ret_type) const_cast( + Val); } }; 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 @@ -298,11 +298,9 @@ ASSERT_EQ(OrigD, D.get()); ASSERT_EQ(nullptr, NewB); - // Converting between unrelated types should fail. The original value should - // remain unchanged and it should return nullptr. - // - // Note that this is a very contrived test - most of the time we want a cast - // like this to emit a compiler error. + // This is a very contrived test, casting between completely unrelated types + // should generally fail to compile. See the classof shenanigans we have in + // the definition of `foo` above. auto F = unique_dyn_cast(D); ASSERT_EQ(nullptr, F); ASSERT_EQ(OrigD, D.get()); @@ -317,6 +315,9 @@ auto B3 = unique_dyn_cast(newb()); EXPECT_NE(nullptr, B3); + // This is a very contrived test, casting between completely unrelated types + // should generally fail to compile. See the classof shenanigans we have in + // the definition of `foo` above. auto F2 = unique_dyn_cast(newb()); EXPECT_EQ(nullptr, F2); }