C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Relocation in C++

From: Ville Voutilainen <ville.voutilainen_at_[hidden]>
Date: Mon, 19 Dec 2022 14:11:42 +0200
On Mon, 19 Dec 2022 at 13:33, Sébastien Bini via Std-Proposals
<std-proposals_at_[hidden]> wrote:
>
> Hello all,
>
> This post is mainly for the brave ones that followed the discussion about relocation with the putative reloc keyword. I am in the process of writing the proposal, and I find that the ABI stability section is the weakest point.
>
> For everyone to follow, here is a brief recap: we want to provide full relocation support in the language. relocation happens through its own constructor, which destructively steals the resources of the source object. The destructor on the source object is then never called.
>
> Problem is enabling relocation from function parameters passed by value. For this to work, we need the ABI of the function to be callee-destroy (the function itself is responsible for destroying its parameters). Otherwise if the ABI were caller-destroy, then the function could not avoid the call to the destructor on its input parameters, should some be passed to a relocation constructor.
>
> The ABI break is planned to be opt-in and opt-out. Declaring a relocation constructor on a class-type will force each function that takes that class as value parameter to be callee-destroy (potential ABI break, depending on compilers).
>
> class T { T(T); /* reloc ctor declaration */ };
> void foo(T); //< now forcibly callee-destroy
>
> It can also be opted-out, by adding a new implementation-defined attribute on the class definition, so that despite the fact that a relocation constructor may be declared, the ABI of functions are not impacted:
>
> class [[no_parameter_reloc]] T { T(T); /* reloc ctor declaration */ };
> void foo(T); //< callee-destroy constraint no longer applies
>
> This works well for many cases. Library vendors migrating to this proposal can simply carefully pick which classes they choose to declare a relocation ctor in, and then also add the opt-out attribute in the class definition if they wish to provide ABI stability.
>
> The problem I foresee is that this has terrible composability. If I declare a relocation ctor to my MyString class-type, and opt-out of the ABI break, what happens to all the functions where std::pair<MyString, int> is passed by value? We have many good reasons not to add the opt-out parameter to std::pair. Hence, with the given rules, that would mean that there is no way of ensuring ABI stability on such functions.
>
> I'm thinking of tweaking the rules a little bit. First, we keep the opt-out attribute on the class definition, but it is no longer implementation-defined. Second, the opt-out attribute also provides an (auto) syntax: class [[no_parameter_reloc(auto)]] that will inspect the class subobjects (direct or virtual bases and non-static data-members) and decide accordingly. Here are the deduction rules:
>
> If one of the class subobjects hasn't opted-out, and (maybe implicitly) declares a relocation constructor and is not trivial (trivial implies destructor is a no-op) then the class opts-in for the ABI break ;
> Otherwise if one of the class subobjects opted-out, and that it (maybe implicitly) declares a relocation constructor, and it is not trivial, then the class opts-out of the ABI break ;
> Otherwise the class opts-in by default.
>
> With the updated rules, if std::pair has the [[no_parameter_reloc(auto)]] attribute, then std::pair<MyString,int> opts-out, while std::pair<MyString,UserDefinedOptInType> opts-in.
>
> I am also thinking of allowing a function attribute to opt-out on function level for tricky cases.
>
> Anyone have some thoughts on the matter?

I don't get it. If we have a new kind of constructor, there is no ABI
_break_, since it's just a new constructor. So why aren't you adding
such
a new constructor for pair?

Since this is a semantic facility with semantic guarantees, using
attributes here seems like the wrong thing to do.

Received on 2022-12-19 12:11:55