aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2018-02-13 09:22:07 -0500
committerJason Merrill <jason@gcc.gnu.org>2018-02-13 09:22:07 -0500
commit29e10a680730cfcdec486eb2f636169e5ffb08ab (patch)
tree602834c72b6c4146330bf07aa0709513ff34785f /gcc
parent812c0795283d5eaebf84922e3d1951fdba1936c5 (diff)
downloadgcc-29e10a680730cfcdec486eb2f636169e5ffb08ab.zip
gcc-29e10a680730cfcdec486eb2f636169e5ffb08ab.tar.gz
gcc-29e10a680730cfcdec486eb2f636169e5ffb08ab.tar.bz2
Fix more variadic capture issues.
* pt.c (find_parameter_packs_r): Also look at explicit captures. (check_for_bare_parameter_packs): Check current_class_type for lambda context. (extract_locals_r): Handle seeing a full instantiation of a pack. (tsubst_pack_expansion): Likewise. Force lambda capture. * parser.c (cp_parser_lambda_introducer): Don't check_for_bare_parameter_packs. From-SVN: r257627
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/parser.c2
-rw-r--r--gcc/cp/pt.c79
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic5.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic12.C16
5 files changed, 90 insertions, 17 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 677392c..3f37392 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,14 @@
2018-02-13 Jason Merrill <jason@redhat.com>
+ Fix more variadic capture issues.
+ * pt.c (find_parameter_packs_r): Also look at explicit captures.
+ (check_for_bare_parameter_packs): Check current_class_type for
+ lambda context.
+ (extract_locals_r): Handle seeing a full instantiation of a pack.
+ (tsubst_pack_expansion): Likewise. Force lambda capture.
+ * parser.c (cp_parser_lambda_introducer): Don't
+ check_for_bare_parameter_packs.
+
PR c++/84338 - wrong variadic sizeof.
* pt.c (argument_pack_select_arg): Like the macro, but look through
a pack expansion.
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 9a05e4f..81c6f01 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -10412,8 +10412,6 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
cp_lexer_consume_token (parser->lexer);
capture_init_expr = make_pack_expansion (capture_init_expr);
}
- else
- check_for_bare_parameter_packs (capture_init_expr);
}
if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index a83b707..02d448e 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -3587,7 +3587,6 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
}
break;
- /* Look through a lambda capture proxy to the field pack. */
case VAR_DECL:
if (DECL_PACK_P (t))
{
@@ -3707,6 +3706,12 @@ find_parameter_packs_r (tree *tp, int *walk_subtrees, void* data)
case LAMBDA_EXPR:
{
+ /* Look at explicit captures. */
+ for (tree cap = LAMBDA_EXPR_CAPTURE_LIST (t);
+ cap; cap = TREE_CHAIN (cap))
+ cp_walk_tree (&TREE_VALUE (cap), &find_parameter_packs_r, ppd,
+ ppd->visited);
+ /* Since we defer implicit capture, look in the body as well. */
tree fn = lambda_function (t);
cp_walk_tree (&DECL_SAVED_TREE (fn), &find_parameter_packs_r, ppd,
ppd->visited);
@@ -3907,7 +3912,7 @@ check_for_bare_parameter_packs (tree t)
return false;
/* A lambda might use a parameter pack from the containing context. */
- if (current_function_decl && LAMBDA_FUNCTION_P (current_function_decl))
+ if (current_class_type && LAMBDA_TYPE_P (current_class_type))
return false;
if (TREE_CODE (t) == TYPE_DECL)
@@ -11410,30 +11415,72 @@ tsubst_binary_right_fold (tree t, tree args, tsubst_flags_t complain,
/* Walk through the pattern of a pack expansion, adding everything in
local_specializations to a list. */
+struct el_data
+{
+ tree extra;
+ tsubst_flags_t complain;
+};
static tree
-extract_locals_r (tree *tp, int */*walk_subtrees*/, void *data)
+extract_locals_r (tree *tp, int */*walk_subtrees*/, void *data_)
{
- tree *extra = reinterpret_cast<tree*>(data);
+ el_data &data = *reinterpret_cast<el_data*>(data_);
+ tree *extra = &data.extra;
+ tsubst_flags_t complain = data.complain;
if (tree spec = retrieve_local_specialization (*tp))
{
if (TREE_CODE (spec) == NONTYPE_ARGUMENT_PACK)
{
- /* Pull out the actual PARM_DECL for the partial instantiation. */
+ /* Maybe pull out the PARM_DECL for a partial instantiation. */
tree args = ARGUMENT_PACK_ARGS (spec);
- gcc_assert (TREE_VEC_LENGTH (args) == 1);
- tree arg = TREE_VEC_ELT (args, 0);
- spec = PACK_EXPANSION_PATTERN (arg);
+ if (TREE_VEC_LENGTH (args) == 1)
+ {
+ tree elt = TREE_VEC_ELT (args, 0);
+ if (PACK_EXPANSION_P (elt))
+ elt = PACK_EXPANSION_PATTERN (elt);
+ if (DECL_PACK_P (elt))
+ spec = elt;
+ }
+ if (TREE_CODE (spec) == NONTYPE_ARGUMENT_PACK)
+ {
+ /* Handle lambda capture here, since we aren't doing any
+ substitution now, and so tsubst_copy won't call
+ process_outer_var_ref. */
+ tree args = ARGUMENT_PACK_ARGS (spec);
+ int len = TREE_VEC_LENGTH (args);
+ for (int i = 0; i < len; ++i)
+ {
+ tree arg = TREE_VEC_ELT (args, i);
+ tree carg = arg;
+ if (outer_automatic_var_p (arg))
+ carg = process_outer_var_ref (arg, complain);
+ if (carg != arg)
+ {
+ /* Make a new NONTYPE_ARGUMENT_PACK of the capture
+ proxies. */
+ if (i == 0)
+ {
+ spec = copy_node (spec);
+ args = copy_node (args);
+ SET_ARGUMENT_PACK_ARGS (spec, args);
+ register_local_specialization (spec, *tp);
+ }
+ TREE_VEC_ELT (args, i) = carg;
+ }
+ }
+ }
}
+ if (outer_automatic_var_p (spec))
+ spec = process_outer_var_ref (spec, complain);
*extra = tree_cons (*tp, spec, *extra);
}
return NULL_TREE;
}
static tree
-extract_local_specs (tree pattern)
+extract_local_specs (tree pattern, tsubst_flags_t complain)
{
- tree extra = NULL_TREE;
- cp_walk_tree_without_duplicates (&pattern, extract_locals_r, &extra);
- return extra;
+ el_data data = { NULL_TREE, complain };
+ cp_walk_tree_without_duplicates (&pattern, extract_locals_r, &data);
+ return data.extra;
}
/* Substitute ARGS into T, which is an pack expansion
@@ -11468,8 +11515,10 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
extract_local_specs; map from the general template to our local
context. */
tree gen = TREE_PURPOSE (elt);
- tree partial = TREE_VALUE (elt);
- tree inst = retrieve_local_specialization (partial);
+ tree inst = TREE_VALUE (elt);
+ if (DECL_PACK_P (inst))
+ inst = retrieve_local_specialization (inst);
+ /* else inst is already a full instantiation of the pack. */
register_local_specialization (inst, gen);
}
gcc_assert (!TREE_PURPOSE (extra));
@@ -11651,7 +11700,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
t = make_pack_expansion (pattern, complain);
tree extra = args;
if (local_specializations)
- if (tree locals = extract_local_specs (pattern))
+ if (tree locals = extract_local_specs (pattern, complain))
extra = tree_cons (NULL_TREE, extra, locals);
PACK_EXPANSION_EXTRA_ARGS (t) = extra;
return t;
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic5.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic5.C
index 5196a18..97f64cd 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-variadic5.C
@@ -11,6 +11,7 @@ template<class... T>
void print_all(const T&... t)
{
accept_all([&]()->int { print(t); return 0; }...);
+ accept_all([&t]()->int { print(t); return 0; }...);
}
int main()
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic12.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic12.C
new file mode 100644
index 0000000..8113320
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic12.C
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++14 } }
+
+template < typename... T > void sink(T ...){}
+
+template < typename... T >
+auto f(T... t){
+ [=](auto ... j){
+ sink((t + j)...);
+ }(t...);
+}
+
+int main(){
+ f(0);
+ f();
+ f(0.1,0.2);
+}