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 @@ -353,9 +353,9 @@ static inline CastResultType castFailed() { return CastResultType(nullptr); } static inline CastResultType doCastIfPossible(std::unique_ptr &&f) { - if (!Self::isPossible(f)) + if (!Self::isPossible(f.get())) return castFailed(); - return doCast(f); + return doCast(std::forward>(f)); } }; 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 @@ -45,6 +45,10 @@ static bool classof(const base *B) { return true; } }; +struct derived_nocast : public base { + static bool classof(const base *B) { return false; } +}; + template <> struct isa_impl { static inline bool doit(const bar &Val) { dbgs() << "Classof: " << &Val << "\n"; @@ -212,6 +216,20 @@ // EXPECT_EQ(F4, null_foo); foo *F5 = B1.daz(); EXPECT_NE(F5, null_foo); + + std::unique_ptr BP(B2); + auto FP = dyn_cast(std::move(BP)); + static_assert(std::is_same_v, decltype(FP)>, + "Incorrect deduced return type!"); + EXPECT_NE(FP.get(), null_foo); + EXPECT_EQ(BP.get(), nullptr); + FP.release(); + + auto BP2 = std::make_unique(); + auto DP = dyn_cast(std::move(BP2)); + EXPECT_EQ(DP.get(), nullptr); + EXPECT_NE(BP2.get(), nullptr); + BP2.release(); } // All these tests forward to dyn_cast_if_present, so they also provde an