[cxx-abi-dev] Volatile nonstatic data members

David Vandevoorde daveed at edg.com
Fri Mar 6 21:49:56 UTC 2015


> On Mar 6, 2015, at 4:32 PM, Richard Smith <richardsmith at googlers.com> wrote:
> 
> On 6 March 2015 at 12:40, David Vandevoorde <daveed at edg.com <mailto:daveed at edg.com>> wrote:
>> On Mar 6, 2015, at 2:52 PM, Richard Smith <richardsmith at googlers.com <mailto:richardsmith at googlers.com>> wrote:
>> 
>> On 6 March 2015 at 09:35, David Vandevoorde <daveed at edg.com <mailto:daveed at edg.com>> wrote:
>> At some point, the C++ standard changed to cause volatile nonstatic data members to make a generated copy/move constructor nontrivial.
>> 
>> To save anyone else looking, this was http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#496 <http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#496>
>> 
>> 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.
>> 
>> Clang does not implement this (http://clang.llvm.org/cxx_dr_status.html#496 <http://clang.llvm.org/cxx_dr_status.html#496>); I'm not sure about GCC trunk. We still accept
>> 
>>   struct A { volatile int v; };
>>   union U { A a; };
>>   extern U u1;
>>   U u2(u1);
>> 
>> (for example).
> 
> 
> Ah yes, I misinterpreted Clang/GCC behavior because I was using a volatile _class_ type.  Even there, though (as illustrated by the example below), there is an ABI breakage lurking, I think.
> 
> 
>> 
>> 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.
>> 
>> 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, ...
>> 
>> ?
>> 
>> No strong preference here, but...
>> 
>> Do you have any feeling about how much code would be broken if we don't do this? If we were starting from a clean sheet, I think I'd prefer the rule as it is (volatile subobjects prevent a class from being passed in registers), so if this doesn't actually happen in practice, I'd prefer for us to leave the ABI alone.
> 
> I don’t have a strong sense, but we have one customer that ran into this (and that’s only for the class type case, we don’t implement 496 either yet).
> 
> And it’s also a C-ABI compatibility issue…
> 
> The proposed ABI change would be non-conforming even under the proposed resolution of http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1590 <http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1590>, because we are not permitted to make additional technical copies of a parameter unless it has a trivial copy/move constructor. Consider:
> 
>   struct A { A *volatile p = this; };
>   void f(A a) { assert(&a == a.p); }
>   int main() { f({}); }
> 

Ow!

> We are not permitted to fabricate an extra copy of the A object here because its constructor is non-trivial. Thus the assertion must not fail, and we cannot pass the object in registers.
> 
> I see three ways out: extend 1590 to also include this "volatile members don't count" clause, or allow a constructor to make an additional copy of a parameter object in all cases of copy-initialization, or revert the resolution of 496.
> 
> Reverting 496 seems most palatable to me right now, but in any case this seems like something for CWG to decide rather than something for us to work around in the ABI.


Agreed.

	Daveed



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://sourcerytools.com/pipermail/cxx-abi-dev/attachments/20150306/5c97adca/attachment-0001.html>


More information about the cxx-abi-dev mailing list