[PATCH] D31890: Add support for unique_ptr<T> to dyn_cast<>

Zachary Turner via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 10 14:53:28 PDT 2017


zturner updated this revision to Diff 94746.
zturner added a reviewer: rsmith.
zturner added a comment.

Discussed this with rsmith@ some, and we came to the conclusion that it's actually the other way around.  We should support this **only** for `cast`, and not for `dyn_cast`.  The reason being that you would need to declare the function as `dyn_cast(unique_ptr<T> &&Value)`, and so to invoke it you would need to write `dyn_cast<To>(std::move(From))`.  So even though you're writing this as an unconditional move, it's actually a conditional move, because if it's not actually convertible to `To` then you would want to return `nullptr` and leave the source unchanged.  The code would still work, but it would just be confusing because `std::move(From)` sometimes doesn't actually move anything.

This patch removes the implementation of `dyn_cast<>` and adds a version of `cast<>` which has expected semantics.  It moves unconditionally, and just asserts if it's the wrong type.


https://reviews.llvm.org/D31890

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


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<const bar> BP(B2);
+  auto FP = cast<foo>(std::move(BP));
+  static_assert(std::is_same<std::unique_ptr<const foo>, 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<const bar> BP(fub());
+  auto FP = cast_or_null<foo>(std::move(BP));
+  EXPECT_EQ(FP.get(), null_foo);
 }
 
 TEST(CastingTest, dyn_cast) {
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 <cassert>
+#include <memory>
 
 namespace llvm {
 
@@ -161,6 +162,15 @@
   typedef const To* ret_type;   // Constant pointer arg case, return const Ty*
 };
 
+template <class To, class From>
+struct cast_retty_impl<To, std::unique_ptr<From>> {
+private:
+  typedef typename cast_retty_impl<To, From *>::ret_type PointerType;
+  typedef typename std::remove_pointer<PointerType>::type ResultType;
+
+public:
+  typedef std::unique_ptr<ResultType> ret_type;
+};
 
 template<class To, class From, class SimpleFrom>
 struct cast_retty_wrap {
@@ -238,6 +248,16 @@
                           typename simplify_type<Y*>::SimpleType>::doit(Val);
 }
 
+template <class X, class Y>
+inline typename cast_retty<X, std::unique_ptr<Y>>::ret_type
+cast(std::unique_ptr<Y> &&Val) {
+  assert(isa<X>(Val.get()) && "cast<Ty>() argument of incompatible type!");
+  using ret_type = typename cast_retty<X, std::unique_ptr<Y>>::ret_type;
+  return ret_type(
+      cast_convert_val<X, Y *, typename simplify_type<Y *>::SimpleType>::doit(
+          Val.release()));
+}
+
 // cast_or_null<X> - Functionally identical to cast, except that a null value is
 // accepted.
 //
@@ -271,6 +291,13 @@
   return cast<X>(Val);
 }
 
+template <class X, class Y>
+inline typename cast_retty<X, std::unique_ptr<Y>>::ret_type
+cast_or_null(std::unique_ptr<Y> &&Val) {
+  if (!Val)
+    return nullptr;
+  return cast<X>(std::move(Val));
+}
 
 // dyn_cast<X> - 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


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D31890.94746.patch
Type: text/x-patch
Size: 2721 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170410/b1a4ca16/attachment-0001.bin>


More information about the llvm-commits mailing list