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

            Bug ID: 109945
           Summary: Escape analysis hates copy elision: different result
                    with -O1 vs -O2
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Keywords: wrong-code
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: arthur.j.odwyer at gmail dot com
  Target Milestone: ---

Background:
https://quuxplusone.github.io/blog/2021/03/07/copy-elision-borks-escape-analysis/
The background paradox here is, "When class Widget is subject to copy elision,
then any unseen function can return a prvalue Widget whose address has already
escaped!" Aaron Puchert and I were discussing this, with examples. (He thinks
the resolution of the paradox is "you *must* treat a lot more things as
escaped"; I think an acceptable resolution would be "you may treat copy-elision
itself as a magic that invalidates pointers and references even though the
object is still in the same place.")
But then I came up with an example that didn't rely on copy elision at all. We
both agree this code is perfectly well-defined — yet GCC miscompiles it at -O1!

// https://godbolt.org/z/bTnv68nhG
struct Widget {
    Widget();
    int i = 1;
    int a[4];
};
Widget *global = nullptr;
Widget::Widget() { global = this; }
Widget make() { return Widget(); }
void g() { global->i = 42; }
int main() {
  Widget w = make();
  int i = w.i;
  g();
  return (i == w.i);
    // Does this need to be reloaded and
    // compared? or is it obviously true?  
}

gcc -O0 and gcc -O2 both correctly return 0 from main.
gcc -O1 wrongly returns 1 from main.

*At least* since C++17, I think the -O1 result is flat-out wrong codegen. We
have `global == &w`, and so the call to `g()` can definitely modify `w.i`.

(Clang always treats Widgets' addresses as escaped, no matter what Widget looks
like. MSVC's escape analysis is more complicated and I have not yet been able
to trick it into wrong codegen.)

Reply via email to