aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2018-01-24 10:20:53 -0500
committerJason Merrill <jason@gcc.gnu.org>2018-01-24 10:20:53 -0500
commit018e9cb5e6050e03944f426e300a1227cbbba3e2 (patch)
treefbbe2451dc630b36b36285a1f1fbf23890c5dfe7 /gcc
parenta84aff585b6fea6445ae831d523f088c9662af73 (diff)
downloadgcc-018e9cb5e6050e03944f426e300a1227cbbba3e2.zip
gcc-018e9cb5e6050e03944f426e300a1227cbbba3e2.tar.gz
gcc-018e9cb5e6050e03944f426e300a1227cbbba3e2.tar.bz2
PR c++/82249 - wrong mismatched pack length error.
* pt.c (extract_fnparm_pack, tsubst_pack_expansion): Handle unsubstituted function parameter pack. From-SVN: r257018
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/pt.c21
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic7.C19
3 files changed, 43 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index bc89041..2c499db 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2018-01-23 Jason Merrill <jason@redhat.com>
+
+ PR c++/82249 - wrong mismatched pack length error.
+ * pt.c (extract_fnparm_pack, tsubst_pack_expansion): Handle
+ unsubstituted function parameter pack.
+
2018-01-23 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/83921
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index d39b54e..abfdbd9 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10961,7 +10961,12 @@ extract_fnparm_pack (tree tmpl_parm, tree *spec_p)
parmvec = make_tree_vec (len);
spec_parm = *spec_p;
for (i = 0; i < len; i++, spec_parm = DECL_CHAIN (spec_parm))
- TREE_VEC_ELT (parmvec, i) = spec_parm;
+ {
+ tree elt = spec_parm;
+ if (DECL_PACK_P (elt))
+ elt = make_pack_expansion (elt);
+ TREE_VEC_ELT (parmvec, i) = elt;
+ }
/* Build the argument packs. */
SET_ARGUMENT_PACK_ARGS (argpack, parmvec);
@@ -11414,6 +11419,7 @@ 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;
hash_map<tree, tree> *saved_local_specializations = NULL;
@@ -11484,6 +11490,13 @@ 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 (TREE_CODE (parm_pack) == FIELD_DECL)
arg_pack = tsubst_copy (parm_pack, args, complain, in_decl);
@@ -11521,7 +11534,8 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
if (len < 0)
len = my_len;
- else if (len != my_len)
+ else if (len != my_len
+ && !unsubstituted_fn_pack)
{
if (!(complain & tf_error))
/* Fail quietly. */;
@@ -11574,7 +11588,8 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
/* We cannot expand this expansion expression, because we don't have
all of the argument packs we need. */
- if (use_pack_expansion_extra_args_p (packs, len, unsubstituted_packs))
+ if (use_pack_expansion_extra_args_p (packs, len, (unsubstituted_packs
+ || unsubstituted_fn_pack)))
{
/* We got some full packs, but we can't substitute them in until we
have values for all the packs. So remember these until then. */
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic7.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic7.C
new file mode 100644
index 0000000..5c5af14
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic7.C
@@ -0,0 +1,19 @@
+// PR c++/82249
+// { dg-do compile { target c++14 } }
+
+template<class T, class U> T calc (T t, U u) { return t; }
+template <class... Ts> void sink(Ts...);
+
+template < typename ... Ds >
+void f(Ds ...) {
+ [](auto ... n){
+ sink (calc(n, Ds{}) ...);
+ }(Ds{} ...);
+}
+
+
+int main(){
+ f(); // Wrong error
+ f(0, 0); // Wrong error
+ f(0); // ICE
+}