Skip to content

Commit 1949beb

Browse files
committed
c++: lambda in function template signature [PR119401]
Here we instantiate the lambda three times in producing A<0>::f: 1) in tsubst_function_type, substituting the type of A<>::f 2) in tsubst_function_decl, substituting the parameters of A<>::f 3) in regenerate_decl_from_template when instantiating A<>::f The first one gets thrown away by maybe_rebuild_function_decl_type. Before r15-7202, we happily built all of them and mangled the result wrongly as lambda #3. After r15-7202, we try to mangle #3 as #1, which breaks because #1 is already mangled as #1. This patch avoids building #3 by suppressing regenerate_decl_from_template if the template signature includes a lambda, fixing the ICE. We now mangle the lambda as #2, which is still wrong. Addressing that should involve not calling tsubst_function_type from tsubst_function_decl, and building the type from the parms types in the first place rather than fixing it up in maybe_rebuild_function_decl_type. PR c++/119401 gcc/cp/ChangeLog: * pt.cc (regenerate_decl_from_template): Don't regenerate if the signature involves a lambda. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/lambda-targ11.C: New test.
1 parent 95c25cb commit 1949beb

File tree

3 files changed

+39
-0
lines changed

3 files changed

+39
-0
lines changed

gcc/cp/pt.cc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27238,6 +27238,19 @@ regenerate_decl_from_template (tree decl, tree tmpl, tree args)
2723827238
if (DECL_UNIQUE_FRIEND_P (decl))
2723927239
goto done;
2724027240

27241+
/* A template with a lambda in the signature also changes type if
27242+
regenerated (PR119401). */
27243+
walk_tree_fn find_lambda
27244+
= [](tree *tp, int *, void *)
27245+
{
27246+
if (TREE_CODE (*tp) == LAMBDA_EXPR)
27247+
return *tp;
27248+
return NULL_TREE;
27249+
};
27250+
if (cp_walk_tree_without_duplicates
27251+
(&TREE_TYPE (tmpl), find_lambda, nullptr))
27252+
goto done;
27253+
2724127254
/* Use the source location of the definition. */
2724227255
DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (tmpl);
2724327256

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// PR c++/119401
2+
// { dg-do compile { target c++20 } }
3+
4+
template <auto>
5+
struct B {};
6+
template <int N>
7+
struct A {
8+
void f(B<[]{}>) {}
9+
};
10+
auto t = &A<0>::f;
11+
12+
// A<0>::f(B<A<0>::{lambda()#1}{}>)
13+
// { dg-final { scan-assembler "_ZN1AILi0EE1fE1BIXtlNS0_UlvE_EEEE" { xfail *-*-* } } }
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// PR c++/119401
2+
// { dg-do compile { target c++20 } }
3+
4+
template <class>
5+
struct B {};
6+
template <int N>
7+
struct A {
8+
void f(B<decltype([]{})>) {}
9+
};
10+
auto t = &A<0>::f;
11+
12+
// A<0>::f(B<A<0>::{lambda()#1}>)
13+
// { dg-final { scan-assembler "_ZN1AILi0EE1fE1BINS0_UlvE_EE" { xfail *-*-* } } }

0 commit comments

Comments
 (0)