public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/110912] New: False assumption that constructors cannot alias any of their parameters
@ 2023-08-05 10:04 janschultke at googlemail dot com
  2023-08-08  2:13 ` [Bug c++/110912] " de34 at live dot cn
  2023-08-08  8:47 ` janschultke at googlemail dot com
  0 siblings, 2 replies; 3+ messages in thread
From: janschultke at googlemail dot com @ 2023-08-05 10:04 UTC (permalink / raw)
  To: gcc-bugs

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.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [Bug c++/110912] False assumption that constructors cannot alias any of their parameters
  2023-08-05 10:04 [Bug c++/110912] New: False assumption that constructors cannot alias any of their parameters janschultke at googlemail dot com
@ 2023-08-08  2:13 ` de34 at live dot cn
  2023-08-08  8:47 ` janschultke at googlemail dot com
  1 sibling, 0 replies; 3+ messages in thread
From: de34 at live dot cn @ 2023-08-08  2:13 UTC (permalink / raw)
  To: gcc-bugs

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

Jiang An <de34 at live dot cn> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |de34 at live dot cn

--- Comment #1 from Jiang An <de34 at live dot cn> ---
The restriction agains aliasing was intended, see
https://cplusplus.github.io/CWG/issues/2271.html.

The status quo seems to be that in the body of `A::A(int &x)`, compilers can
assume that the value of `x` won't be changed by a modification on `*this`, but
not the other way around.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [Bug c++/110912] False assumption that constructors cannot alias any of their parameters
  2023-08-05 10:04 [Bug c++/110912] New: False assumption that constructors cannot alias any of their parameters janschultke at googlemail dot com
  2023-08-08  2:13 ` [Bug c++/110912] " de34 at live dot cn
@ 2023-08-08  8:47 ` janschultke at googlemail dot com
  1 sibling, 0 replies; 3+ messages in thread
From: janschultke at googlemail dot com @ 2023-08-08  8:47 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #2 from Jan Schultke <janschultke at googlemail dot com> ---
(In reply to Jiang An from comment #1)
> The restriction agains aliasing was intended, see
> https://cplusplus.github.io/CWG/issues/2271.html.
> 
> The status quo seems to be that in the body of `A::A(int &x)`, compilers can
> assume that the value of `x` won't be changed by a modification on `*this`,
> but not the other way around.

Then this status quo is not correctly implemented, because in the example, GCC
assumes that a change of `x` (see `x = 5`) cannot alter `this->i` (see `i == 0`
assumed to be always true).

It is not enough to put `__restrict` on the parameters; a much weaker modifier
must be used for this purpose. At most, a "one-way `__restrict`" must be used,
if such a thing exists.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-08-08  8:47 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-08-05 10:04 [Bug c++/110912] New: False assumption that constructors cannot alias any of their parameters janschultke at googlemail dot com
2023-08-08  2:13 ` [Bug c++/110912] " de34 at live dot cn
2023-08-08  8:47 ` janschultke at googlemail dot com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).