aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2025-03-29 14:00:55 -0400
committerJason Merrill <jason@redhat.com>2025-03-31 07:29:23 -0400
commit1949beb7dbe66687542f4a19d316914dd73fe84d (patch)
tree5f209878fb0968adac5ad5084907079bd38dca12
parent95c25cb09f58810bc520c3db469945c6a751aa32 (diff)
downloadgcc-1949beb7dbe66687542f4a19d316914dd73fe84d.zip
gcc-1949beb7dbe66687542f4a19d316914dd73fe84d.tar.gz
gcc-1949beb7dbe66687542f4a19d316914dd73fe84d.tar.bz2
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.
-rw-r--r--gcc/cp/pt.cc13
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/lambda-targ11.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/lambda-targ12.C13
3 files changed, 39 insertions, 0 deletions
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 417d107..f7c56a1 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -27238,6 +27238,19 @@ regenerate_decl_from_template (tree decl, tree tmpl, tree args)
if (DECL_UNIQUE_FRIEND_P (decl))
goto done;
+ /* A template with a lambda in the signature also changes type if
+ regenerated (PR119401). */
+ walk_tree_fn find_lambda
+ = [](tree *tp, int *, void *)
+ {
+ if (TREE_CODE (*tp) == LAMBDA_EXPR)
+ return *tp;
+ return NULL_TREE;
+ };
+ if (cp_walk_tree_without_duplicates
+ (&TREE_TYPE (tmpl), find_lambda, nullptr))
+ goto done;
+
/* Use the source location of the definition. */
DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (tmpl);
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ11.C b/gcc/testsuite/g++.dg/cpp2a/lambda-targ11.C
new file mode 100644
index 0000000..9f2f743
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ11.C
@@ -0,0 +1,13 @@
+// PR c++/119401
+// { dg-do compile { target c++20 } }
+
+template <auto>
+struct B {};
+template <int N>
+struct A {
+ void f(B<[]{}>) {}
+};
+auto t = &A<0>::f;
+
+// A<0>::f(B<A<0>::{lambda()#1}{}>)
+// { dg-final { scan-assembler "_ZN1AILi0EE1fE1BIXtlNS0_UlvE_EEEE" { xfail *-*-* } } }
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-targ12.C b/gcc/testsuite/g++.dg/cpp2a/lambda-targ12.C
new file mode 100644
index 0000000..bb3f701
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-targ12.C
@@ -0,0 +1,13 @@
+// PR c++/119401
+// { dg-do compile { target c++20 } }
+
+template <class>
+struct B {};
+template <int N>
+struct A {
+ void f(B<decltype([]{})>) {}
+};
+auto t = &A<0>::f;
+
+// A<0>::f(B<A<0>::{lambda()#1}>)
+// { dg-final { scan-assembler "_ZN1AILi0EE1fE1BINS0_UlvE_EE" { xfail *-*-* } } }