Index: include/llvm/Support/Casting.h =================================================================== --- include/llvm/Support/Casting.h +++ include/llvm/Support/Casting.h @@ -67,51 +67,24 @@ static inline bool doit(const From &) { return true; } }; -template struct isa_impl_cl { - static inline bool doit(const From &Val) { - return isa_impl::doit(Val); - } -}; +template struct isa_impl_cl {}; -template struct isa_impl_cl { +template +struct isa_impl_cl::value>> { + using FromTy = typename std::remove_const::type; static inline bool doit(const From &Val) { - return isa_impl::doit(Val); + return isa_impl::doit(Val); } }; 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"); - return isa_impl::doit(*Val); - } -}; - -template struct isa_impl_cl { - static inline bool doit(const From *Val) { - assert(Val && "isa<> used on a null pointer"); - return isa_impl::doit(*Val); - } -}; - -template struct isa_impl_cl { - static inline bool doit(const From *Val) { - assert(Val && "isa<> used on a null pointer"); - return isa_impl::doit(*Val); - } -}; - -template struct isa_impl_cl { - static inline bool doit(const From *Val) { +struct isa_impl_cl::value>> { + using FromTy = + typename std::remove_const>::type; + static inline bool doit(const From &Val) { assert(Val && "isa<> used on a null pointer"); - return isa_impl::doit(*Val); + return isa_impl::doit(*Val); } }; Index: include/llvm/Support/type_traits.h =================================================================== --- include/llvm/Support/type_traits.h +++ include/llvm/Support/type_traits.h @@ -104,6 +104,30 @@ using type = typename add_const_past_pointer::type; }; +template (), + (void)(std::declval() && true))> +std::true_type is_dereferenceable_test(const T &); +std::false_type is_dereferenceable_test(...); + +template +using is_dereferenceable = decltype(is_dereferenceable_test(std::declval())); + +template +using enable_if_t = typename std::enable_if::type; + +template +using decay_t = typename std::decay::type; + +template struct dereferenced_type; + +template +struct dereferenced_type::value>> { + using type = decay_t())>; +}; + +template +using dereferenced_type_t = typename dereferenced_type::type; + } // end namespace llvm // If the compiler supports detecting whether a class is final, define Index: unittests/Support/Casting.cpp =================================================================== --- unittests/Support/Casting.cpp +++ unittests/Support/Casting.cpp @@ -11,6 +11,7 @@ #include "llvm/IR/User.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/ADT/Optional.h" #include "gtest/gtest.h" #include @@ -281,6 +282,12 @@ EXPECT_TRUE(BP != nullptr); } +TEST(CastingTest, DereferencableIsA) { + std::shared_ptr DShared = std::make_shared(); + EXPECT_TRUE(isa(DShared)); + llvm::Optional DOpt; + EXPECT_TRUE(isa(DOpt)); +} // This test verifies that the inferred upcast takes precedence over an // explicitly written one. This is important because it verifies that the