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:
Jason Merrill 2009-01-07 15:43:01 -05:00 committed by Jason Merrill
parent 30af0edbf4
commit ffaf1e05dd
8 changed files with 247 additions and 81 deletions

View file

@ -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

View file

@ -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);

View file

@ -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.

View file

@ -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 *-*-* } }

View file

@ -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 *-*-* } }

View file

@ -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 *-*-* } }

View 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;

View 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;
}