C++ Logo

std-proposals

Advanced search

Re: [std-proposals] consteval int relocatability

From: Lénárd Szolnoki <cpp_at_[hidden]>
Date: Wed, 12 Nov 2025 09:50:31 +0000
On 12/11/2025 07:45, Oliver Hunt wrote:
>
>
>> On Nov 11, 2025, at 11:04 PM, Lénárd Szolnoki <cpp_at_[hidden]> wrote:
>>
>>
>>
>> On 11 November 2025 23:33:42 GMT, Oliver Hunt via Std-Proposals <std-
>> proposals_at_[hidden] <mailto:std-proposals_at_[hidden]>> wrote:
>>>
>>>
>>>> On Nov 11, 2025, at 6:34 AM, Frederick Virchanza Gotham via Std-Proposals <std-
>>>> proposals_at_[hidden]> wrote:
>>>>
>>>> On Mon, Nov 10, 2025 at 10:08 AM Oliver Hunt wrote:
>>>>>
>>>>> Re: funky - it would actually just be impossible, it is not defined
>>>>> in a context where C++ exists, and it has no support for the C++
>>>>> type system, hence it being invalid to use it over most C++ types.
>>>>
>>>>
>>>> You’re absolutely right about `qsort` using ` void* ` and not having access
>>>> to the C++ type system – I’d simply overlooked that.
>>>>
>>>> I have a question for you Oliver about `std::restart_lifetime` in the presence
>>>> of arm64e pointer authentication.
>>>>
>>>> For the sake of argument, let's suppose that the compiler has a builtin
>>>> function as follows:
>>>>
>>>> void const * __builtin_get_address_vtable(T);
>>>>
>>>> which, for a class type `T`, yields the address of the vtable.
>>>>
>>>> Then we could print the vtable address of 'std::ostream' as follows:
>>>>
>>>> #include <iostream>
>>>> using namespace std;
>>>> int main()
>>>> {
>>>> cout << __builtin_get_address_vtable(ostream) << endl;
>>>> }
>>>
>>> This is essentially what copy constructors do - `__builtin_get_address_vtable` is a
>>> reference to the vtable symbol.
>>>
>>> The problem is that trivial relocation and restart lifetime are/were specified to
>>> maintain the dynamic type of the object, so you can’t simply store the vptr for the
>>> static type, but rather have to load the vptr from the object being relocated/restarted.
>>
>> You couldn't use trivial relocation on potentially overlapping subobjects, hence base
>> subobjects. Which means you couldn't use it with not matching static and dynamic types
>> in the first place.
>
> I’m not sure what you mean here? You could relocate from one location to a potentially
> overlapping destination, and the semantics as specified maintained the dynamic type. E.g
> the functional behaviour - absent technologies like pointer authentication - was identical
> to memmove, this included the hazard of performing a relocation where the static type did
> not match the dynamic type, which could result in object slicing, and a host of problems
> the follow from that.

* There is a dynamic and static type of the source object.
* There is a dynamic and static type of the destination object.

trivially_relocate is preconditioned on the source object not being potentially
overlapping, which means that the dynamic and static types of the source object must
match. This means that providing the pointer to the original pointer is redundant for
restart_lifetime, we know the dynamic type of the source object, it's the same as the
static type.

As for the target, I don't think we can easily make trivial relocation onto a base member
of an existing complete object work, nor I understand why we would want to make it work.
The interface of trivially_relocate is insufficient to do that, as it can't assume that
there is a live object at the destination and read it before the relocation to determine
its dynamic type. Even if it would work, base members are transparently replaceable, so it
would be of little use, but maybe this would involve extending the transparently
replaceable rules?

Personally I think the trivial relocation efforts lost focus when it was tried to make it
work for objects where adjustments need to be made after bitwise copying. It is a niche of
a niche, and I think virtually nobody cares about optimising this case.

>
> To my knowledge this was the intended behavior, as all arguments assumed that the behavior
> of TR without pointer auth was equivalent to memmove, but if it is expected to override
> the dynamic type of an object with the static type, then it is not longer memmove on _any_
> implementation. I presumed that this worked on the assumption that a developer had
> guaranteed that when relocating with static type A, an object with dynamic type B is the
> same size and ABI as the super type A, which is certainly a thing that people do. If the
> intent in this scenario is to mimic a copy constructor and revert the dynamic type to the
> relocated static type, then TR requires similar logic to replace the dynamic type across
> all platforms, not just those with ptrauth, i.e. it would not be memmove anywhere.
>
> —Oliver
>
>
>
>
>

Received on 2025-11-12 09:50:42