C++ Logo

std-proposals

Advanced search

[std-proposals] Relocation in C++

From: Sébastien Bini <sebastien.bini_at_[hidden]>
Date: Mon, 19 Dec 2022 12:32:53 +0100
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?

Regards,
Sébastien Bini

Received on 2022-12-19 11:33:05