<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></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 Nov 14, 2017, at 2:12 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk" class="">richard@metafoo.co.uk</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div dir="auto" class=""><div class=""><div class="gmail_extra"><div class="gmail_quote">On 13 Nov 2017 23:46, "John McCall via cfe-dev" <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank" class="">cfe-dev@lists.llvm.org</a>> wrote:<br type="attribution" class=""><blockquote class="m_-2815048909514534594quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="m_-2815048909514534594elided-text"><br class="">
> On Nov 13, 2017, at 8:37 PM, Akira Hatanaka via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org" target="_blank" class="">cfe-dev@lists.llvm.org</a>> wrote:<br class="">
><br class="">
> I'd like to propose an attribute that can be used to instruct clang to pass and return non-trivial C++ structs directly when it's possible to do so. Any feedback would be greatly appreciated.<br class="">
><br class="">
> ### Motivation for the attribute<br class="">
> We have a user who wants to adopt smart pointers to manage lifetime of objects. The current code looks like this:<br class="">
><br class="">
> struct Object {<br class="">
>   ...<br class="">
>   void release();<br class="">
> };<br class="">
><br class="">
> Object *getObject();<br class="">
><br class="">
> void test() {<br class="">
>   Object *t = getObject();<br class="">
>   ...<br class="">
>   // Users have to call 'release' manually.<br class="">
>   t->release();<br class="">
> }<br class="">
><br class="">
> The smart pointer the user plans to use is a thin C++ template wrapper whose only data member is the raw pointer that points to the object being managed:<br class="">
><br class="">
> template<class T><br class="">
> struct SmartPtr {<br class="">
>   T *ptr;<br class="">
>   SmartPtr(T *p);<br class="">
>   SmartPtr(const SmartPtr &);<br class="">
>   ~SmartPtr() {<br class="">
>     ptr->release();<br class="">
>   }<br class="">
> };<br class="">
><br class="">
> SmartPtr<Object> getObject();<br class="">
><br class="">
> void test() {<br class="">
>   SmartPtr<Object> t = getObject();<br class="">
>   ...<br class="">
>   // The object 't' points to is automatically released when ~SmartPtr is called.<br class="">
> }<br class="">
><br class="">
> The problem with the code above is that, since SmartPtr is considered to be non-trivial for the purpose of calls according to the C++ ABI, function getObject now returns its return value indirectly via an implicit pointer parameter passed to the function even though the struct has the same in-memory representation as a raw pointer. This breaks ABI compatibility for users who use getObject in their code but cannot rewrite their code to use the new API.<br class="">
><br class="">
> ### The proposed attribute<br class="">
> The attribute (tentatively named "trivial_abi") will be used to annotate C++ structs and instruct clang to pass and return the struct indirectly when it's possible to do so. This means that the presence of a non-trivial destructor or copy constructor will not force the struct to be passed or returned indirectly, but it doesn't guarantee the struct will always be passed or returned directly (the struct have to be passed indirectly if its size is too large or there is another data member that is non-trivial, for example).<br class="">
<br class="">
</div>To clarify, the expected behavior here is that the type would get passed using the C ABI for the underlying struct type instead of being forced to use an indirect ABI.  There isn't a direct guarantee that the ABI will match that of a pointer if the struct happens to only contain a pointer.  Our internal client is satisfied with that.<br class="">
<br class="">
I guess this attribute would be illegal on a class with virtual methods or virtual bases?  That's probably simplest for now.<br class="">
<br class="">
In semantic terms, this attribute is a guarantee that the type can be destructively moved with memcpy, combined with an assertion that there is no code in the program that isn't aware of that (and therefore that it's acceptable to rely on that in the ABI).  By a "destructively move" I mean, effectively, a move-initialization immediately followed by the destruction of the source.<br class=""></blockquote></div></div></div><div dir="auto" class=""><br class=""></div><div dir="auto" class="">Even when not initializing a function parameter / return object, I assume? (The attribute name seems a little too specific for such cases, but it's probably fine for it to describe only the primary intended use.)</div></div></div></blockquote><div><br class=""></div>Yes, I think it would enable such an optimization.  Of course, if we were pursuing that optimization in general, I think we'd want to also add a non-ABI-breaking attribute that could be applied to basically everything in the STL.</div><div><br class=""><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div dir="auto" class="">I think you also need to extend this rule to cover the attributed types: <a href="http://eel.is/c++draft/special#class.temporary-3" class="">http://eel.is/c++draft/special#class.temporary-3</a></div></div></div></blockquote><div><br class=""></div>Agreed.  We may need to insert an implicit copy of the value to perform the call, and since that can be detectable (by ill-advised code), we need a call-out that says that's legal.</div><div><br class=""></div><div>I don't think we'd thought about documenting this (additionally) in terms of precise edits to the standard, but that's not a bad idea.</div><div><br class=""><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div dir="auto" class="">Would an aggregate containing only such types and trivial types inherit the same property? (More accurately, a type whose copy or move ctor and dtor would be trivial if not for calling corresponding members on such a type.)</div></div></div></blockquote><div><br class=""></div><div>Yes.  I would phrase it the other way: being required to be passed indirectly is a property that's inherited by containing aggregates.</div><div><br class=""></div><div>John.</div><br class=""><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div dir="auto" class="">Or is that a bridge too far for what you're trying to achieve? Once we implement this, will it be considered part of our immutable ABI surface, or will we have time to iterate on such design questions?</div></div></div></blockquote></div><div><br class=""><blockquote type="cite" class=""><div class=""><div dir="auto" class=""><div dir="auto" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="m_-2815048909514534594quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
The destruction convention for arguments of trivial_abi types would be that the callee is responsible for destroying the object (regardless of how it is passed under the C ABI).  This allows the callee to just initialize the parameter variable with the passed representation and then destroy that on exit.  If the caller were responsible for destroying the object, we would need to implicitly copy in order to protect against the callee changing the value of its parameter variable before returning.  Destroying a parameter at callee exit is not the Itanium rule, but it is the MSVC rule, and it is permitted by [expr.call]p4.  We will arguably be required to violate the rule that the parameter's destruction "occurs within the context of the calling function", but I believe we can implement this to at least not violate the rule that the parameter is destroyed outside of the scope of a function-try-block in the callee.<br class=""></blockquote></div></div></div><div dir="auto" class=""><br class=""></div><div dir="auto" class="">Seems very reasonable to me. I'd love for libc++ to start using this for unique_ptr in its unstable ABI mode.</div><div dir="auto" class=""><br class=""></div><div dir="auto" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="m_-2815048909514534594quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
John.<br class="">
<div class="m_-2815048909514534594quoted-text"><br class="">
><br class="">
> Besides avoiding ABI breakage, the attribute can potentially improve performance since the extra load instruction to get the value of the pointer isn't needed when the struct is passed or returned directly.<br class="">
</div>> ______________________________<wbr class="">_________________<br class="">
> cfe-dev mailing list<br class="">
> <a href="mailto:cfe-dev@lists.llvm.org" target="_blank" class="">cfe-dev@lists.llvm.org</a><br class="">
> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank" class="">http://lists.llvm.org/cgi-bin/<wbr class="">mailman/listinfo/cfe-dev</a><br class="">
<br class="">
______________________________<wbr class="">_________________<br class="">
cfe-dev mailing list<br class="">
<a href="mailto:cfe-dev@lists.llvm.org" target="_blank" class="">cfe-dev@lists.llvm.org</a><br class="">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-dev" rel="noreferrer" target="_blank" class="">http://lists.llvm.org/cgi-bin/<wbr class="">mailman/listinfo/cfe-dev</a><br class="">
</blockquote></div><br class=""></div></div></div>
</div></blockquote></div><br class=""></body></html>