Bug 101717 - [9 Regression] ICE capturing static member within stateless generic lambda
Summary: [9 Regression] ICE capturing static member within stateless generic lambda
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 12.0
: P2 normal
Target Milestone: 9.5
Assignee: Jason Merrill
URL:
Keywords: c++-lambda, ice-checking, ice-on-valid-code
Depends on:
Blocks: lambdas
  Show dependency treegraph
 
Reported: 2021-08-02 00:21 UTC by Johel Ernesto Guerrero Peña
Modified: 2022-05-13 17:47 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2021-12-28 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Johel Ernesto Guerrero Peña 2021-08-02 00:21:38 UTC
See https://godbolt.org/z/z4d4qhx8j.
```C++
struct x {
  static void f() noexcept { }
  void (*_)() = [] { [&](auto) { f(); }(0); };
};
```
Comment 1 Johel Ernesto Guerrero Peña 2021-08-02 00:24:06 UTC
A bit simpler and a clarification: capturing at all within a generic stateless lambda. https://godbolt.org/z/q11fT7MM8.
```C++
struct x {
  static void f() { }
  void (*_)() = [] { [=](auto) { f(); }(0); };
};
```
Comment 2 Andrew Pinski 2021-08-02 17:17:05 UTC
Confirmed, GCC 11.2 compiles it cleanly.  So this is a regression.
Comment 3 Steven Sun 2021-08-03 22:23:39 UTC
This bug is not introduced in GCC 12.

The relevant code fragment is last edited by g:91e534b0d


in `gcc/cp/lambda.c`
```
gcc_checking_assert
(init && (TREE_TYPE (TREE_TYPE (init))
== current_nonlambda_class_type ()));

```

The assertion fails since long ago. (init == 0 in this case)

Before GCC 12, the `gcc_checking_assert` is `(void)0` in release version, leaving everything fine. Somehow `gcc_checking_assert` starts working now, and aborts the program.


My insight on the problem:
The program seems never think of a situation "a lambda inside a lambda inside a NSDMI`. We need to amend the logic here.

"here" means https://gcc.gnu.org/git?p=gcc.git;a=blob;f=gcc/cp/lambda.c;h=2e9d38bbe832702804ddcaffc4024ce930a74843;hb=refs/heads/master#l755

By the way, does anyone know other magics like g:hash?
Comment 4 Andrew Pinski 2021-08-03 22:51:28 UTC
(In reply to Steven Sun from comment #3)
> By the way, does anyone know other magics like g:hash?

rNNNN works for the old Subversion revisions
"PRNNNN" and "bug NNNN" (maybe one more) puts a link to the other bug.
rN-NNNN (and rN-NNNN-HHHHH) works if you know the new scheme of git revisions (git gcc-descr can find that for you and you can undo them with gcc-undescr)

I think those are all of the ones which we added to bugzilla, everything else is standard (e.g. comment #0 works).
Comment 5 Steven Sun 2021-08-03 23:28:22 UTC
(In reply to Andrew Pinski from comment #4)
Thanks!


(In reply to myself from comment #3)

> The program seems never think of a situation "a lambda inside a lambda
> inside a NSDMI`. We need to amend the logic here.


edit to:

The program seems never think of a situation "member function call inside a generic lambda inside a lambda inside a NSDMI`. We need to amend the logic here.


-------------------------------------

The direct cause of failure is in g:91e534b0d

```
if (!containing_function && !COMPLETE_TYPE_P (closure))
    /* If we're parsing a lambda in a non-local class,
       we can find the fake 'this' in scope_chain.  */
    init = scope_chain->x_current_class_ptr;
```

This part of logic is to find the potential `this` since there is a (static) member function call `f`. Refer to the following comments:

  /* For the overload resolution we need to find the actual `this`
     that would be captured if the call turns out to be to a
     non-static member function.  Do not actually capture it at this
     point.  */


// in function `build_new_method_call_1` in `gcc/cp/call.c`

-------------------------------------

As for example in comment 1:


`scope_chain->x_current_class_ptr` is correctly set when parsing 

```
[=](auto) { f(); }
```

But it was soon incorrectly set when instantiating the same lambda, i.e. parsing

```
[=](auto) { f(); }()
``` 


This failure only affectes the potential `this` pointer inside the

```
[=](auto) { f(); }
```

But since here needs no `this` pointer, deleting that problematical `gcc_checking_assert` is actually a potential fix for this problem.
Comment 6 Martin Liška 2022-01-31 15:59:24 UTC
Started with r9-279-g86cf10840b6cfbfe.
Comment 7 GCC Commits 2022-04-07 03:26:08 UTC
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:8e4339f5023286d25c7dfa40b4c88e63b780cfd7

commit r12-8036-g8e4339f5023286d25c7dfa40b4c88e63b780cfd7
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Apr 6 22:20:49 2022 -0400

    c++: nested generic lambda in DMI [PR101717]
    
    We were already checking COMPLETE_TYPE_P to recognize instantiation of a
    generic lambda, but didn't consider that we might be nested in a non-generic
    lambda.
    
            PR c++/101717
    
    gcc/cp/ChangeLog:
    
            * lambda.cc (lambda_expr_this_capture): Check all enclosing
            lambdas for completeness.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp1y/lambda-generic-this4.C: New test.
Comment 8 GCC Commits 2022-04-12 20:14:24 UTC
The releases/gcc-11 branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:eea5641912b914f3589ec1ec576a596451180baa

commit r11-9824-geea5641912b914f3589ec1ec576a596451180baa
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Apr 6 22:20:49 2022 -0400

    c++: nested generic lambda in DMI [PR101717]
    
    We were already checking COMPLETE_TYPE_P to recognize instantiation of a
    generic lambda, but didn't consider that we might be nested in a non-generic
    lambda.
    
            PR c++/101717
    
    gcc/cp/ChangeLog:
    
            * lambda.c (lambda_expr_this_capture): Check all enclosing
            lambdas for completeness.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp1y/lambda-generic-this4.C: New test.
Comment 9 GCC Commits 2022-05-12 21:15:20 UTC
The releases/gcc-10 branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:20dc7a2119cc0a4e5ddc4a6899a7350621f05440

commit r10-10721-g20dc7a2119cc0a4e5ddc4a6899a7350621f05440
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Apr 6 22:20:49 2022 -0400

    c++: nested generic lambda in DMI [PR101717]
    
    We were already checking COMPLETE_TYPE_P to recognize instantiation of a
    generic lambda, but didn't consider that we might be nested in a non-generic
    lambda.
    
            PR c++/101717
    
    gcc/cp/ChangeLog:
    
            * lambda.c (lambda_expr_this_capture): Check all enclosing
            lambdas for completeness.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp1y/lambda-generic-this4.C: New test.
Comment 10 GCC Commits 2022-05-13 17:41:23 UTC
The releases/gcc-9 branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:7ce3d2ab2a1a144f94a3a9be716fb831cb76603b

commit r9-10168-g7ce3d2ab2a1a144f94a3a9be716fb831cb76603b
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Apr 6 22:20:49 2022 -0400

    c++: nested generic lambda in DMI [PR101717]
    
    We were already checking COMPLETE_TYPE_P to recognize instantiation of a
    generic lambda, but didn't consider that we might be nested in a non-generic
    lambda.
    
            PR c++/101717
    
    gcc/cp/ChangeLog:
    
            * lambda.c (lambda_expr_this_capture): Check all enclosing
            lambdas for completeness.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/cpp1y/lambda-generic-this4.C: New test.
Comment 11 Jason Merrill 2022-05-13 17:47:50 UTC
Fixed for 9.5/10.4/11.3/12.