From 1108bdc1b409ff80fd655a8fb8e2cb1e635c90e3 Mon Sep 17 00:00:00 2001 From: jason Date: Tue, 13 Feb 2018 14:22:01 +0000 Subject: [PATCH] PR c++/84338 - wrong variadic sizeof. * pt.c (argument_pack_select_arg): Like the macro, but look through a pack expansion. (tsubst, tsubst_copy, dependent_template_arg_p): Use it. (extract_fnparm_pack): Do make_pack_expansion. (extract_locals_r): Do strip a pack expansion. * cp-tree.h (ARGUMENT_PACK_SELECT_ARG): Remove. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@257626 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/cp/ChangeLog | 10 ++++ gcc/cp/cp-tree.h | 6 -- gcc/cp/pt.c | 68 +++++++++++++--------- .../g++.dg/cpp1y/lambda-generic-variadic13.C | 15 +++++ 4 files changed, 66 insertions(+), 33 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic13.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c2b19d8eb59..677392c31fc 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2018-02-13 Jason Merrill + + PR c++/84338 - wrong variadic sizeof. + * pt.c (argument_pack_select_arg): Like the macro, but look through + a pack expansion. + (tsubst, tsubst_copy, dependent_template_arg_p): Use it. + (extract_fnparm_pack): Do make_pack_expansion. + (extract_locals_r): Do strip a pack expansion. + * cp-tree.h (ARGUMENT_PACK_SELECT_ARG): Remove. + 2018-02-12 Jakub Jelinek PR c++/84341 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index a6c75aed33d..9a9e9f0bbcb 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -3558,12 +3558,6 @@ extern void decl_shadowed_for_var_insert (tree, tree); #define ARGUMENT_PACK_SELECT_INDEX(NODE) \ (((struct tree_argument_pack_select *)ARGUMENT_PACK_SELECT_CHECK (NODE))->index) -/* In an ARGUMENT_PACK_SELECT, the actual underlying argument that the - ARGUMENT_PACK_SELECT represents. */ -#define ARGUMENT_PACK_SELECT_ARG(NODE) \ - TREE_VEC_ELT (ARGUMENT_PACK_ARGS (ARGUMENT_PACK_SELECT_FROM_PACK (NODE)), \ - ARGUMENT_PACK_SELECT_INDEX (NODE)) - #define FOLD_EXPR_CHECK(NODE) \ TREE_CHECK4 (NODE, UNARY_LEFT_FOLD_EXPR, UNARY_RIGHT_FOLD_EXPR, \ BINARY_LEFT_FOLD_EXPR, BINARY_RIGHT_FOLD_EXPR) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index b58c60f0dcb..a83b7073d20 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -3394,6 +3394,34 @@ get_template_argument_pack_elems (const_tree t) return ARGUMENT_PACK_ARGS (t); } +/* In an ARGUMENT_PACK_SELECT, the actual underlying argument that the + ARGUMENT_PACK_SELECT represents. */ + +static tree +argument_pack_select_arg (tree t) +{ + tree args = ARGUMENT_PACK_ARGS (ARGUMENT_PACK_SELECT_FROM_PACK (t)); + tree arg = TREE_VEC_ELT (args, ARGUMENT_PACK_SELECT_INDEX (t)); + + /* If the selected argument is an expansion E, that most likely means we were + called from gen_elem_of_pack_expansion_instantiation during the + substituting of an argument pack (of which the Ith element is a pack + expansion, where I is ARGUMENT_PACK_SELECT_INDEX) into a pack expansion. + In this case, the Ith element resulting from this substituting is going to + be a pack expansion, which pattern is the pattern of E. Let's return the + pattern of E, and gen_elem_of_pack_expansion_instantiation will build the + resulting pack expansion from it. */ + if (PACK_EXPANSION_P (arg)) + { + /* Make sure we aren't throwing away arg info. */ + gcc_assert (!PACK_EXPANSION_EXTRA_ARGS (arg)); + arg = PACK_EXPANSION_PATTERN (arg); + } + + return arg; +} + + /* True iff FN is a function representing a built-in variadic parameter pack. */ @@ -10933,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); @@ -11388,7 +11421,8 @@ extract_locals_r (tree *tp, int */*walk_subtrees*/, void *data) /* Pull out the actual PARM_DECL for the partial instantiation. */ tree args = ARGUMENT_PACK_ARGS (spec); gcc_assert (TREE_VEC_LENGTH (args) == 1); - spec = TREE_VEC_ELT (args, 0); + tree arg = TREE_VEC_ELT (args, 0); + spec = PACK_EXPANSION_PATTERN (arg); } *extra = tree_cons (*tp, spec, *extra); } @@ -13747,29 +13781,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) { arg = TMPL_ARG (args, level, idx); + /* See through ARGUMENT_PACK_SELECT arguments. */ if (arg && TREE_CODE (arg) == ARGUMENT_PACK_SELECT) - { - /* See through ARGUMENT_PACK_SELECT arguments. */ - arg = ARGUMENT_PACK_SELECT_ARG (arg); - /* If the selected argument is an expansion E, that most - likely means we were called from - gen_elem_of_pack_expansion_instantiation during the - substituting of pack an argument pack (which Ith - element is a pack expansion, where I is - ARGUMENT_PACK_SELECT_INDEX) into a pack expansion. - In this case, the Ith element resulting from this - substituting is going to be a pack expansion, which - pattern is the pattern of E. Let's return the - pattern of E, and - gen_elem_of_pack_expansion_instantiation will - build the resulting pack expansion from it. */ - if (PACK_EXPANSION_P (arg)) - { - /* Make sure we aren't throwing away arg info. */ - gcc_assert (!PACK_EXPANSION_EXTRA_ARGS (arg)); - arg = PACK_EXPANSION_PATTERN (arg); - } - } + arg = argument_pack_select_arg (arg); } if (arg == error_mark_node) @@ -14734,7 +14748,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) } if (TREE_CODE (r) == ARGUMENT_PACK_SELECT) - r = ARGUMENT_PACK_SELECT_ARG (r); + r = argument_pack_select_arg (r); if (!mark_used (r, complain) && !(complain & tf_error)) return error_mark_node; return r; @@ -14866,7 +14880,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl) register_local_specialization (r, t); } if (TREE_CODE (r) == ARGUMENT_PACK_SELECT) - r = ARGUMENT_PACK_SELECT_ARG (r); + r = argument_pack_select_arg (r); } else r = t; @@ -24701,7 +24715,7 @@ dependent_template_arg_p (tree arg) return true; if (TREE_CODE (arg) == ARGUMENT_PACK_SELECT) - arg = ARGUMENT_PACK_SELECT_ARG (arg); + arg = argument_pack_select_arg (arg); if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM) return true; diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic13.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic13.C new file mode 100644 index 00000000000..92fd34cb268 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-variadic13.C @@ -0,0 +1,15 @@ +// PR c++/84338 +// { dg-do compile { target c++14 } } + +template < typename ... T > +auto f(T ... i){ + [](auto ... i){ + // // wrongly true in current trunk + // static_assert(sizeof...(i) == 1, ""); + static_assert(sizeof...(i) == 2, ""); + }(i ...); +} + +int main(){ + f(0, 1); +} -- 2.11.4.GIT