[cxx-abi-dev] Transfer modes for parameters and return values
Gabriel Dos Reis
gdr at integrable-solutions.net
Mon Nov 26 05:33:40 UTC 2012
On Sun, Nov 25, 2012 at 11:03 PM, Richard Smith <richardsmith at google.com> wrote:
> On Fri, Nov 23, 2012 at 12:37 PM, Jason Merrill <jason at redhat.com> wrote:
>>
>> On 06/03/2009 04:59 PM, David Vandevoorde wrote:
>>>
>>> In 3.1.1 and 3.1.4, the ABI specifies that "by value" class type
>>> parameters and class type return values are passed via the address of a
>>> reference if the class type has
>>> (a) a nontrivial destructor, or
>>> (b) a nontrivial copy constructor.
>>>
>>> Should we now also add to that:
>>> (c) a (nontrivial) move constructor
>>> ?
>>
>>
>> This change doesn't seem to have been applied to the ABI, though G++
>> implements it. What are other compilers doing?
>
>
> I happened to be looking into this very recently... Clang implements the ABI
> as currently specified (along with the corresponding miscompiles). However,
> the proposed approach doesn't appear to remove all the miscompiles, for at
> least two reasons:
>
> 1) A parameter can be passed or a return value constructed by calling a
> constructor which is not a copy or move constructor. This can happen when a
> templated constructor is selected:
>
> struct A {
> A(const A&) = default; // suppress implicit move constructor, still
> trivial
> template<typename T> A(T &&); // chosen for copies from non-const objects
> and for moves, not a copy constructor nor a move constructor
> };
>
> 2) A parameter can be passed or a return value constructed by
> copy-list-initialization with no copy or move occurring:
>
> struct B {
> B(int);
> B(const B&) = delete; // deleted, but still trivial
> B(B&&) = delete; // likewise
> B *p = this;
> };
> B f(B x) {
> return { 1 };
> }
> void g() {
> f({2});
> }
>
> Both of these cases can lead to miscompiles with both g++ 4.7 and Clang
> trunk due to the ABI's rules. Both problems can also arise for classes with
> no user-declared special members.
>
> The second issue in particular seems unsolvable without a major ABI break or
> a core language change (we cannot pass types in registers if they have any
> non-trivial constructors).
The examples also suggest that in-class non-static data
member initialization is potentially ABI-breaking.
Whatever the changes are, we should not lose efficient
value transfer modes as we have today.
-- Gaby
More information about the cxx-abi-dev
mailing list