Bug 98326 - [10/11 Regression] ICE: in create_tmp_var, at gimple-expr.c:482, converting stateless generic-lambda to function pointer since r10-599-gc652ff8312433483
Summary: [10/11 Regression] ICE: in create_tmp_var, at gimple-expr.c:482, converting s...
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 10.2.0
: P2 normal
Target Milestone: 10.3
Assignee: Jason Merrill
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2020-12-16 18:17 UTC by Lénárd Szolnoki
Modified: 2021-02-12 02:50 UTC (History)
5 users (show)

See Also:
Host:
Target:
Build:
Known to work: 9.3.0
Known to fail: 10.2.0, 11.0
Last reconfirmed: 2020-12-17 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Lénárd Szolnoki 2020-12-16 18:17:41 UTC
version: g++ (Compiler-Explorer-Build) 10.2.0
arguments: -O2 -std=c++17 -pedantic-errors

```
struct A {
    A() = default;
    A(const A&) {}
};

void (*fptr)(A) = [](auto){};
```

<source>: In static member function 'static constexpr decltype (((const<lambda(auto:1)>*)0)->operator()<auto:1>(static_cast<auto:1&&>(<anonymous>)))<lambda(auto:1)>::_FUN(auto:1) [with auto:1 = A]':
<source>:6:28: internal compiler error: in create_tmp_var, at gimple-expr.c:482
    6 | void (*fptr)(A) = [](auto){};
      |                            ^


The ICE seems to happen when the by-value parameter's type is not trivially copyable. It can also be reproduced with a non-trivial destructor.

If the copy-constructor is deleted then it fails to compile with a non-ice error.

Related: PR 86943

In my understanding gcc tries to copy/move the by-value parameter in the free function to pass it to `closure{}(args)`. I don't think that copying/moving the by-value argument is correct. The effect of calling the resulting function pointer should be equivalent to calling the operator() on the closure object, it's not expressed in terms of forwarding the parameters:

https://timsong-cpp.github.io/cppwp/n4659/expr.prim.lambda.closure#8

It's more precisely spelled out in C++20, as there it can be expressed it in terms of a default constructed object of the closure type:

http://eel.is/c++draft/expr.prim.lambda.closure#10.sentence-1
Comment 1 Martin Liška 2020-12-17 11:05:33 UTC
Confirmed, started with r10-599-gc652ff8312433483.
Comment 2 Jakub Jelinek 2021-02-03 13:22:49 UTC
So, shouldn't either the cp/call.c change have been:
-           && ! TREE_ADDRESSABLE (TREE_TYPE (arg)))
+           && ! TREE_ADDRESSABLE (TREE_TYPE (arg))
+           && simple_empty_class_p (TREE_TYPE (arg), arg, INIT_EXPR))
rather than
-           && ! TREE_ADDRESSABLE (TREE_TYPE (arg)))
+           && simple_empty_class_p (TREE_TYPE (arg), arg, INIT_EXPR))
so it would don't try to handle TREE_ADDRESSABLE classes this way?
Or perhaps simple_empty_class_p should punt for TREE_ADDRESSABLE types?
In any case, passing CONSTRUCTOR with TREE_ADDRESSABLE type directly as argument to function call leads to creating temporaries of the type, which aren't allowed.
Comment 3 CVS Commits 2021-02-09 01:52:39 UTC
The master branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

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

commit r11-7142-gbdbca69e0720fa9062fe71782235141f629ae006
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Feb 8 17:04:03 2021 -0500

    c++: generic lambda, fn* conv, empty class [PR98326]
    
    Here, in the thunk returned from the captureless lambda conversion to
    pointer-to-function, we try to pass through invisible reference parameters
    by reference, without doing a copy.  The empty class copy optimization was
    messing that up.
    
    gcc/cp/ChangeLog:
    
            PR c++/98326
            PR c++/20408
            * cp-gimplify.c (simple_empty_class_p): Don't touch an invisiref
            parm.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/98326
            * g++.dg/cpp1y/lambda-generic-empty1.C: New test.
Comment 4 CVS Commits 2021-02-12 02:30:16 UTC
The releases/gcc-10 branch has been updated by Jason Merrill <jason@gcc.gnu.org>:

https://gcc.gnu.org/g:031e97207463710797625382baff112b6c3ade51

commit r10-9362-g031e97207463710797625382baff112b6c3ade51
Author: Jason Merrill <jason@redhat.com>
Date:   Mon Feb 8 17:04:03 2021 -0500

    c++: generic lambda, fn* conv, empty class [PR98326]
    
    Here, in the thunk returned from the captureless lambda conversion to
    pointer-to-function, we try to pass through invisible reference parameters
    by reference, without doing a copy.  The empty class copy optimization was
    messing that up.
    
    gcc/cp/ChangeLog:
    
            PR c++/98326
            PR c++/20408
            * cp-gimplify.c (simple_empty_class_p): Don't touch an invisiref
            parm.
    
    gcc/testsuite/ChangeLog:
    
            PR c++/98326
            * g++.dg/cpp1y/lambda-generic-empty1.C: New test.
Comment 5 Jason Merrill 2021-02-12 02:50:07 UTC
Fixed for 10.3/11.