mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
80ca43a314
commit
c67dd25689
|
@ -1,5 +1,16 @@
|
||||||
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)
|
||||||
|
|
||||||
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);
|
||||||
#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) \
|
||||||
|
|
90
gcc/cp/pt.c
90
gcc/cp/pt.c
|
@ -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)
|
||||||
/* 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,
|
||||||
{
|
{
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
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)
|
||||||
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,
|
||||||
|
|
||||||
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)
|
||||||
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)
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
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> {
|
||||||
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" }
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
// 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>();
|
||||||
|
}
|
|
@ -1,5 +1,8 @@
|
||||||
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
|
||||||
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)...) { }
|
||||||
|
|
Loading…
Reference in New Issue