[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