[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