public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c++/106864] New: Unexpected capture of "constexpr int" variable inside lambda
@ 2022-09-06 19:51 a.elovikov at gmail dot com
  2022-10-21  3:22 ` [Bug c++/106864] " pinskia at gcc dot gnu.org
  2022-10-21  3:31 ` pinskia at gcc dot gnu.org
  0 siblings, 2 replies; 3+ messages in thread
From: a.elovikov at gmail dot com @ 2022-09-06 19:51 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 106864
           Summary: Unexpected capture of "constexpr int" variable inside
                    lambda
           Product: gcc
           Version: unknown
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: a.elovikov at gmail dot com
  Target Milestone: ---

void bad() {
  constexpr int x = 1;
  auto Outer = [&]() {
    auto L = [=]() {
      for (int i = 0; i < x; ++i) {
      }
    };
    static_assert(sizeof(L) == 1); // fails
  };
}

void good() {
  constexpr int x = 1;
  auto L = [=]() {
    for (int i = 0; i < x; ++i) {
    }
  };
  static_assert(sizeof(L) == 1);  // passes
}

Not sure if that's a bug from the standard conformance point of view, but I'd
expect the L not to capture constexpr variable in both cases.

Sizeof is one in both cases with clang and (MSVC v19.latest + "/std:c++latest
/c") on godbolt.

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

* [Bug c++/106864] Unexpected capture of "constexpr int" variable inside lambda
  2022-09-06 19:51 [Bug c++/106864] New: Unexpected capture of "constexpr int" variable inside lambda a.elovikov at gmail dot com
@ 2022-10-21  3:22 ` pinskia at gcc dot gnu.org
  2022-10-21  3:31 ` pinskia at gcc dot gnu.org
  1 sibling, 0 replies; 3+ messages in thread
From: pinskia at gcc dot gnu.org @ 2022-10-21  3:22 UTC (permalink / raw)
  To: gcc-bugs

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

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |missed-optimization

--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
I think this is just a missed optimization really.
Because GCC does the right thing inside the inner most lambda and it is
considered as a constexpr there still. But the inner lambda L has a capture
still.

You can see the missed optimization via:
void bad() {
  constexpr int x = 123;
  auto Outer = [&] [[gnu::noipa]] () {
    auto L = [=]  [[gnu::noipa]] () {
      for (int i = 0; i < x; ++i) { asm("":::"memory"); }

    };
    //static_assert(sizeof(L) == 1); // fails
    asm("":::"memory");
   L();
  };
  Outer();
    static_assert(sizeof(Outer) == 1); // fails
}

And look at the assembly for `bad()::{lambda()#1}::operator()() const` which
does the store before calling `bad()::{lambda()#1}::operator()()
const::{lambda()#1}::operator()() const`
But `bad()::{lambda()#1}::operator()() const::{lambda()#1}::operator()() const`
uses 123 always.
Even at -O2 and such.

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

* [Bug c++/106864] Unexpected capture of "constexpr int" variable inside lambda
  2022-09-06 19:51 [Bug c++/106864] New: Unexpected capture of "constexpr int" variable inside lambda a.elovikov at gmail dot com
  2022-10-21  3:22 ` [Bug c++/106864] " pinskia at gcc dot gnu.org
@ 2022-10-21  3:31 ` pinskia at gcc dot gnu.org
  1 sibling, 0 replies; 3+ messages in thread
From: pinskia at gcc dot gnu.org @ 2022-10-21  3:31 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #2 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Take:
void bad() {
  constexpr int x = 123;
  auto Outer = [&] [[gnu::noipa]] () {
    auto L = [=]  [[gnu::noipa]] () {
      const int *x1 = &x;
      for (int i = 0; i < *x1; ++i) { asm("":::"memory"); }
    };
    asm("":::"memory");
   L();
  };
  Outer();
}

void good() {
  constexpr int x = 123;
  auto L = [=] [[gnu::noipa]]() {
      const int *x1 = &x;
    for (int i = 0; i < *x1; ++i) {asm("":::"memory"); }    
  };
  L();
}

In the bad case, L is sizeof int and Outer is still 1. In good, it is sizeof
int.
This is for GCC and clang.

So I think GCC is just capturing and not removing constexpr after doing the
prop for constexpr. Which I think is just a missed optimization.

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

end of thread, other threads:[~2022-10-21  3:31 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-06 19:51 [Bug c++/106864] New: Unexpected capture of "constexpr int" variable inside lambda a.elovikov at gmail dot com
2022-10-21  3:22 ` [Bug c++/106864] " pinskia at gcc dot gnu.org
2022-10-21  3:31 ` pinskia at gcc dot gnu.org

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).