re PR c++/35297 (Compiling error with variadic template with fixed parameter with default type.)
PR c++/35297 PR c++/35477 PR c++/35784 PR c++/36846 PR c++/38276 * pt.c (check_default_tmpl_args): Don't complain about out-of-order parameter packs in the enclosing class or parameter packs after default args. (coerce_template_parms): If we have more than one parameter pack, don't flatten argument packs. (template_args_equal): Handle argument packs. (comp_template_args): Don't flatten argument packs. (check_instantiated_arg): Split out from... (check_instantiated_args): Here. Handle arg packs. (convert_template_argument): Just check that nontype argument packs have the right type. From-SVN: r143166
This commit is contained in:
parent
30af0edbf4
commit
ffaf1e05dd
8 changed files with 247 additions and 81 deletions
|
@ -1,3 +1,22 @@
|
|||
2009-01-06 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/35297
|
||||
PR c++/35477
|
||||
PR c++/35784
|
||||
PR c++/36846
|
||||
PR c++/38276
|
||||
* pt.c (check_default_tmpl_args): Don't complain about
|
||||
out-of-order parameter packs in the enclosing class
|
||||
or parameter packs after default args.
|
||||
(coerce_template_parms): If we have more than one
|
||||
parameter pack, don't flatten argument packs.
|
||||
(template_args_equal): Handle argument packs.
|
||||
(comp_template_args): Don't flatten argument packs.
|
||||
(check_instantiated_arg): Split out from...
|
||||
(check_instantiated_args): Here. Handle arg packs.
|
||||
(convert_template_argument): Just check that nontype argument
|
||||
packs have the right type.
|
||||
|
||||
2009-01-05 Dodji Seketeli <dodji@redhat.com>
|
||||
|
||||
PR c++/38472
|
||||
|
|
213
gcc/cp/pt.c
213
gcc/cp/pt.c
|
@ -3590,7 +3590,8 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary,
|
|||
|
||||
if (TREE_PURPOSE (parm))
|
||||
seen_def_arg_p = 1;
|
||||
else if (seen_def_arg_p)
|
||||
else if (seen_def_arg_p
|
||||
&& !template_parameter_pack_p (TREE_VALUE (parm)))
|
||||
{
|
||||
error ("no default argument for %qD", TREE_VALUE (parm));
|
||||
/* For better subsequent error-recovery, we indicate that
|
||||
|
@ -3601,6 +3602,9 @@ check_default_tmpl_args (tree decl, tree parms, int is_primary,
|
|||
else if (is_primary
|
||||
&& !is_partial
|
||||
&& !is_friend_decl
|
||||
/* Don't complain about an enclosing partial
|
||||
specialization. */
|
||||
&& parm_level == parms
|
||||
&& TREE_CODE (decl) == TYPE_DECL
|
||||
&& i < ntparms - 1
|
||||
&& template_parameter_pack_p (TREE_VALUE (parm)))
|
||||
|
@ -5060,7 +5064,19 @@ convert_template_argument (tree parm,
|
|||
if (invalid_nontype_parm_type_p (t, complain))
|
||||
return error_mark_node;
|
||||
|
||||
if (!uses_template_parms (orig_arg) && !uses_template_parms (t))
|
||||
if (template_parameter_pack_p (parm) && ARGUMENT_PACK_P (orig_arg))
|
||||
{
|
||||
if (same_type_p (t, TREE_TYPE (orig_arg)))
|
||||
val = orig_arg;
|
||||
else
|
||||
{
|
||||
/* Not sure if this is reachable, but it doesn't hurt
|
||||
to be robust. */
|
||||
error ("type mismatch in nontype parameter pack");
|
||||
val = error_mark_node;
|
||||
}
|
||||
}
|
||||
else if (!uses_template_parms (orig_arg) && !uses_template_parms (t))
|
||||
/* We used to call digest_init here. However, digest_init
|
||||
will report errors, which we don't want when complain
|
||||
is zero. More importantly, digest_init will try too
|
||||
|
@ -5233,10 +5249,6 @@ coerce_template_parms (tree parms,
|
|||
parameters. */
|
||||
int variadic_p = 0;
|
||||
|
||||
inner_args
|
||||
= expand_template_argument_pack (INNERMOST_TEMPLATE_ARGS (args));
|
||||
|
||||
nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
|
||||
nparms = TREE_VEC_LENGTH (parms);
|
||||
|
||||
/* Determine if there are any parameter packs. */
|
||||
|
@ -5244,13 +5256,22 @@ coerce_template_parms (tree parms,
|
|||
{
|
||||
tree tparm = TREE_VALUE (TREE_VEC_ELT (parms, parm_idx));
|
||||
if (template_parameter_pack_p (tparm))
|
||||
{
|
||||
variadic_p = 1;
|
||||
break;
|
||||
}
|
||||
++variadic_p;
|
||||
}
|
||||
|
||||
if ((nargs > nparms - variadic_p && !variadic_p)
|
||||
inner_args = INNERMOST_TEMPLATE_ARGS (args);
|
||||
/* If there are 0 or 1 parameter packs, we need to expand any argument
|
||||
packs so that we can deduce a parameter pack from some non-packed args
|
||||
followed by an argument pack, as in variadic85.C. If there are more
|
||||
than that, we need to leave argument packs intact so the arguments are
|
||||
assigned to the right parameter packs. This should only happen when
|
||||
dealing with a nested class inside a partial specialization of a class
|
||||
template, as in variadic92.C. */
|
||||
if (variadic_p <= 1)
|
||||
inner_args = expand_template_argument_pack (inner_args);
|
||||
|
||||
nargs = inner_args ? NUM_TMPL_ARGS (inner_args) : 0;
|
||||
if ((nargs > nparms && !variadic_p)
|
||||
|| (nargs < nparms - variadic_p
|
||||
&& require_all_args
|
||||
&& (!use_default_args
|
||||
|
@ -5297,42 +5318,48 @@ coerce_template_parms (tree parms,
|
|||
}
|
||||
|
||||
/* Calculate the next argument. */
|
||||
if (template_parameter_pack_p (TREE_VALUE (parm)))
|
||||
if (arg_idx < nargs)
|
||||
arg = TREE_VEC_ELT (inner_args, arg_idx);
|
||||
else
|
||||
arg = NULL_TREE;
|
||||
|
||||
if (template_parameter_pack_p (TREE_VALUE (parm))
|
||||
&& !(arg && ARGUMENT_PACK_P (arg)))
|
||||
{
|
||||
/* All remaining arguments will be placed in the
|
||||
template parameter pack PARM. */
|
||||
arg = coerce_template_parameter_pack (parms, parm_idx, args,
|
||||
inner_args, arg_idx,
|
||||
new_args, &lost,
|
||||
in_decl, complain);
|
||||
|
||||
/* All remaining arguments will be placed in the
|
||||
template parameter pack PARM. */
|
||||
arg = coerce_template_parameter_pack (parms, parm_idx, args,
|
||||
inner_args, arg_idx,
|
||||
new_args, &lost,
|
||||
in_decl, complain);
|
||||
|
||||
/* Store this argument. */
|
||||
if (arg == error_mark_node)
|
||||
lost++;
|
||||
TREE_VEC_ELT (new_inner_args, parm_idx) = arg;
|
||||
|
||||
/* We are done with all of the arguments. */
|
||||
arg_idx = nargs;
|
||||
|
||||
/* We are done with all of the arguments. */
|
||||
arg_idx = nargs;
|
||||
|
||||
continue;
|
||||
}
|
||||
else if (arg_idx < nargs)
|
||||
{
|
||||
arg = TREE_VEC_ELT (inner_args, arg_idx);
|
||||
|
||||
if (arg && PACK_EXPANSION_P (arg))
|
||||
else if (arg)
|
||||
{
|
||||
if (PACK_EXPANSION_P (arg))
|
||||
{
|
||||
if (complain & tf_error)
|
||||
{
|
||||
/* FIXME this restriction was removed by N2555; see
|
||||
bug 35722. */
|
||||
/* If ARG is a pack expansion, but PARM is not a
|
||||
template parameter pack (if it were, we would have
|
||||
handled it above), we're trying to expand into a
|
||||
fixed-length argument list. */
|
||||
if (TREE_CODE (arg) == EXPR_PACK_EXPANSION)
|
||||
error ("cannot expand %<%E%> into a fixed-length "
|
||||
sorry ("cannot expand %<%E%> into a fixed-length "
|
||||
"argument list", arg);
|
||||
else
|
||||
error ("cannot expand %<%T%> into a fixed-length "
|
||||
sorry ("cannot expand %<%T%> into a fixed-length "
|
||||
"argument list", arg);
|
||||
}
|
||||
return error_mark_node;
|
||||
|
@ -5389,6 +5416,25 @@ template_args_equal (tree ot, tree nt)
|
|||
return PACK_EXPANSION_P (nt)
|
||||
&& template_args_equal (PACK_EXPANSION_PATTERN (ot),
|
||||
PACK_EXPANSION_PATTERN (nt));
|
||||
else if (ARGUMENT_PACK_P (ot))
|
||||
{
|
||||
int i, len;
|
||||
tree opack, npack;
|
||||
|
||||
if (!ARGUMENT_PACK_P (nt))
|
||||
return 0;
|
||||
|
||||
opack = ARGUMENT_PACK_ARGS (ot);
|
||||
npack = ARGUMENT_PACK_ARGS (nt);
|
||||
len = TREE_VEC_LENGTH (opack);
|
||||
if (TREE_VEC_LENGTH (npack) != len)
|
||||
return 0;
|
||||
for (i = 0; i < len; ++i)
|
||||
if (!template_args_equal (TREE_VEC_ELT (opack, i),
|
||||
TREE_VEC_ELT (npack, i)))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
else if (TYPE_P (nt))
|
||||
return TYPE_P (ot) && same_type_p (ot, nt);
|
||||
else if (TREE_CODE (ot) == TREE_VEC || TYPE_P (ot))
|
||||
|
@ -5405,9 +5451,6 @@ comp_template_args (tree oldargs, tree newargs)
|
|||
{
|
||||
int i;
|
||||
|
||||
oldargs = expand_template_argument_pack (oldargs);
|
||||
newargs = expand_template_argument_pack (newargs);
|
||||
|
||||
if (TREE_VEC_LENGTH (oldargs) != TREE_VEC_LENGTH (newargs))
|
||||
return 0;
|
||||
|
||||
|
@ -11706,6 +11749,66 @@ tsubst_copy_and_build (tree t,
|
|||
make sure they are constants if they are integral or enumerations.
|
||||
Emit an error under control of COMPLAIN, and return TRUE on error. */
|
||||
|
||||
static bool
|
||||
check_instantiated_arg (tree tmpl, tree t, tsubst_flags_t complain)
|
||||
{
|
||||
if (ARGUMENT_PACK_P (t))
|
||||
{
|
||||
tree vec = ARGUMENT_PACK_ARGS (t);
|
||||
int len = TREE_VEC_LENGTH (vec);
|
||||
bool result = false;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < len; ++i)
|
||||
if (check_instantiated_arg (tmpl, TREE_VEC_ELT (vec, i), complain))
|
||||
result = true;
|
||||
return result;
|
||||
}
|
||||
else if (TYPE_P (t))
|
||||
{
|
||||
/* [basic.link]: A name with no linkage (notably, the name
|
||||
of a class or enumeration declared in a local scope)
|
||||
shall not be used to declare an entity with linkage.
|
||||
This implies that names with no linkage cannot be used as
|
||||
template arguments. */
|
||||
tree nt = no_linkage_check (t, /*relaxed_p=*/false);
|
||||
|
||||
if (nt)
|
||||
{
|
||||
/* DR 488 makes use of a type with no linkage cause
|
||||
type deduction to fail. */
|
||||
if (complain & tf_error)
|
||||
{
|
||||
if (TYPE_ANONYMOUS_P (nt))
|
||||
error ("%qT is/uses anonymous type", t);
|
||||
else
|
||||
error ("template argument for %qD uses local type %qT",
|
||||
tmpl, t);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
/* In order to avoid all sorts of complications, we do not
|
||||
allow variably-modified types as template arguments. */
|
||||
else if (variably_modified_type_p (t, NULL_TREE))
|
||||
{
|
||||
if (complain & tf_error)
|
||||
error ("%qT is a variably modified type", t);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/* A non-type argument of integral or enumerated type must be a
|
||||
constant. */
|
||||
else if (TREE_TYPE (t)
|
||||
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t))
|
||||
&& !TREE_CONSTANT (t))
|
||||
{
|
||||
if (complain & tf_error)
|
||||
error ("integral expression %qE is not constant", t);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain)
|
||||
{
|
||||
|
@ -11714,50 +11817,8 @@ check_instantiated_args (tree tmpl, tree args, tsubst_flags_t complain)
|
|||
|
||||
for (ix = 0; ix != len; ix++)
|
||||
{
|
||||
tree t = TREE_VEC_ELT (args, ix);
|
||||
|
||||
if (TYPE_P (t))
|
||||
{
|
||||
/* [basic.link]: A name with no linkage (notably, the name
|
||||
of a class or enumeration declared in a local scope)
|
||||
shall not be used to declare an entity with linkage.
|
||||
This implies that names with no linkage cannot be used as
|
||||
template arguments. */
|
||||
tree nt = no_linkage_check (t, /*relaxed_p=*/false);
|
||||
|
||||
if (nt)
|
||||
{
|
||||
/* DR 488 makes use of a type with no linkage cause
|
||||
type deduction to fail. */
|
||||
if (complain & tf_error)
|
||||
{
|
||||
if (TYPE_ANONYMOUS_P (nt))
|
||||
error ("%qT is/uses anonymous type", t);
|
||||
else
|
||||
error ("template argument for %qD uses local type %qT",
|
||||
tmpl, t);
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
/* In order to avoid all sorts of complications, we do not
|
||||
allow variably-modified types as template arguments. */
|
||||
else if (variably_modified_type_p (t, NULL_TREE))
|
||||
{
|
||||
if (complain & tf_error)
|
||||
error ("%qT is a variably modified type", t);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
/* A non-type argument of integral or enumerated type must be a
|
||||
constant. */
|
||||
else if (TREE_TYPE (t)
|
||||
&& INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t))
|
||||
&& !TREE_CONSTANT (t))
|
||||
{
|
||||
if (complain & tf_error)
|
||||
error ("integral expression %qE is not constant", t);
|
||||
result = true;
|
||||
}
|
||||
if (check_instantiated_arg (tmpl, TREE_VEC_ELT (args, ix), complain))
|
||||
result = true;
|
||||
}
|
||||
if (result && (complain & tf_error))
|
||||
error (" trying to instantiate %qD", tmpl);
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2009-01-07 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* g++.dg/cpp0x/variadic92.C: New test.
|
||||
* g++.dg/cpp0x/variadic93.C: New test.
|
||||
|
||||
2009-01-07 Janis Johnson <janis187@us.ibm.com>
|
||||
|
||||
* lib/target-supports-dg.exp (current_compiler_flags): New.
|
||||
|
|
|
@ -5,4 +5,4 @@ template<typename T1 = unused, typename T2 = unused, typename T3 = unused,
|
|||
struct tuple {};
|
||||
|
||||
template<typename... Args>
|
||||
void foo(tuple<Args...>) { } // { dg-error "cannot expand" }
|
||||
void foo(tuple<Args...>) { } // { dg-bogus "cannot expand" "" { xfail *-*-* } }
|
||||
|
|
|
@ -3,9 +3,9 @@
|
|||
|
||||
template<typename> struct A;
|
||||
|
||||
template<typename... T> struct A<T*...> // { dg-error "cannot expand" }
|
||||
template<typename... T> struct A<T*...> // { dg-bogus "cannot expand" "" { xfail *-*-* } }
|
||||
{
|
||||
struct B;
|
||||
};
|
||||
|
||||
A<void*> a; // { dg-error "incomplete type" }
|
||||
A<void*> a; // { dg-bogus "incomplete type" "" { xfail *-*-* } }
|
||||
|
|
|
@ -3,6 +3,6 @@
|
|||
|
||||
template<typename> struct A;
|
||||
|
||||
template<typename... T> struct A<T...> { }; // { dg-error "cannot expand" }
|
||||
template<typename... T> struct A<T...> { }; // { dg-bogus "cannot expand" "" { xfail *-*-* } }
|
||||
|
||||
A<int> a; // { dg-error "incomplete type" }
|
||||
A<int> a; // { dg-bogus "incomplete type" "" { xfail *-*-* } }
|
||||
|
|
70
gcc/testsuite/g++.dg/cpp0x/variadic92.C
Normal file
70
gcc/testsuite/g++.dg/cpp0x/variadic92.C
Normal file
|
@ -0,0 +1,70 @@
|
|||
// Various tests for variadic templates and partial specialization.
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
// PR c++/36846
|
||||
template<typename A, typename B>
|
||||
struct pair;
|
||||
|
||||
template<typename... T>
|
||||
struct pairs;
|
||||
|
||||
template<typename... AS, typename... BS>
|
||||
struct pairs<pair<AS, BS>...> {
|
||||
struct mismatched_packs {};
|
||||
};
|
||||
|
||||
template class pairs<
|
||||
pair<int, int>,
|
||||
pair<int, int>
|
||||
>;
|
||||
|
||||
template<int A, int B>
|
||||
struct point;
|
||||
|
||||
template<typename... T>
|
||||
struct points;
|
||||
|
||||
template<int... AS, int... BS>
|
||||
struct points<point<AS, BS>...> {
|
||||
struct mismatched_packs {};
|
||||
};
|
||||
|
||||
template class points<
|
||||
point<0, 1>,
|
||||
point<0, 1>
|
||||
>;
|
||||
|
||||
// PR c++/35477
|
||||
template <class...ARGS> struct tuple {};
|
||||
template <class A, class B> struct test {};
|
||||
template <class... ARGS, class B> struct test<B, tuple<ARGS...>>
|
||||
{
|
||||
template <class T> struct inside {};
|
||||
};
|
||||
|
||||
// PR c++/38276
|
||||
template<typename...> struct A;
|
||||
|
||||
template<typename, typename> struct B;
|
||||
|
||||
template<typename... T, typename... U> struct B<A<T...>, A<U...> >
|
||||
{
|
||||
static int i;
|
||||
};
|
||||
|
||||
B<A<>, A<int> > b1;
|
||||
|
||||
B<A<int>, A<> > b2;
|
||||
|
||||
// PR c++/35784
|
||||
template <typename...> struct p;
|
||||
|
||||
template <typename, typename> struct d;
|
||||
|
||||
template <typename... A, typename... B>
|
||||
struct d<p<A...>, p<B...> > { typedef int t; };
|
||||
|
||||
typedef d<p<>, p<int, float> >::t q;
|
||||
typedef d<q, d<p<int>, p<float> >::t> r; // *
|
||||
|
||||
typedef d<d<p<>, p<int, float> >::t, d<p<>, p<> >::t> s;
|
11
gcc/testsuite/g++.dg/cpp0x/variadic93.C
Normal file
11
gcc/testsuite/g++.dg/cpp0x/variadic93.C
Normal file
|
@ -0,0 +1,11 @@
|
|||
// PR c++/35297
|
||||
// { dg-options "-std=c++0x" }
|
||||
|
||||
template <class T=int, class... ARGS>
|
||||
struct test2 {};
|
||||
|
||||
int main()
|
||||
{
|
||||
test2<> a;
|
||||
return 0;
|
||||
}
|
Loading…
Add table
Reference in a new issue