> On Jan 2, 2018, at 9:15 PM, Akira Hatanaka <ahatan...@apple.com> wrote:
> 
> 
> 
>> On Jan 2, 2018, at 4:56 PM, Richard Smith via cfe-commits 
>> <cfe-commits@lists.llvm.org <mailto:cfe-commits@lists.llvm.org>> wrote:
>> 
>> On 2 January 2018 at 15:33, John McCall via cfe-commits 
>> <cfe-commits@lists.llvm.org <mailto:cfe-commits@lists.llvm.org>> wrote:
>> 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.
>> 
>> The current definition in Itanium is:
>> 
>>   non-trivial for the purposes of calls <>
>>  <>
>> A type is considered non-trivial for the purposes of calls if:
>> 
>> it has a non-trivial copy constructor, move constructor, or destructor, or
>>  <>
>> 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.)
>> all of its copy and move constructors are deleted.
>>  <>
>> 
>> I'd suggest modifying this to:
>> 
>>      A type is considered non-trivial for the purposes of calls if:
>>              - if has a copy constructor, move constructor, or destructor 
>> which is non-trivial for the purposes of calls, or
>>              - all of its copy and move constructors are deleted and it does 
>> not have the trivial_abi attribute.
>> 
>>      A copy/move constructor is considered trivial for the purposes of calls 
>> if:
>>              - it is user-provided and
>>                      - the class has the trivial_abi attribute and
>>                      - a defaulted definition of the constructor would be 
>> trivial for the purposes of calls; or
>> 
>> 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:
>> 
>> struct [[clang::trivial_abi]] A {
>>   A(A && = make());
>> };
>> 
>> Here, A::A(A&&) cannot validly be defaulted. Is A trivial for the purpose of 
>> calls? Likewise:
>> 
>> struct [[clang::trivial_abi]] B {
>>   B(...);
>> };
>> struct C {
>>   volatile B b;
>> };
>> 
>> 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...)
>> 
>> 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.
>> 
>>              - it is not user-provided and
>>                      - the class has no virtual functions and no virtual 
>> base classes, and
>>                      - the constructor used to copy/move each direct base 
>> class subobject is trivial for the purposes of calls, and
>>                      - 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.
>> 
>>      A destructor is considered trivial for the purposes of calls if:
>>              - it is not user-provided or the class has the trivial_abi 
>> attribute, and
>>              - the destructor is not virtual, and
>>              - all of the direct base classes of its class have destructors 
>> that are trivial for the purposes of calls, and
>>              - 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.
>> 
>>      These definitions are intended to follow [class.copy.ctor]p11 and 
>> [class.dtor]p6 except for the special rules applicable to trivial_abi 
>> classes.
>> 
>> 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.
>> 
>> I think that's a reasonable rule, if we have a satisfactory notion of 
>> "defaulted definition".
>> 
>> 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.
>> 
>> Per the above examples, I don't think you can escape asking about triviality 
>> for an arbitrary constructor if you take this path.
>> 
>> 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.
>>  
> 
> 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:
> 
> struct [[clang::trivial_abi]] S0 {
>   // user-provided special functions declared here.
> };
> 
> struct S1 {
>   S0 f0;
> };
> 
> I thought we wanted containing classes (S1 in this case) to be trivial for 
> the purpose of calls too?

I would like that, yeah.

John.

> 
>> 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?
>> 
>> 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.
>> _______________________________________________
>> cfe-commits mailing list
>> cfe-commits@lists.llvm.org <mailto:cfe-commits@lists.llvm.org>
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits 
>> <http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits>

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to