<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=""><div><blockquote type="cite" class=""><div class="">On Jan 8, 2018, at 10:57 AM, David Blaikie <<a href="mailto:dblaikie@gmail.com" class="">dblaikie@gmail.com</a>> wrote:</div><div class=""><div dir="ltr" class="">(just a side note: perhaps this conversation would've been more suited to cfe-dev? I sort of missed it because I only check commits once a week, unless I'm specifically cc'd on something. All good though :))</div></div></blockquote><div><br class=""></div><div>I suppose it's more design-and-development than just code review, so yes, perhaps cfe-dev would have been more appropriate. Regardless I should've made a point of CC'ing you, since you'd been part of the ongoing conversation. Apologies.</div><div><br class=""></div><div>John.</div></div><div><br class=""><blockquote type="cite" class=""><div class=""><br class=""><div class="gmail_quote"><div dir="ltr" class="">On Wed, Jan 3, 2018 at 4:06 PM Richard Smith via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" class="">cfe-commits@lists.llvm.org</a>> wrote:<br class=""></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote">On 3 January 2018 at 15:24, John McCall via cfe-commits <span dir="ltr" class=""><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" class="">cfe-commits@lists.llvm.org</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class="m_2498443779405359386h5"><blockquote type="cite" class=""><div class="">On Jan 3, 2018, at 5:53 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk" target="_blank" class="">richard@metafoo.co.uk</a>> wrote:</div><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote">On 3 January 2018 at 14:29, John McCall via cfe-commits <span dir="ltr" class=""><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" class="">cfe-commits@lists.llvm.org</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><br class=""><div class=""><div class=""><div class="m_2498443779405359386m_5847268543470718903gmail-h5"><blockquote type="cite" class=""><div class="">On Jan 3, 2018, at 5:12 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk" target="_blank" class="">richard@metafoo.co.uk</a>> wrote:</div><br class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote">On 2 January 2018 at 20:55, John McCall via cfe-commits <span dir="ltr" class=""><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" class="">cfe-commits@lists.llvm.org</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-h5"><blockquote type="cite" class=""><div class="">On Jan 2, 2018, at 10:43 PM, Richard Smith <<a href="mailto:richard@metafoo.co.uk" target="_blank" class="">richard@metafoo.co.uk</a>> wrote:</div><br class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429Apple-interchange-newline"><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote">On 2 January 2018 at 19:02, John McCall via cfe-commits <span dir="ltr" class=""><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" class="">cfe-commits@lists.llvm.org</a>></span> wrote:<br class=""><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><br class=""><div class=""><div class=""><div class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-h5"><blockquote type="cite" class=""><div class="">On Jan 2, 2018, at 9:15 PM, Akira Hatanaka <<a href="mailto:ahatanaka@apple.com" target="_blank" class="">ahatanaka@apple.com</a>> wrote:</div><br class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381Apple-interchange-newline"><div class=""><div style="word-wrap:break-word" class=""><br class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On Jan 2, 2018, at 4:56 PM, Richard Smith via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" class="">cfe-commits@lists.llvm.org</a>> wrote:</div><br class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381Apple-interchange-newline"><div class=""><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div class="gmail_extra"><div class="gmail_quote">On 2 January 2018 at 15:33, John McCall via cfe-commits<span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381Apple-converted-space"> </span><span dir="ltr" class=""><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" class="">cfe-commits@lists.llvm.org</a>></span><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381Apple-converted-space"> </span>wrote:<br class=""><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class="">Hey, Richard et al. Akira and I were talking about the right ABI rule for deciding can-pass-in-registers-ness for structs in the presence of trivial_abi, and I think I like Akira's approach but wanted to get your input.<div class=""><br class=""></div><div class="">The current definition in Itanium is:<div class=""><div class=""><br class=""></div><div class=""> <a name="m_2498443779405359386_m_5847268543470718903_m_-7936856144155171063_m_4082600853061718429_m_-7492911719749036381_m_4763064200015128419_non-trivial" style="font-family:-webkit-standard" class=""><i class="">non-trivial for the purposes of calls</i></a></div><dl class=""><dt style="font-family:-webkit-standard" class=""><a name="m_2498443779405359386_m_5847268543470718903_m_-7936856144155171063_m_4082600853061718429_m_-7492911719749036381_m_4763064200015128419_non-trivial" class=""></a></dt><dd style="font-family:-webkit-standard" class=""><a name="m_2498443779405359386_m_5847268543470718903_m_-7936856144155171063_m_4082600853061718429_m_-7492911719749036381_m_4763064200015128419_non-trivial" class=""><p class="">A type is considered non-trivial for the purposes of calls if:</p><ul class=""><li class="">it has a non-trivial copy constructor, move constructor, or destructor, or</li></ul></a></dd></dl></div></div></div></blockquote><div class="">I'm assuming we're implicitly excluding deleted functions here. (I'd prefer to make that explicit; this has been the source of a number of ABI mismatches.)</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class=""><dl class=""><dd style="font-family:-webkit-standard" class=""><a name="m_2498443779405359386_m_5847268543470718903_m_-7936856144155171063_m_4082600853061718429_m_-7492911719749036381_m_4763064200015128419_non-trivial" class=""><ul class=""><li class="">all of its copy and move constructors are deleted.</li></ul></a></dd></dl><div class=""><br class=""></div><div class="">I'd suggest modifying this to:</div></div></div><div class=""><br class=""></div><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381gmail-m_4763064200015128419Apple-tab-span" style="white-space:pre-wrap"> </span>A type is considered non-trivial for the purposes of calls if:</div><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381gmail-m_4763064200015128419Apple-tab-span" style="white-space:pre-wrap"> </span>- if has a copy constructor, move constructor, or destructor which is non-trivial for the purposes of calls, or</div><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381gmail-m_4763064200015128419Apple-tab-span" style="white-space:pre-wrap"> </span>- all of its copy and move constructors are deleted and it does not have the trivial_abi attribute.</div><div class=""><br class=""></div><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381gmail-m_4763064200015128419Apple-tab-span" style="white-space:pre-wrap"> </span>A copy/move constructor is considered trivial for the purposes of calls if:</div><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381gmail-m_4763064200015128419Apple-tab-span" style="white-space:pre-wrap"> </span>- it is user-provided and</div><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381gmail-m_4763064200015128419Apple-tab-span" style="white-space:pre-wrap"> </span>- the class has the trivial_abi attribute and</div><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381gmail-m_4763064200015128419Apple-tab-span" style="white-space:pre-wrap"> </span>- a defaulted definition of the constructor would be trivial for the purposes of calls; or</div></div></blockquote><div class=""><br class=""></div><div class="">We'd need to say what happens if the function in question cannot validly be defaulted for any of the reasons in [dcl.fct.def.default]. Do we try to infer whether it's a copy or move constructor, and use the rules for a defaulted copy or move constructor? Or do we just say that's never trivial for the purposes of calls? Or something else? Eg:</div><div class=""><br class=""></div><div class="">struct [[clang::trivial_abi]] A {</div><div class=""> A(A && = make());</div><div class="">};</div><div class=""><br class=""></div><div class="">Here, A::A(A&&) cannot validly be defaulted. Is A trivial for the purpose of calls? Likewise:</div><div class=""><br class=""></div><div class="">struct [[clang::trivial_abi]] B {</div><div class=""> B(...);</div><div class="">};</div><div class="">struct C {</div><div class=""> volatile B b;</div><div class="">};</div><div class=""><br class=""></div><div class="">Here, C's copy constructor calls B::B(...). Is C trivial for the purpose of calls? (OK, Clang crashes on that example today. But still...)</div><div class=""><br class=""></div><div class="">I'd be uncomfortable making the rules in [dcl.fct.def.default] part of the ABI; they seem to be changing relatively frequently. Perhaps we could say "if the function is a copy constructor ([class.copy.ctor]/1), then consider what an implicitly-declared defaulted copy constructor would do; if it's a move constructor ([class.copy.ctor]/2), then consider what an implicitly-declared defaulted move constructor would do; otherwise, it's not trivial for the purpose of calls". That'd mean A is trivial for the purpose of calls and C is not, which I think is probably the right answer.</div><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381gmail-m_4763064200015128419Apple-tab-span" style="white-space:pre-wrap"> </span>- it is not user-provided and</div><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381gmail-m_4763064200015128419Apple-tab-span" style="white-space:pre-wrap"> </span>- the class has no virtual functions and no virtual base classes, and</div><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381gmail-m_4763064200015128419Apple-tab-span" style="white-space:pre-wrap"> </span>- the constructor used to copy/move each direct base class subobject is trivial for the purposes of calls, and</div><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381gmail-m_4763064200015128419Apple-tab-span" style="white-space:pre-wrap"> </span>- for each non-static data member that is of class type (or array thereof), the constructor selected to copy/move that member is trivial for the purposes of calls.</div><div class=""><br class=""></div><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381gmail-m_4763064200015128419Apple-tab-span" style="white-space:pre-wrap"> </span>A destructor is considered trivial for the purposes of calls if:</div><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381gmail-m_4763064200015128419Apple-tab-span" style="white-space:pre-wrap"> </span>- it is not user-provided or the class has the trivial_abi attribute, and</div><div class=""><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381gmail-m_4763064200015128419Apple-tab-span" style="white-space:pre-wrap"> </span>- the destructor is not virtual, and</div><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381gmail-m_4763064200015128419Apple-tab-span" style="white-space:pre-wrap"> </span>- all of the direct base classes of its class have destructors that are trivial for the purposes of calls, and</div><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381gmail-m_4763064200015128419Apple-tab-span" style="white-space:pre-wrap"> </span>- for all of the non-static data members of its class that are of class type (or array thereof), each such class is trivial for the purposes of calls.</div></div><div class=""><br class=""></div><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-m_-7492911719749036381gmail-m_4763064200015128419Apple-tab-span" style="white-space:pre-wrap"> </span>These definitions are intended to follow [class.copy.ctor]p11 and [class.dtor]p6 except for the special rules applicable to trivial_abi classes.</div></div></blockquote><div class=""><br class=""></div><div class="">If I could rephrase: a *tor is considered trivial for for the purposes of calls if it is either defaulted or the class has the trivial_abi attribute, and the defaulted definition would satisfy the language rule for being trivial but with the word "trivial" replaced by "trivial for the purposes of calls". So only effect of the trivial_abi attribute is to "undo" the non-triviality implied by a user-provided *tor when computing triviality for the purpose of calls.</div><div class=""><br class=""></div><div class="">I think that's a reasonable rule, if we have a satisfactory notion of "defaulted definition".</div><div class=""><br class=""></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><div class="">I'm not sure about the "defaulted definition" rule for copy/move constructors in trivial_abi classes. The intent is to allow class temploids with trivial_abi that are instantiated to contain non-trivial classes to just silently become non-trivial. I was thinking at first that it would be nice to have a general rule that trivial_abi classes only contain trivial_abi subobjects, but unfortunately that's not consistent with the standard triviality rule in some silly corner cases: a trivially-copyable class can have a non-trivially-copyable subobject if it happens to copy that subobject with a trivial copy constructor. I couldn't think of a better way of capturing this than the "defaulted definition" rule. I considered using the actual initializers used by the constructor, but that would introduce a lot of new complexity: suddenly we'd be asking about triviality for an arbitrary constructor, and copy/move elision make the question somewhat ambiguous anyway.</div></div></blockquote><div class=""><br class=""></div><div class="">Per the above examples, I don't think you can escape asking about triviality for an arbitrary constructor if you take this path.</div><div class=""><br class=""></div><div class="">Another option, similar to your general rule, would be to say that a type is considered trivial for the purpose of calls if either: (1) it is trivial for the purpose of calls under the current Itanium ABI rule, or (2) it has the trivial_abi attribute and all members and base classes have types that are trivial for the purpose of calls. That would sidestep the "defaulted definition" complexity entirely, and while it differs from the way that the language computes triviality normally, it doesn't seem fundamentally unreasonable: when we're thinking about triviality for the purpose of calls, there's notionally a call to the trivial copy/move ctor being elided, not a call to an arbitrary ctor selected by overload resolution, and we'd just be pushing that effect from the class itself to its subobjects with this attribute.</div><div class=""> </div></div></div></div></div></blockquote><div class=""><br class=""></div><div class="">It sounds like a class containing a member that has a type annotated with “trivial_abi” would not necessarily be considered trivial for the purpose of calls according to rule (2)? For example, S1 would not be trivial for the purpose of calls because it isn’t annotated with “trivial_abi” in the code below:</div><div class=""><br class=""></div><div class="">struct [[clang::trivial_abi]] S0 {</div><div class=""> // user-provided special functions declared here.</div><div class="">};</div><div class=""><br class=""></div><div class="">struct S1 {</div><div class=""> S0 f0;</div><div class="">};</div><div class=""><br class=""></div>I thought we wanted containing classes (S1 in this case) to be trivial for the purpose of calls too?</div></div></div></blockquote><div class=""><br class=""></div></div></div>I would like that, yeah.</div></div></blockquote><div class=""><br class=""></div><div class="">OK, I think that's fair. Then we probably need the more complex rule. Which I think means we're at something equivalent to:</div><div class=""><br class=""></div><div class=""><div class=""><span style="white-space:pre-wrap" class=""> </span>A type is considered non-trivial for the purposes of calls if:</div><div class=""><span style="white-space:pre-wrap" class=""> </span>- if has a copy constructor, move constructor, or destructor <b class="">that is not deleted and</b> is non-trivial for the purposes of calls, or</div><div class=""><span style="white-space:pre-wrap" class=""> </span>- all of its copy and move constructors are deleted and it does not have the trivial_abi attribute.</div></div></div></div></div></div></blockquote></div></div></div></div></blockquote><div class="">Hold on... this final "and it does not have the trivial_abi attribute" looks wrong to me; it seems to break the "do what I mean"ness of the attribute. Consider:<br class=""></div><div class=""><br class=""></div><div class="">template<typename T, typename U> struct [[clang::trivial_abi]] pair { ... };</div><div class=""><br class=""></div><div class="">std::pair<ContainsPointerToSelf, int> f(); // returned indirect</div><div class="">std::pair<ContainsPointerToSelf, NonCopyable> g(); // returned in registers because all copy/move ctors deleted</div><div class=""><br class=""></div><div class="">That seems like a bug. Can we just strike that addition, or does one of your intended use cases need it?</div></div></div></div></div></blockquote><div class=""><br class=""></div></div></div>It was a last-minute addition that seemed like a good idea, but I was just thinking about all the copy/move ctors being explicitly deleted on the class, not any of the inheritance cases. I agree with striking it.</div><div class=""><br class=""></div><div class="">The only use cases we really have in mind are</div><div class=""> - simple resource-owning classes like smart pointers, which would adopt the attribute, and</div><div class=""> - classes with defaulted copy/destruction semantics, which should propagate triviality if possible.</div><div class=""><br class=""></div><div class="">I just think we need to be prepared to make the rule more general than that.</div><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-"><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-h5"><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><div class=""><span style="white-space:pre-wrap" class=""> </span>A copy/move constructor is considered trivial for the purposes of calls if:<br class=""></div><div class=""><span style="white-space:pre-wrap" class=""> </span>- it is user-provided and</div><div class=""><span style="white-space:pre-wrap" class=""> </span>- the class has the trivial_abi attribute and</div><div class=""><span style="white-space:pre-wrap" class=""> </span>- <b class="">a defaulted definition of a constructor with the signature of the implicit copy/move constructor for the class would be trivial for the purposes of calls</b>; or</div></div></div></div></div></div></blockquote></div></div></div></div></blockquote><div class="">One other concern here: what if the defaulted definition would be deleted? I think in that case the constructor we're considering should also be treated as if it were deleted. And that applies recursively: if the implicit copy/move constructor would itself have been deleted, we want to treat the original member of the type we're checking as being deleted. And likewise, if a defaulted copy/move constructor invokes a copy/move constructor of a trivial_abi class, and a defaulted copy/move constructor for that class would have been deleted, we want to act as if the original defaulted copy/move constructor was deleted. That seems awkward to specify in the fashion we've been using until now, since the result of a triviality calculation is now "deleted", "non-trivial", or "trivial", and deletedness can change in either direction as a result of the attribute.</div></div></div></div></div></blockquote><div class=""><br class=""></div></span>Ugh. I feel like this problem is mostly a further indictment of the idea of basing this on what a defaulted definition would look like.</div><div class=""><br class=""></div><div class="">We could just base it on the overall trivial-for-calls-ness of the subobject types. It's a very different rule from the standard triviality rule, but it's okay to differ here because this *only* affects special members of classes with the attribute.</div></div></blockquote><div class=""><br class=""></div><div class="">I like this idea a lot. Here's a concrete suggestion:<br class=""></div><div class=""><br class=""></div><div class="">"""</div><div class="">A type has a <i class="">triviality override</i> if it has the trivial_abi attribute, and it has no virtual functions nor virtual base classes, and every subobject is trivial for the purposes of calls. The attribute is ill-formed if applied to a non-template class that does not meet these criteria; the attribute is ill-formed, no diagnostic required, if applied to a templated class and no instantiation of that class can meet these criteria.</div></div></div></div></div></blockquote><div class=""><br class=""></div></div></div>David B. and I were talking about whether this should be a required diagnostic even in the template case, and I think we settled on "no" because it could interfere with portability. Imagine that std::unique_ptr were made trivial_abi in some STL; classes containing a std::unique_ptr could only be trivial_abi on that target. On the other hand, I get that it's nice to have a static guarantee that the attribute meant something.</div><div class=""><br class=""></div><div class="">Maybe we could make it ill-formed, no diagnostic required, if the attribute is present but the class can never have a triviality override (for any instantiation, if a template). That would give us wide leeway to complain about putting it on a class with a direct virtual base, or when there's a non-trivial subobject whose type is defined in the "same library", or if specifically requested to.</div><div class=""><br class=""></div><div class="">Besides, we're not actually promising to pass it "directly". It's a totally legal implementation (right now) to just ignore the attribute. That wouldn't be ABI-compatible with compilers that implement it, of course, but not everyone cares about that.</div></div></blockquote><div class=""><br class=""></div></div></div></div><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">I'd be OK with, say, downgrading this from an error to a warning, or making it an error-with-a-warning-flag. But even in the case of a unique_ptr member, I think a user would typically want to be told that the attribute didn't have the effect they're looking for: that's exactly the case where I would expect people to try to "override" the triviality of a subobject using the attribute, so I think the diagnostic should be enabled by default.</div><div class=""><br class=""></div><div class="">I suppose the "ill-formed, no diagnostic required" formulation at least gives other implementers of the attribute a hint that they should also consider producing a diagnostic.</div></div></div></div><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><span class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">A type is trivial for the purposes of calls if:</div><div class=""> - it has a triviality override, or</div><div class=""> - it is trivial for the purposes of calls as specified in the Itanium C++ ABI, or would be so if all direct or indirect construction and destruction of types with a triviality override were ignored when computing the triviality (but not deletedness) of functions</div><div class="">"""<br class=""></div></div></div></div></div></blockquote><div class=""><br class=""></div></span>I like this wording, since we don't have to actually repeat anything from the standard.</div><div class=""><span class=""><br class=""><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">So we would still compute both a "trivial" and a "trivial for the purposes of calls" flag for defaulted copy constructors, move constructors, and destructors, but we'd only do the overload resolution and deletedness analysis once; trivial would always imply trivial for the purposes of calls, and the converse only fails when there is a subobject whose type has a triviality override.</div></div></div></div></blockquote><div class=""><br class=""></div></span>Right.</div><span class="m_2498443779405359386HOEnZb"><font color="#888888" class=""><div class=""><br class=""></div><div class="">John.</div></font></span><div class=""><div class="m_2498443779405359386h5"><div class=""><br class=""></div><div class=""><blockquote type="cite" class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">Put another way, we'd have four levels of triviality for special members: deleted, non-trivial, trivial for purposes of calls, and trivial. The triviality of a deleted member is "deleted". The triviality of any trivial_abi member is "trivial for purposes of calls". The triviality of any other user-provided member is "non-trivial". And the triviality of a non-user-provided non-deleted member is "deleted" if any subobject call is ill-formed, otherwise "non-trivial" for the special cases involving virtual bases and virtual functions, otherwise the mimimum of that value over all subobject calls. And a type is trivial for the purposes of calls unless any copy ctor, move ctor or dtor is "non-trivial" or all copy and move constructors are "deleted".</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-"><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">Here's a terse summary of the rule I'm considering:</div><div class=""><br class=""></div><div class="">"""</div><div class="">For the determination of triviality for the purposes of calls, a modified form of the program is considered. In this modified form, each copy or move constructor or destructor of a class with the trivial_abi attribute is replaced by a defaulted copy or move constructor or destructor (with the signature of an implicit such declaration), and calls to the former are transformed into calls to the latter within the implicit definitions of defaulted special member functions. A function is deleted for the purposes of calls in the original program if the corresponding function is deleted in the modified program, and is otherwise trivial for the purposes of calls in the original program if the corresponding function is trivial in the modified program.</div><div class=""><br class=""></div><div class="">A type is considered non-trivial for the purposes of calls if:</div><div class=""><div class=""><span style="white-space:pre-wrap" class=""> </span>- if has a copy constructor, move constructor, or destructor that is non-deleted and non-trivial for the purposes of calls, or</div><div class=""><span style="white-space:pre-wrap" class=""> </span>- all of its copy and move constructors are deleted for purposes of calls.</div></div></div></div></div></div></blockquote><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class="">"""</div></div></div></div></div></blockquote><div class=""><br class=""></div></span>Yikes. I feel like I would have no ability to explain this rule to a user.</div><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-"><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><div class=""><div class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-h5"><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><div class=""><span style="white-space:pre-wrap" class=""> </span>- it is not user-provided and</div><div class=""><span style="white-space:pre-wrap" class=""> </span>- the class has no virtual functions and no virtual base classes, and</div><div class=""><span style="white-space:pre-wrap" class=""> </span>- the constructor used to copy/move each direct base class subobject is trivial for the purposes of calls, and</div><div class=""><span style="white-space:pre-wrap" class=""> </span>- for each non-static data member that is of class type (or array thereof), the constructor selected to copy/move that member is trivial for the purposes of calls.</div><div class=""><span style="white-space:pre-wrap" class=""> </span><b class="">A constructor that is neither a copy constructor nor a move constructor is considered non-trivial for the purposes of calls</b>.</div></div></div></div></div></div></blockquote><div class=""><br class=""></div></div></div>This clause is there to handle constructors that are copy/move constructors only because of defaulted arguments? I wonder if this is necessary; I think the allocator-like use cases would prefer that we just ignore the non-initial arguments, wouldn't they?</div></div></blockquote><div class=""><br class=""></div><div class="">This doesn't affect the default argument case: if a constructor has a first parameter of type T / cv T& / cv T&&, and all further parameters (if any) have default arguments, it is still a copy or move constructor. Rather, we reach this clause in any case where "the constructor used/selected to copy/move [...]" has some other first parameter type or is X::X(...); such a constructor is only selected when there is no viable copy/move constructor.</div></div></div></div></div></blockquote><div class=""><br class=""></div></span>Oh, which can happen even for non-user-provided constructors because it's just the ordinary overload rules, of course.</div><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-"><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><div class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-"><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""><div class=""><span style="white-space:pre-wrap" class=""> </span>A destructor is considered trivial for the purposes of calls if:</div><div class=""><span style="white-space:pre-wrap" class=""> </span>- it is not user-provided or the class has the trivial_abi attribute, and</div><div class=""><span style="white-space:pre-wrap" class=""> </span>- the destructor is not virtual, and</div><div class=""><span style="white-space:pre-wrap" class=""> </span>- all of the direct base classes of its class have destructors that are trivial for the purposes of calls, and</div><div class=""><span style="white-space:pre-wrap" class=""> </span>- for all of the non-static data members of its class that are of class type (or array thereof), each such class is trivial for the purposes of calls.</div></div><div class=""><br class=""></div><div class="">Bolded phrases are changed from John's initial email.</div></div></div></div></div></blockquote><div class=""><br class=""></div></span>Thank you for the revision; this is much improved.</div></div></blockquote><div class=""><br class=""></div><div class="">I'm concerned about the level of complexity we've discovered to be necessary here, and in particular the necessity of having a side-notion of "trivial for the purpose of calls" for all copy/move ctors and dtors, even in classes that do not directly use the trivial_abi attribute. But I suppose that's fundamental if we want to pass struct S1 (above) directly. I'd like a simpler rule, but I'm not convinced there is one.</div></div></div></div></div></blockquote><div class=""><br class=""></div></span>Well, I think the adjustment I suggest above would cap the complexity a bit; at least we would need these speculative investigation into defaulted definitions that don't actually exist. But we'd still need to track the new kind of triviality for each ctor/dtor.</div><span class="m_2498443779405359386m_5847268543470718903gmail-HOEnZb"><font color="#888888" class=""><div class=""><br class=""></div><div class="">John.</div></font></span><span class="m_2498443779405359386m_5847268543470718903gmail-"><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-HOEnZb"><font color="#888888" class=""><div class="">John.</div></font></span><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-"><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" class=""><div class="gmail_extra"><div class="gmail_quote"><div class=""> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-HOEnZb"><font color="#888888" class=""><div class="">John.</div></font></span><span class="m_2498443779405359386m_5847268543470718903gmail-m_-7936856144155171063gmail-m_4082600853061718429gmail-"><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div style="word-wrap:break-word" class=""><div class=""><br class=""><blockquote type="cite" class=""><div class=""><div dir="ltr" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div style="word-wrap:break-word" class=""><div class="">I'm also not sure about the right rules about virtual methods. Should we allow polymorphic classes to be made trivial by application of the attribute?</div></div></blockquote><div class=""><br class=""></div><div class="">I think that it probably doesn't make much sense to pass dynamic classes indirectly unless we can avoid passing the vptr; otherwise I'd expect we'd use too many registers for it to be worthwhile. Perhaps as a compromise, we could make the attribute ill-formed if used on a class definition that introduces any virtual bases or explicitly declares any member functions as 'virtual'. That gives us the room to make this decision later if we find we want to.</div></div></div></div><span style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline" class="">_______________________________________________</span><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><span style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px;float:none;display:inline" class="">cfe-commits mailing list</span><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><a href="mailto:cfe-commits@lists.llvm.org" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" target="_blank" class="">cfe-commits@lists.llvm.org</a><br style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" class=""><a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" style="font-family:Helvetica;font-size:12px;font-style:normal;font-variant-caps:normal;font-weight:normal;letter-spacing:normal;text-align:start;text-indent:0px;text-transform:none;white-space:normal;word-spacing:0px" target="_blank" class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></span></div><br class="">_______________________________________________<br class="">
cfe-commits mailing list<br class="">
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" class="">cfe-commits@lists.llvm.org</a><br class="">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank" class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br class="">
<br class=""></blockquote></div><br class=""></div></div>
</div></blockquote></div><br class=""></span></div><br class="">_______________________________________________<br class="">
cfe-commits mailing list<br class="">
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" class="">cfe-commits@lists.llvm.org</a><br class="">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank" class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br class="">
<br class=""></blockquote></div><br class=""></div></div>
</div></blockquote></div><br class=""></span></div><br class="">_______________________________________________<br class="">
cfe-commits mailing list<br class="">
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" class="">cfe-commits@lists.llvm.org</a><br class="">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank" class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br class="">
<br class=""></blockquote></div><br class=""></div></div>
</blockquote></div><br class=""></div></div></div><br class="">_______________________________________________<br class="">
cfe-commits mailing list<br class="">
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" class="">cfe-commits@lists.llvm.org</a><br class="">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank" class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br class="">
<br class=""></blockquote></div></div></div>
_______________________________________________<br class="">
cfe-commits mailing list<br class="">
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank" class="">cfe-commits@lists.llvm.org</a><br class="">
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank" class="">http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br class="">
</blockquote></div>
</div></blockquote></div><br class=""></body></html>