aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2011-07-11 17:03:19 -0400
committerJason Merrill <jason@gcc.gnu.org>2011-07-11 17:03:19 -0400
commitebfefb41d9ba815813e222db19748bc7072eb240 (patch)
treea2a6883ab203331d7177483d217b3c6aacd9e7d1
parentd983a802f660304ee850fac52388d698c5539d71 (diff)
downloadgcc-ebfefb41d9ba815813e222db19748bc7072eb240.zip
gcc-ebfefb41d9ba815813e222db19748bc7072eb240.tar.gz
gcc-ebfefb41d9ba815813e222db19748bc7072eb240.tar.bz2
re PR c++/49672 ([C++0x] Internal error when passing variadic template args to a lambda function)
PR c++/49672 * pt.c (extract_fnparm_pack): Split out from... (make_fnparm_pack): ...here. (instantiate_decl): Handle non-pack parms after a pack. * semantics.c (maybe_add_lambda_conv_op): Don't in a template. From-SVN: r176183
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/pt.c54
-rw-r--r--gcc/cp/semantics.c3
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic1.C15
4 files changed, 60 insertions, 18 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index a6df4fb..6d44bf2 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,11 @@
2011-07-11 Jason Merrill <jason@redhat.com>
+ PR c++/49672
+ * pt.c (extract_fnparm_pack): Split out from...
+ (make_fnparm_pack): ...here.
+ (instantiate_decl): Handle non-pack parms after a pack.
+ * semantics.c (maybe_add_lambda_conv_op): Don't in a template.
+
* decl2.c (decl_constant_var_p): Use decl_maybe_constant_var_p.
PR c++/44609
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 7c735ef..33b5b5f 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8711,11 +8711,12 @@ tsubst_template_arg (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return r;
}
-/* Give a chain SPEC_PARM of PARM_DECLs, pack them into a
- NONTYPE_ARGUMENT_PACK. */
+/* Given a function parameter pack TMPL_PARM and some function parameters
+ instantiated from it at *SPEC_P, return a NONTYPE_ARGUMENT_PACK of them
+ and set *SPEC_P to point at the next point in the list. */
static tree
-make_fnparm_pack (tree spec_parm)
+extract_fnparm_pack (tree tmpl_parm, tree *spec_p)
{
/* Collect all of the extra "packed" parameters into an
argument pack. */
@@ -8723,11 +8724,18 @@ make_fnparm_pack (tree spec_parm)
tree parmtypevec;
tree argpack = make_node (NONTYPE_ARGUMENT_PACK);
tree argtypepack = cxx_make_type (TYPE_ARGUMENT_PACK);
- int i, len = list_length (spec_parm);
+ tree spec_parm = *spec_p;
+ int i, len;
+
+ for (len = 0; spec_parm; ++len, spec_parm = TREE_CHAIN (spec_parm))
+ if (tmpl_parm
+ && !function_parameter_expanded_from_pack_p (spec_parm, tmpl_parm))
+ break;
/* Fill in PARMVEC and PARMTYPEVEC with all of the parameters. */
parmvec = make_tree_vec (len);
parmtypevec = 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;
@@ -8738,9 +8746,19 @@ make_fnparm_pack (tree spec_parm)
SET_ARGUMENT_PACK_ARGS (argpack, parmvec);
SET_ARGUMENT_PACK_ARGS (argtypepack, parmtypevec);
TREE_TYPE (argpack) = argtypepack;
+ *spec_p = spec_parm;
return argpack;
-}
+}
+
+/* Give a chain SPEC_PARM of PARM_DECLs, pack them into a
+ NONTYPE_ARGUMENT_PACK. */
+
+static tree
+make_fnparm_pack (tree spec_parm)
+{
+ return extract_fnparm_pack (NULL_TREE, &spec_parm);
+}
/* Substitute ARGS into T, which is an pack expansion
(i.e. TYPE_PACK_EXPANSION or EXPR_PACK_EXPANSION). Returns a
@@ -17830,21 +17848,21 @@ instantiate_decl (tree d, int defer_ok,
spec_parm = skip_artificial_parms_for (d, spec_parm);
tmpl_parm = skip_artificial_parms_for (subst_decl, tmpl_parm);
}
- while (tmpl_parm && !FUNCTION_PARAMETER_PACK_P (tmpl_parm))
+ for (; tmpl_parm; tmpl_parm = DECL_CHAIN (tmpl_parm))
{
- register_local_specialization (spec_parm, tmpl_parm);
- tmpl_parm = DECL_CHAIN (tmpl_parm);
- spec_parm = DECL_CHAIN (spec_parm);
+ if (!FUNCTION_PARAMETER_PACK_P (tmpl_parm))
+ {
+ register_local_specialization (spec_parm, tmpl_parm);
+ spec_parm = DECL_CHAIN (spec_parm);
+ }
+ else
+ {
+ /* Register the (value) argument pack as a specialization of
+ TMPL_PARM, then move on. */
+ tree argpack = extract_fnparm_pack (tmpl_parm, &spec_parm);
+ register_local_specialization (argpack, tmpl_parm);
+ }
}
- if (tmpl_parm && FUNCTION_PARAMETER_PACK_P (tmpl_parm))
- {
- /* Register the (value) argument pack as a specialization of
- TMPL_PARM, then move on. */
- tree argpack = make_fnparm_pack (spec_parm);
- register_local_specialization (argpack, tmpl_parm);
- tmpl_parm = DECL_CHAIN (tmpl_parm);
- spec_parm = NULL_TREE;
- }
gcc_assert (!spec_parm);
/* Substitute into the body of the function. */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 84b0dd8..fd00e29 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -8808,6 +8808,9 @@ maybe_add_lambda_conv_op (tree type)
if (LAMBDA_EXPR_CAPTURE_LIST (CLASSTYPE_LAMBDA_EXPR (type)) != NULL_TREE)
return;
+ if (processing_template_decl)
+ return;
+
stattype = build_function_type (TREE_TYPE (TREE_TYPE (callop)),
FUNCTION_ARG_CHAIN (callop));
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic1.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic1.C
new file mode 100644
index 0000000..f17b336
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic1.C
@@ -0,0 +1,15 @@
+// PR c++/49672
+// { dg-options -std=c++0x }
+
+template<typename ... Args>
+static void foo()
+{
+ [](Args..., int x) {
+ x;
+ };
+}
+
+int main()
+{
+ foo();
+}