Skip to content

core::Container::operator*() trips -Wcast-align for over-aligned types #40

Description

@erik-rainey-neurophos

Summary

core::Container<TYPE>::operator*() casts the raw std::uint8_t storage to TYPE* with reinterpret_cast, which trips -Werror=cast-align for any TYPE whose alignment is greater than 1. This is currently latent — Pool only ever reaches the storage through operator-> — but any use of operator* on a Container holding an over-aligned type fails to compile under a strict build. Against main (commit c66a0d2).

Details

modules/core/include/core/Container.hpp (~lines 78–85):

TYPE& operator*() {
    if (that_) {
        return *that_;
    } else {
        // this is potentially uninitialized or undefined storage!
        return *reinterpret_cast<TYPE*>(&storage_[0]);
    }
}

with the backing storage declared (line ~103):

alignas(alignof(TYPE)) std::uint8_t storage_[sizeof(TYPE)];

&storage_[0] has type std::uint8_t* (alignment 1). Casting it to TYPE* when alignof(TYPE) > 1 makes GCC's -Wcast-align warn (and fail under -Werror):

error: cast from 'uint8_t*' {aka 'unsigned char*'} to 'T*' increases required alignment of target type [-Werror=cast-align]

The cast is in fact safe — storage_ is declared alignas(alignof(TYPE)), so the pointer is correctly aligned — but the compiler only sees the uint8_t element type at the point of the cast, so the diagnostic is a false positive.

Why it's latent today

Pool<TYPE, N> accesses elements via operator-> (which returns that_ directly, no cast), so operator*'s else branch is never instantiated for an aligned type in the current tree. It surfaces the moment operator* is instantiated for a Container of an over-aligned type (a class with alignof > 1, e.g. anything containing a pointer or 4/8-byte field). It would also bite the on-target build, which compiles with -Wcast-align -Werror.

Suggested fix

Route the cast through void*, which is well-defined given the alignas storage and suppresses the false-positive warning:

return *static_cast<TYPE*>(static_cast<void*>(&storage_[0]));

(Same note as the existing comment applies: this branch still returns a reference to not-yet-constructed storage; only the cast is being made portable.)

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions