<html><head><meta http-equiv="Content-Type" content="text/html charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space;" class=""><br class=""><div><blockquote type="cite" class=""><div class="">On Dec 3, 2014, at 2:00 PM, David Blaikie <<a href="mailto:dblaikie@gmail.com" class="">dblaikie@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="ltr" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="gmail_extra"><br class="Apple-interchange-newline"><br class=""><div class="gmail_quote">On Fri, Nov 28, 2014 at 6:14 PM, Duncan P. N. Exon Smith<span class="Apple-converted-space"> </span><span dir="ltr" class=""><<a href="mailto:dexonsmith@apple.com" target="_blank" class="">dexonsmith@apple.com</a>></span><span class="Apple-converted-space"> </span>wrote:<br class=""><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><span class=""><br class="">> On 2014 Nov 24, at 09:01, David Blaikie <<a href="mailto:dblaikie@gmail.com" class="">dblaikie@gmail.com</a>> wrote:<br class="">><br class="">><br class="">><br class="">> On Sun, Nov 23, 2014 at 7:13 PM, Duncan P. N. Exon Smith <<a href="mailto:dexonsmith@apple.com" class="">dexonsmith@apple.com</a>> wrote:<br class="">> Author: dexonsmith<br class="">> Date: Sun Nov 23 21:13:02 2014<br class="">> New Revision: 222644<br class="">><br class="">> URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project?rev=222644&view=rev" target="_blank" class="">http://llvm.org/viewvc/llvm-project?rev=222644&view=rev</a><br class="">> Log:<br class="">> Support: Add *cast_or_null<> for pointer wrappers<br class="">><br class="">> 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))<br class=""><br class=""></span>Well, yes, but not only `unique_ptr<>`.  My motivating use case is a<br class="">yet-to-be-committed pointer-wrapper for `Metadata` operands, similar<br class="">to `Use` for `Value`.<br class=""><br class="">I think testing a dumb pointer-wrapper directly matches better how<br class="">`simpify_type` is implemented.  And it's a bit more flexible if at<br class="">some point we want to support a type that supports `simplify_type`<br class="">but doesn't have an `operator bool()`.<br class=""></blockquote><div class=""><br class="">Hmm, OK. (we could use "== nullptr" as the boolean test, rather than operator bool, not sure either's better, so long as it can cope with explicit operator bool, which I see you tested)<br class=""> </div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><span class=""><br class="">><br class="">> In some cases, we actually want ownership transfer:<br class="">><br class="">>   unique_ptr<Base> b = ...;<br class="">>   unique_ptr<Derived> d = dyn_cast<Derived>(b);<br class="">>   assert(b ^ d);<br class="">><br class="">> 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(?))<br class=""></span></blockquote></div></div></div></div></blockquote>cast*_move perhaps?  Given that i’d write std::move to transfer ownership from one unique_ptr to another, would it be reasonable to overload that name here?</div><div><br class=""></div><div>Pete<br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><span class=""><br class=""></span>I agree we would need different names, but I'm not sure it fits in<br class="">the same library -- these are meant to be lightweight RTTI<br class="">replacements.  Ownership transfer seems perpendicular to RTTI.<br class=""></blockquote><div class=""><br class="">Except it unfortunately isn't - see <a href="http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast" class="">http://en.cppreference.com/w/cpp/memory/shared_ptr/pointer_cast</a><span class="Apple-converted-space"> </span>- mostly because those shared_ptr is more finicky to transfer ownership while changing types, etc. So there aren't equivalents for unique_ptr - but like make_shared, there's some convenience in also having make_unique (& thus in having unique_casts).<br class=""> </div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;">Nevertheless, I wouldn't be against having convenient wrappers for<br class="">casting+transfer if we have enough use cases for it...<br class=""></blockquote><div class=""><br class="">*nod* some day, perhaps<br class=""> </div><blockquote class="gmail_quote" style="margin: 0px 0px 0px 0.8ex; border-left-width: 1px; border-left-color: rgb(204, 204, 204); border-left-style: solid; padding-left: 1ex;"><div class=""><div class="h5"><br class="">><br class="">><br class="">> Fill in omission of `cast_or_null<>` and `dyn_cast_or_null<>` for types<br class="">> that wrap pointers (e.g., smart pointers).<br class="">><br class="">> Type traits need to be slightly stricter than for `cast<>` and<br class="">> `dyn_cast<>` to resolve ambiguities with simple types.<br class="">><br class="">> There didn't seem to be any unit tests for pointer wrappers, so I tested<br class="">> `isa<>`, `cast<>`, and `dyn_cast<>` while I was in there.<br class="">><br class="">> This only supports pointer wrappers with a conversion to `bool` to check<br class="">> for null.  If in the future it's useful to support wrappers without such<br class="">> a conversion, it should be a straightforward incremental step to use the<br class="">> `simplify_type` machinery for the null check.  In that case, the unit<br class="">> tests should be updated to remove the `operator bool()` from the<br class="">> `pointer_wrappers::PTy`.<br class="">><br class="">> Modified:<br class="">>     llvm/trunk/include/llvm/Support/Casting.h<br class="">>     llvm/trunk/unittests/Support/Casting.cpp<br class="">><br class="">> Modified: llvm/trunk/include/llvm/Support/Casting.h<br class="">> URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Casting.h?rev=222644&r1=222643&r2=222644&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Casting.h?rev=222644&r1=222643&r2=222644&view=diff</a><br class="">> ==============================================================================<br class="">> --- llvm/trunk/include/llvm/Support/Casting.h (original)<br class="">> +++ llvm/trunk/include/llvm/Support/Casting.h Sun Nov 23 21:13:02 2014<br class="">> @@ -243,6 +243,26 @@ inline typename cast_retty<X, Y *>::ret_<br class="">>  // accepted.<br class="">>  //<br class="">>  template <class X, class Y><br class="">> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<<br class="">> +    !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type<br class="">> +cast_or_null(const Y &Val) {<br class="">> +  if (!Val)<br class="">> +    return nullptr;<br class="">> +  assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");<br class="">> +  return cast<X>(Val);<br class="">> +}<br class="">> +<br class="">> +template <class X, class Y><br class="">> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<<br class="">> +    !is_simple_type<Y>::value, typename cast_retty<X, Y>::ret_type>::type<br class="">> +cast_or_null(Y &Val) {<br class="">> +  if (!Val)<br class="">> +    return nullptr;<br class="">> +  assert(isa<X>(Val) && "cast_or_null<Ty>() argument of incompatible type!");<br class="">> +  return cast<X>(Val);<br class="">> +}<br class="">> +<br class="">> +template <class X, class Y><br class="">>  LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type<br class="">>  cast_or_null(Y *Val) {<br class="">>    if (!Val) return nullptr;<br class="">> @@ -282,6 +302,20 @@ dyn_cast(Y *Val) {<br class="">>  // value is accepted.<br class="">>  //<br class="">>  template <class X, class Y><br class="">> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<<br class="">> +    !is_simple_type<Y>::value, typename cast_retty<X, const Y>::ret_type>::type<br class="">> +dyn_cast_or_null(const Y &Val) {<br class="">> +  return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;<br class="">> +}<br class="">> +<br class="">> +template <class X, class Y><br class="">> +LLVM_ATTRIBUTE_UNUSED_RESULT inline typename std::enable_if<<br class="">> +    !is_simple_type<Y>::value, typename cast_retty<X, Y>::ret_type>::type<br class="">> +dyn_cast_or_null(Y &Val) {<br class="">> +  return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;<br class="">> +}<br class="">> +<br class="">> +template <class X, class Y><br class="">>  LLVM_ATTRIBUTE_UNUSED_RESULT inline typename cast_retty<X, Y *>::ret_type<br class="">>  dyn_cast_or_null(Y *Val) {<br class="">>    return (Val && isa<X>(Val)) ? cast<X>(Val) : nullptr;<br class="">><br class="">> Modified: llvm/trunk/unittests/Support/Casting.cpp<br class="">> URL:<span class="Apple-converted-space"> </span><a href="http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/Casting.cpp?rev=222644&r1=222643&r2=222644&view=diff" target="_blank" class="">http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/Casting.cpp?rev=222644&r1=222643&r2=222644&view=diff</a><br class="">> ==============================================================================<br class="">> --- llvm/trunk/unittests/Support/Casting.cpp (original)<br class="">> +++ llvm/trunk/unittests/Support/Casting.cpp Sun Nov 23 21:13:02 2014<br class="">> @@ -232,3 +232,99 @@ namespace TemporaryCast {<br class="">>  struct pod {};<br class="">>  IllegalCast *testIllegalCast() { return cast<foo>(pod()); }<br class="">>  }<br class="">> +<br class="">> +namespace {<br class="">> +namespace pointer_wrappers {<br class="">> +<br class="">> +struct Base {<br class="">> +  bool IsDerived;<br class="">> +  Base(bool IsDerived = false) : IsDerived(IsDerived) {}<br class="">> +};<br class="">> +<br class="">> +struct Derived : Base {<br class="">> +  Derived() : Base(true) {}<br class="">> +  static bool classof(const Base *B) { return B->IsDerived; }<br class="">> +};<br class="">> +<br class="">> +class PTy {<br class="">> +  Base *B;<br class="">> +public:<br class="">> +  PTy(Base *B) : B(B) {}<br class="">> +  LLVM_EXPLICIT operator bool() const { return get(); }<br class="">> +  Base *get() const { return B; }<br class="">> +};<br class="">> +<br class="">> +} // end namespace pointer_wrappers<br class="">> +} // end namespace<br class="">> +<br class="">> +namespace llvm {<br class="">> +<br class="">> +template <> struct simplify_type<pointer_wrappers::PTy> {<br class="">> +  typedef pointer_wrappers::Base *SimpleType;<br class="">> +  static SimpleType getSimplifiedValue(pointer_wrappers::PTy &P) {<br class="">> +    return P.get();<br class="">> +  }<br class="">> +};<br class="">> +template <> struct simplify_type<const pointer_wrappers::PTy> {<br class="">> +  typedef pointer_wrappers::Base *SimpleType;<br class="">> +  static SimpleType getSimplifiedValue(const pointer_wrappers::PTy &P) {<br class="">> +    return P.get();<br class="">> +  }<br class="">> +};<br class="">> +<br class="">> +} // end namespace llvm<br class="">> +<br class="">> +namespace {<br class="">> +namespace pointer_wrappers {<br class="">> +<br class="">> +// Some objects.<br class="">> +pointer_wrappers::Base B;<br class="">> +pointer_wrappers::Derived D;<br class="">> +<br class="">> +// Mutable "smart" pointers.<br class="">> +pointer_wrappers::PTy MN(nullptr);<br class="">> +pointer_wrappers::PTy MB(&B);<br class="">> +pointer_wrappers::PTy MD(&D);<br class="">> +<br class="">> +// Const "smart" pointers.<br class="">> +const pointer_wrappers::PTy CN(nullptr);<br class="">> +const pointer_wrappers::PTy CB(&B);<br class="">> +const pointer_wrappers::PTy CD(&D);<br class="">> +<br class="">> +TEST(CastingTest, smart_isa) {<br class="">> +  EXPECT_TRUE(!isa<pointer_wrappers::Derived>(MB));<br class="">> +  EXPECT_TRUE(!isa<pointer_wrappers::Derived>(CB));<br class="">> +  EXPECT_TRUE(isa<pointer_wrappers::Derived>(MD));<br class="">> +  EXPECT_TRUE(isa<pointer_wrappers::Derived>(CD));<br class="">> +}<br class="">> +<br class="">> +TEST(CastingTest, smart_cast) {<br class="">> +  EXPECT_TRUE(cast<pointer_wrappers::Derived>(MD) == &D);<br class="">> +  EXPECT_TRUE(cast<pointer_wrappers::Derived>(CD) == &D);<br class="">> +}<br class="">> +<br class="">> +TEST(CastingTest, smart_cast_or_null) {<br class="">> +  EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(MN) == nullptr);<br class="">> +  EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(CN) == nullptr);<br class="">> +  EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(MD) == &D);<br class="">> +  EXPECT_TRUE(cast_or_null<pointer_wrappers::Derived>(CD) == &D);<br class="">> +}<br class="">> +<br class="">> +TEST(CastingTest, smart_dyn_cast) {<br class="">> +  EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(MB) == nullptr);<br class="">> +  EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(CB) == nullptr);<br class="">> +  EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(MD) == &D);<br class="">> +  EXPECT_TRUE(dyn_cast<pointer_wrappers::Derived>(CD) == &D);<br class="">> +}<br class="">> +<br class="">> +TEST(CastingTest, smart_dyn_cast_or_null) {<br class="">> +  EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MN) == nullptr);<br class="">> +  EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CN) == nullptr);<br class="">> +  EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MB) == nullptr);<br class="">> +  EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CB) == nullptr);<br class="">> +  EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(MD) == &D);<br class="">> +  EXPECT_TRUE(dyn_cast_or_null<pointer_wrappers::Derived>(CD) == &D);<br class="">> +}<br class="">> +<br class="">> +} // end namespace pointer_wrappers<br class="">> +} // end namespace<br class="">><br class="">><br class="">> _______________________________________________<br class="">> llvm-commits mailing list<br class="">><span class="Apple-converted-space"> </span><a href="mailto:llvm-commits@cs.uiuc.edu" class="">llvm-commits@cs.uiuc.edu</a><br class="">><span class="Apple-converted-space"> </span><a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" target="_blank" class="">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a><br class="">><br class=""><br class=""></div></div></blockquote></div><br class=""></div></div><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">_______________________________________________</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class="">llvm-commits mailing list</span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class=""><a href="mailto:llvm-commits@cs.uiuc.edu" class="">llvm-commits@cs.uiuc.edu</a></span><br style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px;" class=""><span style="font-family: Helvetica; font-size: 12px; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: auto; text-align: start; text-indent: 0px; text-transform: none; white-space: normal; widows: auto; word-spacing: 0px; -webkit-text-stroke-width: 0px; float: none; display: inline !important;" class=""><a href="http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits" class="">http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits</a></span></div></blockquote></div><br class=""></body></html>