[gcc(refs/vendors/ARM/heads/arm-perf-staging)] c++: generic lambda forwarding function [PR94546]
Tamar Christina
tnfchris@gcc.gnu.org
Fri Jul 17 14:49:18 GMT 2020
https://gcc.gnu.org/g:aedd04caa945260ea77fd22f29b77292f7dba72e
commit aedd04caa945260ea77fd22f29b77292f7dba72e
Author: Jason Merrill <jason@redhat.com>
Date: Wed Apr 22 02:27:54 2020 -0400
c++: generic lambda forwarding function [PR94546]
While instantiating test(Plot) we partially instantiate the generic lambda.
We look at forward<T>(rest)... and see that it's just replacing parameter
packs with new parameter packs and tries to do a direct substitution. But
because register_parameter_specializations had built up a
NONTYPE_ARGUMENT_PACK around the new parameter pack, the substitution
failed. So let's not wrap it that way.
gcc/cp/ChangeLog
2020-04-22 Jason Merrill <jason@redhat.com>
PR c++/94546
* pt.c (register_parameter_specializations): If the instantiation is
still a parameter pack, don't wrap it in a NONTYPE_ARGUMENT_PACK.
(tsubst_pack_expansion, tsubst_expr): Adjust.
Diff:
---
gcc/cp/ChangeLog | 7 ++++++
gcc/cp/pt.c | 28 ++++++++--------------
.../g++.dg/cpp2a/lambda-generic-variadic20.C | 23 ++++++++++++++++++
3 files changed, 40 insertions(+), 18 deletions(-)
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 640e4948130..4b6691a77f0 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+2020-04-22 Jason Merrill <jason@redhat.com>
+
+ PR c++/94546
+ * pt.c (register_parameter_specializations): If the instantiation is
+ still a parameter pack, don't wrap it in a NONTYPE_ARGUMENT_PACK.
+ (tsubst_pack_expansion, tsubst_expr): Adjust.
+
2020-04-22 Martin Sebor <msebor@redhat.com>
Jason Merrill <jason@redhat.com>
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 7bf249cee5c..2fe7b66707c 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12753,7 +12753,6 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
tree pattern;
tree pack, packs = NULL_TREE;
bool unsubstituted_packs = false;
- bool unsubstituted_fn_pack = false;
int i, len = -1;
tree result;
bool need_local_specializations = false;
@@ -12833,19 +12832,15 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
else
arg_pack = make_fnparm_pack (arg_pack);
}
- else if (argument_pack_element_is_expansion_p (arg_pack, 0))
- /* This argument pack isn't fully instantiated yet. We set this
- flag rather than clear arg_pack because we do want to do the
- optimization below, and we don't want to substitute directly
- into the pattern (as that would expose a NONTYPE_ARGUMENT_PACK
- where it isn't expected). */
- unsubstituted_fn_pack = true;
+ else if (DECL_PACK_P (arg_pack))
+ /* This argument pack isn't fully instantiated yet. */
+ arg_pack = NULL_TREE;
}
else if (is_capture_proxy (parm_pack))
{
arg_pack = retrieve_local_specialization (parm_pack);
- if (argument_pack_element_is_expansion_p (arg_pack, 0))
- unsubstituted_fn_pack = true;
+ if (DECL_PACK_P (arg_pack))
+ arg_pack = NULL_TREE;
}
else
{
@@ -12880,8 +12875,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
if (len < 0)
len = my_len;
- else if (len != my_len
- && !unsubstituted_fn_pack)
+ else if (len != my_len)
{
if (!(complain & tf_error))
/* Fail quietly. */;
@@ -12904,10 +12898,6 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
/* We can't substitute for this parameter pack. We use a flag as
well as the missing_level counter because function parameter
packs don't have a level. */
- if (!(processing_template_decl || is_auto (parm_pack)))
- {
- gcc_unreachable ();
- }
gcc_assert (processing_template_decl || is_auto (parm_pack));
unsubstituted_packs = true;
}
@@ -17897,7 +17887,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
{
inst = (retrieve_local_specialization
(DECL_CAPTURED_VARIABLE (decl)));
- gcc_assert (TREE_CODE (inst) == NONTYPE_ARGUMENT_PACK);
+ gcc_assert (TREE_CODE (inst) == NONTYPE_ARGUMENT_PACK
+ || DECL_PACK_P (inst));
}
else
inst = lookup_init_capture_pack (decl);
@@ -25315,7 +25306,8 @@ register_parameter_specializations (tree pattern, tree inst)
}
for (; tmpl_parm; tmpl_parm = DECL_CHAIN (tmpl_parm))
{
- if (!DECL_PACK_P (tmpl_parm))
+ if (!DECL_PACK_P (tmpl_parm)
+ || (spec_parm && DECL_PACK_P (spec_parm)))
{
register_local_specialization (spec_parm, tmpl_parm);
spec_parm = DECL_CHAIN (spec_parm);
diff --git a/gcc/testsuite/g++.dg/cpp2a/lambda-generic-variadic20.C b/gcc/testsuite/g++.dg/cpp2a/lambda-generic-variadic20.C
new file mode 100644
index 00000000000..3d69dbb8e98
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/lambda-generic-variadic20.C
@@ -0,0 +1,23 @@
+// PR c++/94546
+// { dg-do compile { target c++2a } }
+
+template <class T> T&& forward(T&& t) { return static_cast<T&&>(t); }
+
+template <class X>
+void test(X&& plot)
+{
+ // Note: For brevity, this lambda function is only
+ // defined, not called nor assigned to a variable.
+ // Doing those things won't fix the error.
+ [&]<class... T>(T&&... rest)
+ {
+ plot(forward<T>(rest)...);
+ };
+}
+int main()
+{
+ auto Plot = [](auto&&...)
+ {
+ };
+ test(Plot);
+}
More information about the Gcc-cvs
mailing list