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:
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?

S├ębastien Bini