https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127434
Richard Biener <rguenth at gcc dot gnu.org> changed:
What |Removed |Added
----------------------------------------------------------------------------
Resolution|--- |INVALID
Status|UNCONFIRMED |RESOLVED
--- Comment #4 from Richard Biener <rguenth at gcc dot gnu.org> ---
Part 2: Verification of C++ Language Constraints
The non-workaround version of t.C (compiled with WORKAROUND=0 or undefined)
violates multiple C++ language constraints, triggering Undefined Behavior
(UB):
1. Invoking a Member Function on a Non-Existent Object
According to the ISO C++ Standard, [class.mfct.non-static] / 2:
> "If a non-static member function of a class X is called for an object that
is not of type X, or of a type derived from X, the behavior is undefined."
In t.C, no IndexingHeader object has been constructed or lives at the address
butterfly->indexingHeader() (pages + pageSize). Invoking preCapacity and
indexingPayloadSizeInBytes on this invalid/unconstructed memory address is
undefined behavior. Because the program exhibits UB, the compiler is
structurally permitted to assume that this points to a valid constructed
object (matching SRA's safe_ref assumption) and to introduce the speculative
load.
2. Out-of-Bounds/Invalid Pointer Arithmetic
According to [expr.add] / 4:
> "When an expression that has integral type is added to or subtracted from a
pointer, the result has the type of the pointer operand. If the pointer
operand points to an element of an array object [...] otherwise, the behavior
is undefined."
In the expression
reinterpret_cast<IndexingHeader*>(const_cast<Butterfly*>(this)) - 1, the
pointer is cast and decremented. There is no array of IndexingHeader at that
location, making this pointer arithmetic undefined behavior under standard
C++.
3. Object Lifetime and Strict Aliasing
According to [basic.life], an object's lifetime only begins when storage is
allocated with proper alignment and initialization (e.g., via placement new).
No Butterfly or IndexingHeader objects are ever constructed in the mapped
page. Reinterpreting and accessing raw bytes of uninitialized memory as these
class types violates both the lifetime rules and the strict aliasing rules
([basic.lval]).