[cxx-abi-dev] Volatile nonstatic data members

John McCall rjmccall at apple.com
Mon Feb 29 23:28:57 UTC 2016


> On Mar 3, 2015, at 1:12 PM, David Vandevoorde <daveed at vandevoorde.com> 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.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://sourcerytools.com/pipermail/cxx-abi-dev/attachments/20160229/79a098f7/attachment.html>


More information about the cxx-abi-dev mailing list