Commit c67dd256 by Jason Merrill Committed by Jason Merrill

re PR c++/48322 ([C++0x] Plural variadic parameter packs are not expanded well)

	PR c++/48322
gcc/cp/
	* cp-tree.h (PACK_EXPANSION_EXTRA_ARGS): New.
	* cp-tree.def (EXPR_PACK_EXPANSION): Add an operand for it.
	* pt.c (tsubst_pack_expansion): Set and use it.
	(iterative_hash_template_arg): Hash it.
	(template_args_equal): Compare it.
	(comp_template_args_with_info): Handle nulls.
	* tree.c (cp_walk_subtrees): Walk it.
	* typeck.c (structural_comptypes): Compare it.
	* ptree.c (cxx_print_type): Print it.
libstdc++-v3/
	* include/std/tuple (tuple(_UElements&&...)): Fix SFINAE.

From-SVN: r181547
parent 80ca43a3
2011-11-20 Jason Merrill <jason@redhat.com> 2011-11-20 Jason Merrill <jason@redhat.com>
PR c++/48322
* cp-tree.h (PACK_EXPANSION_EXTRA_ARGS): New.
* cp-tree.def (EXPR_PACK_EXPANSION): Add an operand for it.
* pt.c (tsubst_pack_expansion): Set and use it.
(iterative_hash_template_arg): Hash it.
(template_args_equal): Compare it.
(comp_template_args_with_info): Handle nulls.
* tree.c (cp_walk_subtrees): Walk it.
* typeck.c (structural_comptypes): Compare it.
* ptree.c (cxx_print_type): Print it.
* pt.c (type_unification_real): Set input_location * pt.c (type_unification_real): Set input_location
during default arg instantiation. during default arg instantiation.
......
...@@ -419,7 +419,7 @@ DEFTREECODE (TYPE_PACK_EXPANSION, "type_pack_expansion", tcc_type, 0) ...@@ -419,7 +419,7 @@ DEFTREECODE (TYPE_PACK_EXPANSION, "type_pack_expansion", tcc_type, 0)
EXPR_PACK_EXPANSION plays precisely the same role as TYPE_PACK_EXPANSION, EXPR_PACK_EXPANSION plays precisely the same role as TYPE_PACK_EXPANSION,
but will be used for expressions. */ but will be used for expressions. */
DEFTREECODE (EXPR_PACK_EXPANSION, "expr_pack_expansion", tcc_expression, 2) DEFTREECODE (EXPR_PACK_EXPANSION, "expr_pack_expansion", tcc_expression, 3)
/* Selects the Ith parameter out of an argument pack. This node will /* Selects the Ith parameter out of an argument pack. This node will
be used when instantiating pack expansions; see be used when instantiating pack expansions; see
......
...@@ -2813,7 +2813,14 @@ extern void decl_shadowed_for_var_insert (tree, tree); ...@@ -2813,7 +2813,14 @@ extern void decl_shadowed_for_var_insert (tree, tree);
#define PACK_EXPANSION_PARAMETER_PACKS(NODE) \ #define PACK_EXPANSION_PARAMETER_PACKS(NODE) \
*(TREE_CODE (NODE) == EXPR_PACK_EXPANSION \ *(TREE_CODE (NODE) == EXPR_PACK_EXPANSION \
? &TREE_OPERAND (NODE, 1) \ ? &TREE_OPERAND (NODE, 1) \
: &TREE_CHAIN (TYPE_PACK_EXPANSION_CHECK (NODE))) : &TYPE_MINVAL (TYPE_PACK_EXPANSION_CHECK (NODE)))
/* Any additional template args to be applied when substituting into
the pattern, set by tsubst_pack_expansion for partial instantiations. */
#define PACK_EXPANSION_EXTRA_ARGS(NODE) \
*(TREE_CODE (NODE) == TYPE_PACK_EXPANSION \
? &TYPE_MAXVAL (NODE) \
: &TREE_OPERAND ((NODE), 2))
/* Determine if this is an argument pack. */ /* Determine if this is an argument pack. */
#define ARGUMENT_PACK_P(NODE) \ #define ARGUMENT_PACK_P(NODE) \
......
...@@ -1534,7 +1534,8 @@ iterative_hash_template_arg (tree arg, hashval_t val) ...@@ -1534,7 +1534,8 @@ iterative_hash_template_arg (tree arg, hashval_t val)
case TYPE_PACK_EXPANSION: case TYPE_PACK_EXPANSION:
case EXPR_PACK_EXPANSION: case EXPR_PACK_EXPANSION:
return iterative_hash_template_arg (PACK_EXPANSION_PATTERN (arg), val); val = iterative_hash_template_arg (PACK_EXPANSION_PATTERN (arg), val);
return iterative_hash_template_arg (PACK_EXPANSION_EXTRA_ARGS (arg), val);
case TYPE_ARGUMENT_PACK: case TYPE_ARGUMENT_PACK:
case NONTYPE_ARGUMENT_PACK: case NONTYPE_ARGUMENT_PACK:
...@@ -6902,9 +6903,11 @@ template_args_equal (tree ot, tree nt) ...@@ -6902,9 +6903,11 @@ template_args_equal (tree ot, tree nt)
/* For member templates */ /* For member templates */
return TREE_CODE (ot) == TREE_VEC && comp_template_args (ot, nt); return TREE_CODE (ot) == TREE_VEC && comp_template_args (ot, nt);
else if (PACK_EXPANSION_P (ot)) else if (PACK_EXPANSION_P (ot))
return PACK_EXPANSION_P (nt) return (PACK_EXPANSION_P (nt)
&& template_args_equal (PACK_EXPANSION_PATTERN (ot), && template_args_equal (PACK_EXPANSION_PATTERN (ot),
PACK_EXPANSION_PATTERN (nt)); PACK_EXPANSION_PATTERN (nt))
&& template_args_equal (PACK_EXPANSION_EXTRA_ARGS (ot),
PACK_EXPANSION_EXTRA_ARGS (nt)));
else if (ARGUMENT_PACK_P (ot)) else if (ARGUMENT_PACK_P (ot))
{ {
int i, len; int i, len;
...@@ -6954,6 +6957,12 @@ comp_template_args_with_info (tree oldargs, tree newargs, ...@@ -6954,6 +6957,12 @@ comp_template_args_with_info (tree oldargs, tree newargs,
{ {
int i; int i;
if (oldargs == newargs)
return 1;
if (!oldargs || !newargs)
return 0;
if (TREE_VEC_LENGTH (oldargs) != TREE_VEC_LENGTH (newargs)) if (TREE_VEC_LENGTH (oldargs) != TREE_VEC_LENGTH (newargs))
return 0; return 0;
...@@ -9241,13 +9250,21 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, ...@@ -9241,13 +9250,21 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
tree pattern; tree pattern;
tree pack, packs = NULL_TREE; tree pack, packs = NULL_TREE;
bool unsubstituted_packs = false; bool unsubstituted_packs = false;
bool real_packs = false;
int missing_level = 0;
int i, len = -1; int i, len = -1;
tree result; tree result;
htab_t saved_local_specializations = NULL; htab_t saved_local_specializations = NULL;
int levels;
gcc_assert (PACK_EXPANSION_P (t)); gcc_assert (PACK_EXPANSION_P (t));
pattern = PACK_EXPANSION_PATTERN (t); pattern = PACK_EXPANSION_PATTERN (t);
/* Add in any args remembered from an earlier partial instantiation. */
args = add_to_template_args (PACK_EXPANSION_EXTRA_ARGS (t), args);
levels = TMPL_ARGS_DEPTH (args);
/* Determine the argument packs that will instantiate the parameter /* Determine the argument packs that will instantiate the parameter
packs used in the expansion expression. While we're at it, packs used in the expansion expression. While we're at it,
compute the number of arguments to be expanded and make sure it compute the number of arguments to be expanded and make sure it
...@@ -9258,6 +9275,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, ...@@ -9258,6 +9275,7 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
tree parm_pack = TREE_VALUE (pack); tree parm_pack = TREE_VALUE (pack);
tree arg_pack = NULL_TREE; tree arg_pack = NULL_TREE;
tree orig_arg = NULL_TREE; tree orig_arg = NULL_TREE;
int level = 0;
if (TREE_CODE (parm_pack) == BASES) if (TREE_CODE (parm_pack) == BASES)
{ {
...@@ -9290,10 +9308,9 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, ...@@ -9290,10 +9308,9 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
} }
else else
{ {
int level, idx, levels; int idx;
template_parm_level_and_index (parm_pack, &level, &idx); template_parm_level_and_index (parm_pack, &level, &idx);
levels = TMPL_ARGS_DEPTH (args);
if (level <= levels) if (level <= levels)
arg_pack = TMPL_ARG (args, level, idx); arg_pack = TMPL_ARG (args, level, idx);
} }
...@@ -9344,6 +9361,13 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, ...@@ -9344,6 +9361,13 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
return error_mark_node; return error_mark_node;
} }
if (TREE_VEC_LENGTH (ARGUMENT_PACK_ARGS (arg_pack)) == 1
&& PACK_EXPANSION_P (TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack),
0)))
/* This isn't a real argument pack yet. */;
else
real_packs = true;
/* Keep track of the parameter packs and their corresponding /* Keep track of the parameter packs and their corresponding
argument packs. */ argument packs. */
packs = tree_cons (parm_pack, arg_pack, packs); packs = tree_cons (parm_pack, arg_pack, packs);
...@@ -9351,25 +9375,57 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, ...@@ -9351,25 +9375,57 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
} }
else else
{ {
/* We can't substitute for this parameter pack. */ /* 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. */
unsubstituted_packs = true; unsubstituted_packs = true;
break; if (!missing_level || missing_level > level)
missing_level = level;
} }
} }
/* We cannot expand this expansion expression, because we don't have /* We cannot expand this expansion expression, because we don't have
all of the argument packs we need. Substitute into the pattern all of the argument packs we need. */
and return a PACK_EXPANSION_*. The caller will need to deal with
that. */
if (unsubstituted_packs) if (unsubstituted_packs)
{ {
tree new_pat; if (real_packs)
if (TREE_CODE (t) == EXPR_PACK_EXPANSION) {
new_pat = tsubst_expr (pattern, args, complain, in_decl, /* We got some full packs, but we can't substitute them in until we
/*integral_constant_expression_p=*/false); have values for all the packs. So remember these until then. */
tree save_args;
t = make_pack_expansion (pattern);
/* The call to add_to_template_args above assumes no overlap
between saved args and new args, so prune away any fake
args, i.e. those that satisfied arg_from_parm_pack_p above. */
if (missing_level && levels >= missing_level)
{
gcc_assert (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args)
&& missing_level > 1);
TREE_VEC_LENGTH (args) = missing_level - 1;
save_args = copy_node (args);
TREE_VEC_LENGTH (args) = levels;
}
else
save_args = args;
PACK_EXPANSION_EXTRA_ARGS (t) = save_args;
}
else else
new_pat = tsubst (pattern, args, complain, in_decl); {
return make_pack_expansion (new_pat); /* There were no real arguments, we're just replacing a parameter
pack with another version of itself. Substitute into the
pattern and return a PACK_EXPANSION_*. The caller will need to
deal with that. */
if (TREE_CODE (t) == EXPR_PACK_EXPANSION)
t = tsubst_expr (pattern, args, complain, in_decl,
/*integral_constant_expression_p=*/false);
else
t = tsubst (pattern, args, complain, in_decl);
t = make_pack_expansion (t);
}
return t;
} }
/* We could not find any argument packs that work. */ /* We could not find any argument packs that work. */
......
...@@ -104,6 +104,10 @@ cxx_print_type (FILE *file, tree node, int indent) ...@@ -104,6 +104,10 @@ cxx_print_type (FILE *file, tree node, int indent)
indent + 4); indent + 4);
return; return;
case TYPE_PACK_EXPANSION:
print_node (file, "args", PACK_EXPANSION_EXTRA_ARGS (node), indent + 4);
return;
default: default:
return; return;
} }
......
...@@ -2993,11 +2993,13 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func, ...@@ -2993,11 +2993,13 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
case TYPE_PACK_EXPANSION: case TYPE_PACK_EXPANSION:
WALK_SUBTREE (TREE_TYPE (*tp)); WALK_SUBTREE (TREE_TYPE (*tp));
WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (*tp));
*walk_subtrees_p = 0; *walk_subtrees_p = 0;
break; break;
case EXPR_PACK_EXPANSION: case EXPR_PACK_EXPANSION:
WALK_SUBTREE (TREE_OPERAND (*tp, 0)); WALK_SUBTREE (TREE_OPERAND (*tp, 0));
WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (*tp));
*walk_subtrees_p = 0; *walk_subtrees_p = 0;
break; break;
......
...@@ -1329,8 +1329,10 @@ structural_comptypes (tree t1, tree t2, int strict) ...@@ -1329,8 +1329,10 @@ structural_comptypes (tree t1, tree t2, int strict)
break; break;
case TYPE_PACK_EXPANSION: case TYPE_PACK_EXPANSION:
return same_type_p (PACK_EXPANSION_PATTERN (t1), return (same_type_p (PACK_EXPANSION_PATTERN (t1),
PACK_EXPANSION_PATTERN (t2)); PACK_EXPANSION_PATTERN (t2))
&& comp_template_args (PACK_EXPANSION_EXTRA_ARGS (t1),
PACK_EXPANSION_EXTRA_ARGS (t2)));
case DECLTYPE_TYPE: case DECLTYPE_TYPE:
if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t1) if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t1)
......
2011-11-20 Jason Merrill <jason@redhat.com> 2011-11-20 Jason Merrill <jason@redhat.com>
PR c++/48322
* g++.dg/cpp0x/variadic120.C: New.
* g++.dg/cpp0x/sfinae26.C: Adjust.
* g++.dg/cpp0x/sfinae11.C: Adjust. * g++.dg/cpp0x/sfinae11.C: Adjust.
* g++.dg/cpp0x/sfinae26.C: Adjust. * g++.dg/cpp0x/sfinae26.C: Adjust.
* g++.dg/template/unify11.C: Adjust. * g++.dg/template/unify11.C: Adjust.
......
...@@ -30,9 +30,9 @@ struct is_same<T, T> { ...@@ -30,9 +30,9 @@ struct is_same<T, T> {
template<class... T> template<class... T>
struct S { struct S {
template<class... U, template<class... U,
typename enable_if<and_<is_same<T, U>...>::value>::type*& = enabler typename enable_if<and_<is_same<T, U>...>::value>::type*& = enabler // { dg-error "no type" }
> >
S(U...){} // { dg-error "no type named 'type'" } S(U...){}
}; };
S<bool> s(0); // { dg-error "no match" } S<bool> s(0); // { dg-error "no match" }
// PR c++/48322
// { dg-do compile { target c++11 } }
template <class... T> struct tuple;
template <class T> struct tuple<T> { T t; };
template <class T, class U> struct pair;
template<> struct pair<int,double> { };
template <class... Ts>
struct A
{
template <class... Us,
class V = tuple<pair<Ts,Us>...> >
static void f()
{
V v;
}
};
int main()
{
A<int>::f<double>();
}
2011-11-20 Jason Merrill <jason@redhat.com> 2011-11-20 Jason Merrill <jason@redhat.com>
PR c++/48322
* include/std/tuple (tuple(_UElements&&...)): Fix SFINAE.
* testsuite/20_util/bind/ref_neg.cc: Adjust error markings. * testsuite/20_util/bind/ref_neg.cc: Adjust error markings.
2011-11-20 Jonathan Wakely <jwakely.gcc@gmail.com> 2011-11-20 Jonathan Wakely <jwakely.gcc@gmail.com>
......
...@@ -407,12 +407,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION ...@@ -407,12 +407,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
constexpr tuple(const _Elements&... __elements) constexpr tuple(const _Elements&... __elements)
: _Inherited(__elements...) { } : _Inherited(__elements...) { }
template<typename... _UElements, typename = typename template<typename... _UElements,
enable_if<__and_<integral_constant<bool, sizeof...(_UElements) typename = typename enable_if<sizeof...(_UElements)
== sizeof...(_Elements)>, == sizeof...(_Elements)>::type,
__all_convertible<__conv_types<_UElements...>, typename = typename
__conv_types<_Elements...>> enable_if<__all_convertible<__conv_types<_UElements...>,
>::value>::type> __conv_types<_Elements...> >::value
>::type>
explicit explicit
constexpr tuple(_UElements&&... __elements) constexpr tuple(_UElements&&... __elements)
: _Inherited(std::forward<_UElements>(__elements)...) { } : _Inherited(std::forward<_UElements>(__elements)...) { }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment