[llvm] r222644 - Support: Add *cast_or_null<> for pointer wrappers
David Blaikie
dblaikie at gmail.com
Mon Nov 24 09:01:21 PST 2014
On Sun, Nov 23, 2014 at 7:13 PM, Duncan P. N. Exon Smith <
dexonsmith at apple.com> wrote:
> Author: dexonsmith
> Date: Sun Nov 23 21:13:02 2014
> New Revision: 222644
>
> URL: http://llvm.org/viewvc/llvm-project?rev=222644&view=rev
> Log:
> Support: Add *cast_or_null<> for pointer wrappers
>
I'm assuming this is intended to work with unique_ptr? (is it worth testing
with unique_ptr itself, then? (I'm honestly not sure))
In some cases, we actually want ownership transfer:
unique_ptr<Base> b = ...;
unique_ptr<Derived> d = dyn_cast<Derived>(b);
assert(b ^ d);
But I guess it's probably not the right thing to use the existing
names/templates for this task? (if we mostly /don't/ want to transfer
ownership, which I guess is probably the case(?)) Maybe we'll eventually
add some new names for this (*cast*_transfer(?))
>
> Fill in omission of `cast_or_null<>` and `dyn_cast_or_null<>` for types
> that wrap pointers (e.g., smart pointers).
>
> Type traits need to be slightly stricter than for `cast<>` and
> `dyn_cast<>` to resolve ambiguities with simple types.
>
> There didn't seem to be any unit tests for pointer wrappers, so I tested
> `isa<>`, `cast<>`, and `dyn_cast<>` while I was in there.
>
> This only supports pointer wrappers with a conversion to `bool` to check
> for null. If in the future it's useful to support wrappers without such
> a conversion, it should be a straightforward incremental step to use the
> `simplify_type` machinery for the null check. In that case, the unit
> tests should be updated to remove the `operator bool()` from the
> `pointer_wrappers::PTy`.
>
> Modified:
> llvm/trunk/include/llvm/Support/Casting.h
> llvm/trunk/unittests/Support/Casting.cpp
>
> Modified: llvm/trunk/include/llvm/Support/Casting.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Casting.h?rev=222644&r1=222643&r2=222644&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/Support/Casting.h (original)
> +++ llvm/trunk/include/llvm/Support/Casting.h Sun Nov 23 21:13:02 2014
> @@ -243,6 +243,26 @@ inline typename cast_retty<X, Y *>::ret_
> // accepted.
> //
> template <class X, class Y>
> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
> + !is_simple_type<Y>::value, typename cast_retty<X, const
> Y>::ret_type>::type
> +cast_or_null(const Y &Val) {
> + if (!Val)
> + return nullptr;
> + assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible
> type!");
> + return cast<X>(Val);
> +}
> +
> +template <class X, class Y>
> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
> + !is_simple_type<Y>::value, typename cast_retty<X, Y>::ret_type>::type
> +cast_or_null(Y &Val) {
> + if (!Val)
> + return nullptr;
> + assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible
> type!");
> + return cast<X>(Val);
> +}
> +
> +template <class X, class Y>
> LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type
> cast_or_null(Y *Val) {
> if (!Val) return nullptr;
> @@ -282,6 +302,20 @@ dyn_cast(Y *Val) {
> // value is accepted.
> //
> template <class X, class Y>
> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
> + !is_simple_type<Y>::value, typename cast_retty<X, const
> Y>::ret_type>::type
> +dyn_cast_or_null(const Y &Val) {
> + return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
> +}
> +
> +template <class X, class Y>
> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<
> + !is_simple_type<Y>::value, typename cast_retty<X, Y>::ret_type>::type
> +dyn_cast_or_null(Y &Val) {
> + return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
> +}
> +
> +template <class X, class Y>
> LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type
> dyn_cast_or_null(Y *Val) {
> return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;
>
> Modified: llvm/trunk/unittests/Support/Casting.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/Casting.cpp?rev=222644&r1=222643&r2=222644&view=diff
>
> ==============================================================================
> --- llvm/trunk/unittests/Support/Casting.cpp (original)
> +++ llvm/trunk/unittests/Support/Casting.cpp Sun Nov 23 21:13:02 2014
> @@ -232,3 +232,99 @@ namespace TemporaryCast {
> struct pod {};
> IllegalCast *testIllegalCast() { return cast<foo>(pod()); }
> }
> +
> +namespace {
> +namespace pointer_wrappers {
> +
> +struct Base {
> + bool IsDerived;
> + Base(bool IsDerived = false) : IsDerived(IsDerived) {}
> +};
> +
> +struct Derived : Base {
> + Derived() : Base(true) {}
> + static bool classof(const Base *B) { return B->IsDerived; }
> +};
> +
> +class PTy {
> + Base *B;
> +public:
> + PTy(Base *B) : B(B) {}
> + LLVM_EXPLICIT operator bool() const { return get(); }
> + Base *get() const { return B; }
> +};
> +
> +} // end namespace pointer_wrappers
> +} // end namespace
> +
> +namespace llvm {
> +
> +template <> struct simplify_type<pointer_wrappers::PTy> {
> + typedef pointer_wrappers::Base *SimpleType;
> + static SimpleType getSimplifiedValue(pointer_wrappers::PTy &P) {
> + return P.get();
> + }
> +};
> +template <> struct simplify_type<const pointer_wrappers::PTy> {
> + typedef pointer_wrappers::Base *SimpleType;
> + static SimpleType getSimplifiedValue(const pointer_wrappers::PTy &P) {
> + return P.get();
> + }
> +};
> +
> +} // end namespace llvm
> +
> +namespace {
> +namespace pointer_wrappers {
> +
> +// Some objects.
> +pointer_wrappers::Base B;
> +pointer_wrappers::Derived D;
> +
> +// Mutable "smart" pointers.
> +pointer_wrappers::PTy MN(nullptr);
> +pointer_wrappers::PTy MB(&B);
> +pointer_wrappers::PTy MD(&D);
> +
> +// Const "smart" pointers.
> +const pointer_wrappers::PTy CN(nullptr);
> +const pointer_wrappers::PTy CB(&B);
> +const pointer_wrappers::PTy CD(&D);
> +
> +TEST(CastingTest, smart_isa) {
> + EXPECT_TRUE(!isa<pointer_wrappers::Derived>(MB));
> + EXPECT_TRUE(!isa<pointer_wrappers::Derived>(CB));
> + EXPECT_TRUE(isa<pointer_wrappers::Derived>(MD));
> + EXPECT_TRUE(isa<pointer_wrappers::Derived>(CD));
> +}
> +
> +TEST(CastingTest, smart_cast) {
> + EXPECT_TRUE(cast<pointer_wrappers::Derived>(MD) == &D);
> + EXPECT_TRUE(cast<pointer_wrappers::Derived>(CD) == &D);
> +}
> +
> +TEST(CastingTest, smart_cast_or_null) {
> + EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(MN) == nullptr);
> + EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(CN) == nullptr);
> + EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(MD) == &D);
> + EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(CD) == &D);
> +}
> +
> +TEST(CastingTest, smart_dyn_cast) {
> + EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(MB) == nullptr);
> + EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(CB) == nullptr);
> + EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(MD) == &D);
> + EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(CD) == &D);
> +}
> +
> +TEST(CastingTest, smart_dyn_cast_or_null) {
> + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MN) == nullptr);
> + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CN) == nullptr);
> + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MB) == nullptr);
> + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CB) == nullptr);
> + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MD) == &D);
> + EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CD) == &D);
> +}
> +
> +} // end namespace pointer_wrappers
> +} // end namespace
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141124/97a046b6/attachment.html>
More information about the llvm-commits
mailing list