> On Mar 3, 2015, at 1:12 PM, David Vandevoorde <[email protected]> wrote:
> At some point, the C++ standard changed to cause volatile nonstatic data 
> members to make a generated copy/move constructor nontrivial.
> 
> Unfortunately, that would change the parameter passing mechanism if we stuck 
> to letter of the ABI; see 3.1.1/1:
> 
> 1. In the special case where the parameter type has a non-trivial copy 
> constructor or destructor, the caller must allocate space
>    for a temporary copy, and pass the resulting copy by reference (below). 
> Specifically, ...
> 
> AFAICT, recent versions of GCC and Clang do implement the language aspects of 
> nontriviality of copy/move constructors in such cases (e.g., causing union 
> constructors to become deleted), but not this ABI aspect of it.  For example:
> 
>  typedef struct { int value; } TypeA;
>  typedef struct { TypeA volatile value; } TypeB;
>  typedef struct { TypeA value; } TypeC;
> 
>  int foo(TypeB p) { return p.value.value; }
>  int foo(TypeC p) { return p.value.value; }
> 
> Identical code is being generated for these two definitions of foo, even 
> though TypeB has a nontrivial copy constructor and TypeC has a trivial copy 
> constructor.

Hmm.  I’m somewhat surprised by this, at least from Clang; maybe it’s applying 
union restrictions via some other route.

> If that is right, should the 3.1.1/1 words above be edited to read:
> 
> 1. In the special case where the parameter type has a non-trivial copy 
> constructor (with the exception of a generated copy constructor that is
>    nontrivial only because one or more nonstatic data member are trivial) or 
> destructor, the caller must allocate space for a temporary copy,
>    and pass the resulting copy by reference (below).  Specifically, …

I agree that the intended semantics of the ABI here should not change and that 
we should modify the wording in the ABI to reflect the behavior we want.  Two 
points, though:

First, technically speaking, we need language cover for this.  Implementations 
are not allowed to introduce extra copies of types that aren’t trivially 
copyable.  (IIRC, the rule is narrower than “trivially copyable”, but I can’t 
seem to find the exact wording.)

Second, the wording change needs to be more precise: it should use well-defined 
terms from the standard, and it should cover the recursive cases.  We should 
introduce a new term to the glossary, maybe “non-trivially copyable for the 
purposes of calls”, and define it the way we want, probably something like:

  non-trivially copyable for the purposes of calls
    A type is considered to be non-trivially copyable for the purposes of calls 
if it is a class type and:
    - its destructor is non-trivial, or
    - all of its copy and move constructors are deleted, or
    - it has at least one copy or move constructor which is non-trivial for the 
purposes of calls.

  non-trivial for the purposes of calls
    A copy or move constructor is considered to be non-trivial for the purposes 
of calls if it is not deleted and:
    - it is user-provided or else
    - it is defaulted and either
      - the class has virtual functions or virtual bases or
      - the constructor chosen to initialize one of of subobjects is 
non-trivial for the purposes of calls.

I believe this is the currently-intended rule (albeit a rule that I haven’t yet 
standardized in the document).

John.
_______________________________________________
cxx-abi-dev mailing list
[email protected]
http://sourcerytools.com/cgi-bin/mailman/listinfo/cxx-abi-dev

Reply via email to