[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 11:07:54 PDT 2017
zturner created this revision.
Currently it's possible to take a `T*` and cast it to a `U*` using llvm's casting mechanics, but it's not possible to take a `std::unique_ptr<T>` and cast it to a `std::unique_ptr<U>` even if they are compatible. This patch adds this functionality.
I tried to modify the `cast` macros as well as the `dyn_cast` macros, but honestly the template mechanics started getting a little hairy and I wasn't able to get it working. Upon further reflection, I decided that maybe we don't even want that behavior anyway, since if `T` is not a `U`, then no good can possibly come of casting it to one in the face of `unique_ptr`'s RAII semantics. So hopefully I can get this in without adding `cast<>()` functionality, and then if/when someone actually needs `cast` functionality in the future, they can revisit this.
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
@@ -150,6 +150,11 @@
// EXPECT_EQ(F4, null_foo);
foo *F5 = B1.daz();
EXPECT_NE(F5, null_foo);
+
+ std::unique_ptr<const bar> BP(B2);
+ std::unique_ptr<const foo> FP = dyn_cast<foo>(BP);
+ EXPECT_NE(FP.get(), null_foo);
+ FP.release();
}
TEST(CastingTest, dyn_cast_or_null) {
@@ -163,6 +168,10 @@
EXPECT_EQ(F4, null_foo);
foo *F5 = B1.naz();
EXPECT_NE(F5, null_foo);
+
+ std::unique_ptr<const bar> BP(fub());
+ std::unique_ptr<const foo> FP = dyn_cast_or_null<foo>(BP);
+ EXPECT_EQ(FP.get(), null_foo);
}
// These lines are errors...
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,17 @@
typedef const To* ret_type; // Constant pointer arg case, return const Ty*
};
+struct bar;
+
+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 {
@@ -298,6 +310,15 @@
return isa<X>(Val) ? cast<X>(Val) : nullptr;
}
+template <class X, class Y>
+LLVM_NODISCARD inline typename cast_retty<X, std::unique_ptr<Y>>::ret_type
+dyn_cast(std::unique_ptr<Y> &Val) {
+ if (!isa<X>(Val.get()))
+ return nullptr;
+ typedef typename cast_retty<X, std::unique_ptr<Y>>::ret_type ret_type;
+ return ret_type(cast<X>(Val.release()));
+}
+
// dyn_cast_or_null<X> - Functionally identical to dyn_cast, except that a null
// value is accepted.
//
@@ -323,6 +344,14 @@
return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
}
+template <class X, class Y>
+LLVM_NODISCARD inline typename cast_retty<X, std::unique_ptr<Y>>::ret_type
+dyn_cast_or_null(std::unique_ptr<Y> &Val) {
+ if (!Val)
+ return nullptr;
+ return dyn_cast<X>(Val);
+}
+
} // End llvm namespace
#endif
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D31890.94687.patch
Type: text/x-patch
Size: 2431 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20170410/75e8cdbf/attachment.bin>
More information about the llvm-commits
mailing list