public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
From: "arthur.j.odwyer at gmail dot com" <gcc-bugzilla@gcc.gnu.org>
To: gcc-bugs@gcc.gnu.org
Subject: [Bug tree-optimization/109945] Escape analysis hates copy elision: different result with -O1 vs -O2
Date: Tue, 20 Feb 2024 15:47:49 +0000	[thread overview]
Message-ID: <bug-109945-4-DmTNlmBSRV@http.gcc.gnu.org/bugzilla/> (raw)
In-Reply-To: <bug-109945-4@http.gcc.gnu.org/bugzilla/>

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

--- Comment #30 from Arthur O'Dwyer <arthur.j.odwyer at gmail dot com> ---
I think I understand jwakely's argument at this point, and it's consistent and
teachable. https://eel.is/c++draft/class.temporary#3.sentence-1 says:

> When an object of class type X is passed to or returned from a function, if X has at least one eligible copy or move constructor, each such constructor is trivial, and the destructor of X is either trivial or deleted, implementations are permitted to create a temporary object to hold the function parameter or result object.

It says "implementations are permitted"; this means that an implementation
(GCC) can create such a temporary *whenever* permitted, and then re-optimize
the codegen under the As-If Rule to eliminate the trivial move. That still ends
the lifetime of the original object. `global` points to that original object,
which is out-of-lifetime, so dereferencing `global` is UB. (Yes, even if its
value happens to _compare_ equal to some other pointer that's still
in-lifetime: this is "pointer provenance" as I see and understand it.)

So, in order for me to call this `Widget` example a "bug," I'd have to find a
`Widget` that doesn't meet [class.temporary]/3's conditions. That is, it would
have to be a type that does NOT have eligible copy or move constructors; or has
at least one NON-trivial eligible copy or move constructor; or has a
NON-deleted NON-trivial destructor. Then the implementation (GCC) would NOT be
permitted to create a temporary and the argument wouldn't hold anymore.

And indeed, I cannot find such a `Widget`! Every example I've tried so far
matches jwakely's explanation. For example: https://godbolt.org/z/rT6Mv537e

struct X {
    X();
    X(X&, int=0);
    X(const X&) = default;
    int i = 1;
    int a[4];
};

This `X` has a non-trivial eligible copy constructor, so it doesn't meet
[class.temporary]/3's conditions, and GCC treats it the same at -O1 and -O2.
If you delete the characters `=0`, then that constructor is no longer a copy
constructor, so `X` DOES meet [class.temporary]/3 and GCC treats it differently
at -O1 and -O2 (which is fine because now the program has UB, as jwakely says).
GCC is not misbehaving in this example.

Here's another example (still matching jwakely's argument perfectly: GCC is not
misbehaving) -- this one exploits [special]/6 to play with whether the
non-trivial copy ctor is "eligible" -- https://godbolt.org/z/PWT85n5xb

I'm satisfied with the explanation -- and GCC seems to be implementing it
correctly AFAICT -- so I think it would be reasonable to close this bug as
INVALID. On the other hand, if anyone wants to argue that the current behavior
is technically correct but super confusing to working programmers, I wouldn't
argue against them, either. ;)

  parent reply	other threads:[~2024-02-20 15:47 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-05-23 14:00 [Bug c++/109945] New: " arthur.j.odwyer at gmail dot com
2023-05-23 16:09 ` [Bug tree-optimization/109945] " rguenth at gcc dot gnu.org
2023-05-23 16:11 ` rguenth at gcc dot gnu.org
2023-05-23 16:19 ` pinskia at gcc dot gnu.org
2023-05-23 16:48 ` rguenth at gcc dot gnu.org
2023-05-23 16:53 ` rguenth at gcc dot gnu.org
2023-05-23 16:53 ` pinskia at gcc dot gnu.org
2023-05-23 17:46 ` arthur.j.odwyer at gmail dot com
2023-05-23 17:49 ` pinskia at gcc dot gnu.org
2023-05-23 17:52 ` pinskia at gcc dot gnu.org
2023-05-23 17:53 ` pinskia at gcc dot gnu.org
2023-05-23 19:38 ` arthur.j.odwyer at gmail dot com
2023-05-24  6:48 ` rguenth at gcc dot gnu.org
2023-05-24  7:59 ` rguenth at gcc dot gnu.org
2023-05-24  8:16 ` jakub at gcc dot gnu.org
2023-05-24  8:42 ` rguenther at suse dot de
2023-05-24  8:51 ` jakub at gcc dot gnu.org
2023-05-24  8:55 ` rguenther at suse dot de
2023-05-24  9:00 ` jakub at gcc dot gnu.org
2023-05-24 10:12 ` rguenth at gcc dot gnu.org
2023-07-01 23:37 ` pinskia at gcc dot gnu.org
2023-07-10  8:52 ` rguenth at gcc dot gnu.org
2024-02-20  9:58 ` rguenth at gcc dot gnu.org
2024-02-20 10:45 ` jakub at gcc dot gnu.org
2024-02-20 11:53 ` jakub at gcc dot gnu.org
2024-02-20 12:07 ` redi at gcc dot gnu.org
2024-02-20 12:15 ` redi at gcc dot gnu.org
2024-02-20 12:33 ` rguenth at gcc dot gnu.org
2024-02-20 12:41 ` redi at gcc dot gnu.org
2024-02-20 12:48 ` jakub at gcc dot gnu.org
2024-02-20 15:47 ` arthur.j.odwyer at gmail dot com [this message]
2024-02-20 15:52 ` arthur.j.odwyer at gmail dot com
2024-02-20 16:49 ` redi at gcc dot gnu.org
2024-03-01 17:20 ` redi at gcc dot gnu.org

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=bug-109945-4-DmTNlmBSRV@http.gcc.gnu.org/bugzilla/ \
    --to=gcc-bugzilla@gcc.gnu.org \
    --cc=gcc-bugs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).