[llvm] a7a634a - [LLVM][Casting.h] Fix dyn_cast for std::unique_ptr.

Aleksandr Bezzubikov via llvm-commits llvm-commits at lists.llvm.org
Sun Aug 13 18:05:09 PDT 2023


Author: Aleksandr Bezzubikov
Date: 2023-08-13T18:04:19-07:00
New Revision: a7a634aa2b5c815d18defc32fb837e079d96d1fc

URL: https://github.com/llvm/llvm-project/commit/a7a634aa2b5c815d18defc32fb837e079d96d1fc
DIFF: https://github.com/llvm/llvm-project/commit/a7a634aa2b5c815d18defc32fb837e079d96d1fc.diff

LOG: [LLVM][Casting.h] Fix dyn_cast for std::unique_ptr.

Unlike isa<> and cast<>, current implementation of dyn_cast<> fails
to process a std::unique_ptr to a class supporting LLVM RTTI:

// A and B support LLVM RTTI
class A {...}
class B: public A {...}

void foo() {
...
  auto V = std::make_unique<A>();
  auto VB = dyn_cast<B>(std::move(V));
  if (VB)
    ...
...
}

Reviewed By: lattner, bzcheeseman

Differential Revision: https://reviews.llvm.org/D147991

Added: 
    

Modified: 
    llvm/include/llvm/Support/Casting.h
    llvm/unittests/Support/Casting.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Support/Casting.h b/llvm/include/llvm/Support/Casting.h
index a0a6fb053d3140..2391c1a531a5be 100644
--- a/llvm/include/llvm/Support/Casting.h
+++ b/llvm/include/llvm/Support/Casting.h
@@ -351,10 +351,10 @@ struct UniquePtrCast : public CastIsPossible<To, From *> {
 
   static inline CastResultType castFailed() { return CastResultType(nullptr); }
 
-  static inline CastResultType doCastIfPossible(std::unique_ptr<From> &&f) {
-    if (!Self::isPossible(f))
+  static inline CastResultType doCastIfPossible(std::unique_ptr<From> &f) {
+    if (!Self::isPossible(f.get()))
       return castFailed();
-    return doCast(f);
+    return doCast(std::move(f));
   }
 };
 
@@ -664,10 +664,9 @@ template <typename To, typename From>
 }
 
 template <typename To, typename From>
-[[nodiscard]] inline decltype(auto) dyn_cast(std::unique_ptr<From> &&Val) {
+[[nodiscard]] inline decltype(auto) dyn_cast(std::unique_ptr<From> &Val) {
   assert(detail::isPresent(Val) && "dyn_cast on a non-existent value");
-  return CastInfo<To, std::unique_ptr<From>>::doCastIfPossible(
-      std::forward<std::unique_ptr<From> &&>(Val));
+  return CastInfo<To, std::unique_ptr<From>>::doCastIfPossible(Val);
 }
 
 /// isa_and_present<X> - Functionally identical to isa, except that a null value

diff  --git a/llvm/unittests/Support/Casting.cpp b/llvm/unittests/Support/Casting.cpp
index ed05963bc105cf..a9256548145986 100644
--- a/llvm/unittests/Support/Casting.cpp
+++ b/llvm/unittests/Support/Casting.cpp
@@ -45,6 +45,10 @@ struct derived : public base {
   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<foo, bar> {
   static inline bool doit(const bar &Val) {
     dbgs() << "Classof: " << &Val << "\n";
@@ -212,6 +216,18 @@ TEST(CastingTest, dyn_cast) {
   // EXPECT_EQ(F4, null_foo);
   foo *F5 = B1.daz();
   EXPECT_NE(F5, null_foo);
+
+  auto BP = std::make_unique<const bar>();
+  auto FP = dyn_cast<foo>(BP);
+  static_assert(std::is_same_v<std::unique_ptr<const foo>, decltype(FP)>,
+                "Incorrect deduced return type!");
+  EXPECT_NE(FP.get(), nullptr);
+  EXPECT_EQ(BP.get(), nullptr);
+
+  auto BP2 = std::make_unique<base>();
+  auto DP = dyn_cast<derived_nocast>(BP2);
+  EXPECT_EQ(DP.get(), nullptr);
+  EXPECT_NE(BP2.get(), nullptr);
 }
 
 // All these tests forward to dyn_cast_if_present, so they also provde an


        


More information about the llvm-commits mailing list