Index: llvm/include/llvm/Support/Casting.h =================================================================== --- llvm/include/llvm/Support/Casting.h +++ llvm/include/llvm/Support/Casting.h @@ -18,6 +18,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/type_traits.h" #include +#include namespace llvm { @@ -76,6 +77,14 @@ } }; +template +struct isa_impl_cl> { + static inline bool doit(const std::unique_ptr &Val) { + assert(Val && "isa<> used on a null pointer"); + return isa_impl_cl::doit(*Val); + } +}; + template struct isa_impl_cl { static inline bool doit(const From *Val) { assert(Val && "isa<> used on a null pointer"); @@ -161,6 +170,15 @@ typedef const To* ret_type; // Constant pointer arg case, return const Ty* }; +template +struct cast_retty_impl> { +private: + typedef typename cast_retty_impl::ret_type PointerType; + typedef typename std::remove_pointer::type ResultType; + +public: + typedef std::unique_ptr ret_type; +}; template struct cast_retty_wrap { @@ -238,6 +256,16 @@ typename simplify_type::SimpleType>::doit(Val); } +template +inline typename cast_retty>::ret_type +cast(std::unique_ptr &&Val) { + assert(isa(Val.get()) && "cast() argument of incompatible type!"); + using ret_type = typename cast_retty>::ret_type; + return ret_type( + cast_convert_val::SimpleType>::doit( + Val.release())); +} + // cast_or_null - Functionally identical to cast, except that a null value is // accepted. // @@ -271,6 +299,13 @@ return cast(Val); } +template +inline typename cast_retty>::ret_type +cast_or_null(std::unique_ptr &&Val) { + if (!Val) + return nullptr; + return cast(std::move(Val)); +} // dyn_cast - Return the argument parameter cast to the specified type. This // casting operator returns null if the argument is of the wrong type, so it can Index: llvm/unittests/Support/Casting.cpp =================================================================== --- llvm/unittests/Support/Casting.cpp +++ llvm/unittests/Support/Casting.cpp @@ -123,6 +123,13 @@ // EXPECT_EQ(F7, null_foo); foo *F8 = B1.baz(); EXPECT_NE(F8, null_foo); + + std::unique_ptr BP(B2); + auto FP = cast(std::move(BP)); + static_assert(std::is_same, decltype(FP)>::value, + "Incorrect deduced return type!"); + EXPECT_NE(FP.get(), null_foo); + FP.release(); } TEST(CastingTest, cast_or_null) { @@ -136,6 +143,10 @@ EXPECT_EQ(F14, null_foo); foo *F15 = B1.caz(); EXPECT_NE(F15, null_foo); + + std::unique_ptr BP(fub()); + auto FP = cast_or_null(std::move(BP)); + EXPECT_EQ(FP.get(), null_foo); } TEST(CastingTest, dyn_cast) {