Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Theoretical strict aliasing violation in out_ptr_t operator void**? #133445

Copy link
Copy link
Open
@davidben

Description

@davidben
Issue body actions

(I'm filing this as an issue in the implementation, but, unless I'm wrong, I don't see good solutions beyond fixing the standard.)

I was curious how one is meant to implement std::out_ptr_t::operator void** and noticed both libc++ and libstdc++ just cast the pointer from T** to void**:
https://github.com/llvm/llvm-project/blob/main/libcxx/include/__memory/out_ptr.h#L81

Is this cast actually a valid implementation? I mean, this is presumably the intended implementation of operator void** because keeping two pointers in the out_ptr_t would definitely not be cheap. But ISTM this would cause a strict aliasing violation in the application. AIUI, this is not strictly legal by strict aliasing:

// ptr has dynamic type int*
// https://en.cppreference.com/w/cpp/language/type#Dynamic_type
int *ptr;
// *voidp has type void*
void **voidp = (void**)&ptr;
// ptr is being accessed as a void*, but ptr, of type int*, is not
// type-accessible as a void* because int* and void* are not
// similar.
// https://en.cppreference.com/w/cpp/language/implicit_conversion#Similar_types
*voidp;

Now, I played with Clang and GCC in Godbolt and it looks like neither considers types this fine-grained for strict aliasing analysis, so this is probably fine in practice. But if I'm understanding this right and this is just a compiler-specific implementation-detail, it seems we have two consequences:

First, libc++ should probably have a comment to make it clear we're relying on Clang and GCC providing more guarantees than the standard does. (Is that documented anywhere by Clang and GCC?)

Second, out_ptr_t is, AIUI, meant to be specialized by user code for custom smart pointers. While an STL implementation can be more easily tied to specific compilers, it's a bit harder for user code to justify doing this, especially if the compilers do not actually document this property. ISTM that means that a more UB-avoiding implementation needs to maintain both T* and void* storage and track a flag for which was used. That seems poor. Especially when the aim of specialization would be to return a pointer to the smart pointer's underlying storage.

Am I just misunderstanding things? Is this just a mistake in the standard? Is it time to just relax the strict aliasing rule and allow T* to be accessed as void*, not just convertible to/from?

Metadata

Metadata

Assignees

No one assigned

    Labels

    TBAAType-Based Alias Analysis / Strict AliasingType-Based Alias Analysis / Strict Aliasinglibc++libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      Morty Proxy This is a proxified and sanitized view of the page, visit original site.