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>
|
||||
|
||||
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
|
||||
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,
|
||||
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
|
||||
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) \
|
||||
*(TREE_CODE (NODE) == EXPR_PACK_EXPANSION \
|
||||
? &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. */
|
||||
#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 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 NONTYPE_ARGUMENT_PACK:
|
||||
|
@ -6902,9 +6903,11 @@ template_args_equal (tree ot, tree nt)
|
|||
/* For member templates */
|
||||
return TREE_CODE (ot) == TREE_VEC && comp_template_args (ot, nt);
|
||||
else if (PACK_EXPANSION_P (ot))
|
||||
return PACK_EXPANSION_P (nt)
|
||||
&& template_args_equal (PACK_EXPANSION_PATTERN (ot),
|
||||
PACK_EXPANSION_PATTERN (nt));
|
||||
return (PACK_EXPANSION_P (nt)
|
||||
&& template_args_equal (PACK_EXPANSION_PATTERN (ot),
|
||||
PACK_EXPANSION_PATTERN (nt))
|
||||
&& template_args_equal (PACK_EXPANSION_EXTRA_ARGS (ot),
|
||||
PACK_EXPANSION_EXTRA_ARGS (nt)));
|
||||
else if (ARGUMENT_PACK_P (ot))
|
||||
{
|
||||
int i, len;
|
||||
|
@ -6954,6 +6957,12 @@ comp_template_args_with_info (tree oldargs, tree newargs,
|
|||
{
|
||||
int i;
|
||||
|
||||
if (oldargs == newargs)
|
||||
return 1;
|
||||
|
||||
if (!oldargs || !newargs)
|
||||
return 0;
|
||||
|
||||
if (TREE_VEC_LENGTH (oldargs) != TREE_VEC_LENGTH (newargs))
|
||||
return 0;
|
||||
|
||||
|
@ -9241,13 +9250,21 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
|
|||
tree pattern;
|
||||
tree pack, packs = NULL_TREE;
|
||||
bool unsubstituted_packs = false;
|
||||
bool real_packs = false;
|
||||
int missing_level = 0;
|
||||
int i, len = -1;
|
||||
tree result;
|
||||
htab_t saved_local_specializations = NULL;
|
||||
int levels;
|
||||
|
||||
gcc_assert (PACK_EXPANSION_P (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
|
||||
packs used in the expansion expression. While we're at 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 arg_pack = NULL_TREE;
|
||||
tree orig_arg = NULL_TREE;
|
||||
int level = 0;
|
||||
|
||||
if (TREE_CODE (parm_pack) == BASES)
|
||||
{
|
||||
|
@ -9290,10 +9308,9 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain,
|
|||
}
|
||||
else
|
||||
{
|
||||
int level, idx, levels;
|
||||
int idx;
|
||||
template_parm_level_and_index (parm_pack, &level, &idx);
|
||||
|
||||
levels = TMPL_ARGS_DEPTH (args);
|
||||
if (level <= levels)
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
argument 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
|
||||
{
|
||||
/* 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;
|
||||
break;
|
||||
if (!missing_level || missing_level > level)
|
||||
missing_level = level;
|
||||
}
|
||||
}
|
||||
|
||||
/* We cannot expand this expansion expression, because we don't have
|
||||
all of the argument packs we need. Substitute into the pattern
|
||||
and return a PACK_EXPANSION_*. The caller will need to deal with
|
||||
that. */
|
||||
all of the argument packs we need. */
|
||||
if (unsubstituted_packs)
|
||||
{
|
||||
tree new_pat;
|
||||
if (TREE_CODE (t) == EXPR_PACK_EXPANSION)
|
||||
new_pat = tsubst_expr (pattern, args, complain, in_decl,
|
||||
/*integral_constant_expression_p=*/false);
|
||||
if (real_packs)
|
||||
{
|
||||
/* We got some full packs, but we can't substitute them in until we
|
||||
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
|
||||
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. */
|
||||
|
|
|
@ -104,6 +104,10 @@ cxx_print_type (FILE *file, tree node, int indent)
|
|||
indent + 4);
|
||||
return;
|
||||
|
||||
case TYPE_PACK_EXPANSION:
|
||||
print_node (file, "args", PACK_EXPANSION_EXTRA_ARGS (node), indent + 4);
|
||||
return;
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -2993,11 +2993,13 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
|
|||
|
||||
case TYPE_PACK_EXPANSION:
|
||||
WALK_SUBTREE (TREE_TYPE (*tp));
|
||||
WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (*tp));
|
||||
*walk_subtrees_p = 0;
|
||||
break;
|
||||
|
||||
case EXPR_PACK_EXPANSION:
|
||||
WALK_SUBTREE (TREE_OPERAND (*tp, 0));
|
||||
WALK_SUBTREE (PACK_EXPANSION_EXTRA_ARGS (*tp));
|
||||
*walk_subtrees_p = 0;
|
||||
break;
|
||||
|
||||
|
|
|
@ -1329,8 +1329,10 @@ structural_comptypes (tree t1, tree t2, int strict)
|
|||
break;
|
||||
|
||||
case TYPE_PACK_EXPANSION:
|
||||
return same_type_p (PACK_EXPANSION_PATTERN (t1),
|
||||
PACK_EXPANSION_PATTERN (t2));
|
||||
return (same_type_p (PACK_EXPANSION_PATTERN (t1),
|
||||
PACK_EXPANSION_PATTERN (t2))
|
||||
&& comp_template_args (PACK_EXPANSION_EXTRA_ARGS (t1),
|
||||
PACK_EXPANSION_EXTRA_ARGS (t2)));
|
||||
|
||||
case DECLTYPE_TYPE:
|
||||
if (DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t1)
|
||||
|
|
|
@ -1,5 +1,9 @@
|
|||
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/sfinae26.C: Adjust.
|
||||
* g++.dg/template/unify11.C: Adjust.
|
||||
|
|
|
@ -30,9 +30,9 @@ struct is_same<T, T> {
|
|||
template<class... T>
|
||||
struct S {
|
||||
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" }
|
||||
|
|
|
@ -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>
|
||||
|
||||
PR c++/48322
|
||||
* include/std/tuple (tuple(_UElements&&...)): Fix SFINAE.
|
||||
|
||||
* testsuite/20_util/bind/ref_neg.cc: Adjust error markings.
|
||||
|
||||
2011-11-20 Jonathan Wakely <jwakely.gcc@gmail.com>
|
||||
|
|
|
@ -407,12 +407,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
constexpr tuple(const _Elements&... __elements)
|
||||
: _Inherited(__elements...) { }
|
||||
|
||||
template<typename... _UElements, typename = typename
|
||||
enable_if<__and_<integral_constant<bool, sizeof...(_UElements)
|
||||
== sizeof...(_Elements)>,
|
||||
__all_convertible<__conv_types<_UElements...>,
|
||||
__conv_types<_Elements...>>
|
||||
>::value>::type>
|
||||
template<typename... _UElements,
|
||||
typename = typename enable_if<sizeof...(_UElements)
|
||||
== sizeof...(_Elements)>::type,
|
||||
typename = typename
|
||||
enable_if<__all_convertible<__conv_types<_UElements...>,
|
||||
__conv_types<_Elements...> >::value
|
||||
>::type>
|
||||
explicit
|
||||
constexpr tuple(_UElements&&... __elements)
|
||||
: _Inherited(std::forward<_UElements>(__elements)...) { }
|
||||
|
|
Loading…
Reference in New Issue