Skip to content

[out.ptr.t][inout.ptr.t] Get rid of TBAA-violating implication#8740

Open
frederick-vs-ja wants to merge 1 commit intocplusplus:mainfrom
frederick-vs-ja:tbaa-in-out-ptr
Open

[out.ptr.t][inout.ptr.t] Get rid of TBAA-violating implication#8740
frederick-vs-ja wants to merge 1 commit intocplusplus:mainfrom
frederick-vs-ja:tbaa-in-out-ptr

Conversation

@frederick-vs-ja
Copy link
Contributor

On many platforms, we can just reuse the object/value representation of the raw pointer stored within (in)out_ptr_t for operator void**. However, directly use of reinterpret_cast violates the strict aliasing rule ([basic.lval]/11). At the time when out_ptr_t and inout_ptr_t were added to C++23, there was not yet any standard utility bypassing the strict aliasing rule, and thus the notes had to indicate core UB and were only applicable for implementations that didn't aggressively perform type-based aliasing analysis (TBAA).

Luckily, start_lifetime_as was added later, making it possible to reuse value representation without UB. This PR uses start_lifetime_as in the notes, and thus makes them probably applicable for implementations that have compatible representations for T* and void*.

Note that start_lifetime_as can cause conflicts on object creation, but conflicts are already allowed in [out.ptr.t]/5 and [inout.ptr.t]/5.

On many platforms, we can just reuse the object/value representation of
the raw pointer stored within `(in)out_ptr_t` for `operator void**`.
However, directly use of `reinterpret_cast` violates the strict aliasing
rule ([basic.lval]/11). At the time when `out_ptr_t` and `inout_ptr_t`
were added to C++23, there was not yet any standard utility bypassing
the strict aliasing rule, and thus the notes had to indicate core UB and
were only applicable for implementations that didn't aggressively
perform type-based aliasing analysis (TBAA).

Luckily, `start_lifetime_as` was added later, making it possible to
reuse value representation without UB. This PR uses `start_lifetime_as`
in the notes, and thus makes them probably applicable for
implementations that have compatible representations for `T*` and
`void*`.

Note that `start_lifetime_as` can cause conflicts on object creation,
but conflicts are already allowed in [out.ptr.t]/5 and [inout.ptr.t]/5.
@jensmaurer
Copy link
Member

On what grounds do you believe the value representation is the same for a void * vs. a T* ? Is my (hypothetical) compiler non-conforming if it rotates all void* bits by 13 ? Where is the rule that prohibits that?

@jensmaurer jensmaurer added lwg Issue must be reviewed by LWG. not-editorial Issue is not deemed editorial; the editorial issue is kept open for tracking. labels Feb 12, 2026
@frederick-vs-ja
Copy link
Contributor Author

On what grounds do you believe the value representation is the same for a void * vs. a T*

I don't think this is necessarily true for all implementations, and the notes are already saying "for some implementations" (see #5158 and #4773).

I think the intent of the original notes was noting that reusing value representation is possible for some implementations. However, the original strategy still caused core UB, and I believe start_lifetime_as fits the intent better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lwg Issue must be reviewed by LWG. not-editorial Issue is not deemed editorial; the editorial issue is kept open for tracking.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants