https://gcc.gnu.org/bugzilla/show_bug.cgi?id=110912

            Bug ID: 110912
           Summary: False assumption that constructors cannot alias any of
                    their parameters
           Product: gcc
           Version: 14.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: janschultke at googlemail dot com
  Target Milestone: ---

It looks like GCC thinks that no aliasing can take place betweeen `this` and
any constructor parameters.
You get the same output if you use `__restrict` for any pointers passed into
constructors, or if you add `noalias` to LLVM IR.

There is no wording in the standard that disallows aliasing in constructors
completely, and this may cause more serious issues in real code See
https://github.com/cplusplus/CWG/issues/206.

This bug stems from an over-interpretation of [class.cdtor] p2
(https://eel.is/c++draft/class.cdtor#2), which states that an unspecified value
is obtained when not accessing subobjects through the `this` pointer. However,
it DOES NOT say that side effects will result in unspecified values, and it
DOES NOT say that any undefined behavior is involved, which is the prerequisite
to treat this as `noalias`.

It seems to have been introduced here, and there is a related LLVM issue:
- https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82899
- https://bugs.llvm.org/show_bug.cgi?id=37329

For reference, [class.cdtor] p2:
> During the construction of an object,
> if the value of the object or any of its subobjects is accessed
> through a glvalue that is not obtained,
> directly or indirectly, from the constructor's this pointer,
> the value of the object or subobject thus obtained is unspecified.

THIS WORDING IS NOT STRONG ENOUGH FOR `noalias`! This is an old paragraph which
originally applied to const objects only, and has some problems with breaking
legitimate code for polymorphic classes. I am not entirely sure about the
intention behind it myself, but it would have been very easy for the committee
to make access through such a pointer (not obtained from `this`) undefined
behavior. That would actually allow `noalias`, NOT the current wording.

I have talked to other knowledgeable members of the community, and so far no
one believes that the wording is strong enough, or intended to disallow
aliasing entirely.

Related discussions:
- https://lists.isocpp.org/std-discussion/2023/08/2324.php
- https://lists.isocpp.org/std-discussion/2022/12/1952.php



## Code to Reproduce (https://godbolt.org/z/K4nTPYK3r)

void foo();

struct A {
    int i = 0;
    [[gnu::used]] A(int &x) {
        x = 5;
        if (i == 0) {
            foo();
        }
    }
};



## Actual Output (gcc trunk -O3)

A::A(int&) [base object constructor]:
        mov     DWORD PTR [rdi], 0
        mov     DWORD PTR [rsi], 5
        jmp     foo()



## Expected Output (clang trunk -O3)

A::A(int&) [base object constructor]:
        mov     dword ptr [rdi], 0
        mov     dword ptr [rsi], 5
        cmp     dword ptr [rdi], 0
        je      foo()@PLT
        ret



## Suggested Resolution

Do not assume `noalias` for all parameters in a constructor.

Reply via email to