re PR c++/25342 (internal compiler error: in lookup_member, at cp/search.c:1209)
PR c++/25342 * cp-tree.h (DECL_TEMPLATE_SPECIALIZATIONS): Revise documentation. * pt.c (determine_specialization): Use INNERMOST_TEMPLATE_PARMS, not TREE_VALUE. (instantiate_class_template): Simplify. (verify_class_unification): Remove. (unify): Document parameters. Use INNERMOST_TEMPLATE_ARGS to permit multiple levels of template arguments. (more_specialized_class): Simplify. (get_class_bindings): Pass full arguments to unify. Fold verify_class_unification into this function. Return full arguments. (most_specialized_class): Adjust for changes to get_class_bindings. Issue errors here for ambiguity. Return the fully deduced arguments for the most specialized class, in addition to the partial specialization. PR c++/25342 * g++.gd/template/partial4.C: New test. From-SVN: r110466
This commit is contained in:
parent
f51a281b45
commit
916b63c371
5 changed files with 195 additions and 122 deletions
|
@ -1,3 +1,23 @@
|
||||||
|
2006-01-31 Mark Mitchell <mark@codesourcery.com>
|
||||||
|
|
||||||
|
PR c++/25342
|
||||||
|
* cp-tree.h (DECL_TEMPLATE_SPECIALIZATIONS): Revise
|
||||||
|
documentation.
|
||||||
|
* pt.c (determine_specialization): Use INNERMOST_TEMPLATE_PARMS,
|
||||||
|
not TREE_VALUE.
|
||||||
|
(instantiate_class_template): Simplify.
|
||||||
|
(verify_class_unification): Remove.
|
||||||
|
(unify): Document parameters. Use INNERMOST_TEMPLATE_ARGS to
|
||||||
|
permit multiple levels of template arguments.
|
||||||
|
(more_specialized_class): Simplify.
|
||||||
|
(get_class_bindings): Pass full arguments to unify. Fold
|
||||||
|
verify_class_unification into this function. Return full
|
||||||
|
arguments.
|
||||||
|
(most_specialized_class): Adjust for changes to
|
||||||
|
get_class_bindings. Issue errors here for ambiguity. Return the
|
||||||
|
fully deduced arguments for the most specialized class, in
|
||||||
|
addition to the partial specialization.
|
||||||
|
|
||||||
2006-01-31 Ben Elliston <bje@au.ibm.com>
|
2006-01-31 Ben Elliston <bje@au.ibm.com>
|
||||||
|
|
||||||
* mangle.c: Comment fix.
|
* mangle.c: Comment fix.
|
||||||
|
|
|
@ -2729,12 +2729,13 @@ extern void decl_shadowed_for_var_insert (tree, tree);
|
||||||
|
|
||||||
For a class template, this list contains the partial
|
For a class template, this list contains the partial
|
||||||
specializations of this template. (Full specializations are not
|
specializations of this template. (Full specializations are not
|
||||||
recorded on this list.) The TREE_PURPOSE holds the innermost
|
recorded on this list.) The TREE_PURPOSE holds the arguments used
|
||||||
arguments used in the partial specialization (e.g., for `template
|
in the partial specialization (e.g., for `template <class T> struct
|
||||||
<class T> struct S<T*, int>' this will be `T*'.) The TREE_VALUE
|
S<T*, int>' this will be `T*'.) The arguments will also include
|
||||||
holds the innermost template parameters for the specialization
|
any outer template arguments. The TREE_VALUE holds the innermost
|
||||||
(e.g., `T' in the example above.) The TREE_TYPE is the _TYPE node
|
template parameters for the specialization (e.g., `T' in the
|
||||||
for the partial specialization.
|
example above.) The TREE_TYPE is the _TYPE node for the partial
|
||||||
|
specialization.
|
||||||
|
|
||||||
This list is not used for static variable templates. */
|
This list is not used for static variable templates. */
|
||||||
#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE (NODE)
|
#define DECL_TEMPLATE_SPECIALIZATIONS(NODE) DECL_SIZE (NODE)
|
||||||
|
|
263
gcc/cp/pt.c
263
gcc/cp/pt.c
|
@ -144,7 +144,6 @@ static tree process_partial_specialization (tree);
|
||||||
static void set_current_access_from_decl (tree);
|
static void set_current_access_from_decl (tree);
|
||||||
static void check_default_tmpl_args (tree, tree, int, int);
|
static void check_default_tmpl_args (tree, tree, int, int);
|
||||||
static tree get_template_base (tree, tree, tree, tree);
|
static tree get_template_base (tree, tree, tree, tree);
|
||||||
static int verify_class_unification (tree, tree, tree);
|
|
||||||
static tree try_class_unification (tree, tree, tree, tree);
|
static tree try_class_unification (tree, tree, tree, tree);
|
||||||
static int coerce_template_template_parms (tree, tree, tsubst_flags_t,
|
static int coerce_template_template_parms (tree, tree, tsubst_flags_t,
|
||||||
tree, tree);
|
tree, tree);
|
||||||
|
@ -1450,7 +1449,8 @@ determine_specialization (tree template_id,
|
||||||
if (current_binding_level->kind == sk_template_parms
|
if (current_binding_level->kind == sk_template_parms
|
||||||
&& !current_binding_level->explicit_spec_p
|
&& !current_binding_level->explicit_spec_p
|
||||||
&& (TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (fn))
|
&& (TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (fn))
|
||||||
!= TREE_VEC_LENGTH (TREE_VALUE (current_template_parms))))
|
!= TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS
|
||||||
|
(current_template_parms))))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* See whether this function might be a specialization of this
|
/* See whether this function might be a specialization of this
|
||||||
|
@ -2756,7 +2756,7 @@ process_partial_specialization (tree decl)
|
||||||
return decl;
|
return decl;
|
||||||
|
|
||||||
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)
|
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)
|
||||||
= tree_cons (inner_args, inner_parms,
|
= tree_cons (specargs, inner_parms,
|
||||||
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
|
DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
|
||||||
TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
|
TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
|
||||||
return decl;
|
return decl;
|
||||||
|
@ -5493,34 +5493,34 @@ instantiate_class_template (tree type)
|
||||||
template = most_general_template (CLASSTYPE_TI_TEMPLATE (type));
|
template = most_general_template (CLASSTYPE_TI_TEMPLATE (type));
|
||||||
gcc_assert (TREE_CODE (template) == TEMPLATE_DECL);
|
gcc_assert (TREE_CODE (template) == TEMPLATE_DECL);
|
||||||
|
|
||||||
/* Figure out which arguments are being used to do the
|
|
||||||
instantiation. */
|
|
||||||
args = CLASSTYPE_TI_ARGS (type);
|
|
||||||
|
|
||||||
/* Determine what specialization of the original template to
|
/* Determine what specialization of the original template to
|
||||||
instantiate. */
|
instantiate. */
|
||||||
t = most_specialized_class (template, args);
|
t = most_specialized_class (type, template);
|
||||||
if (t == error_mark_node)
|
if (t == error_mark_node)
|
||||||
{
|
{
|
||||||
const char *str = "candidates are:";
|
|
||||||
error ("ambiguous class template instantiation for %q#T", type);
|
|
||||||
for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t;
|
|
||||||
t = TREE_CHAIN (t))
|
|
||||||
{
|
|
||||||
if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args))
|
|
||||||
{
|
|
||||||
error ("%s %+#T", str, TREE_TYPE (t));
|
|
||||||
str = " ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TYPE_BEING_DEFINED (type) = 1;
|
TYPE_BEING_DEFINED (type) = 1;
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
|
else if (t)
|
||||||
|
{
|
||||||
|
/* This TYPE is actually an instantiation of a partial
|
||||||
|
specialization. We replace the innermost set of ARGS with
|
||||||
|
the arguments appropriate for substitution. For example,
|
||||||
|
given:
|
||||||
|
|
||||||
|
template <class T> struct S {};
|
||||||
|
template <class T> struct S<T*> {};
|
||||||
|
|
||||||
if (t)
|
and supposing that we are instantiating S<int*>, ARGS will
|
||||||
pattern = TREE_TYPE (t);
|
presently be {int*} -- but we need {int}. */
|
||||||
|
pattern = TREE_TYPE (t);
|
||||||
|
args = TREE_PURPOSE (t);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
pattern = TREE_TYPE (template);
|
{
|
||||||
|
pattern = TREE_TYPE (template);
|
||||||
|
args = CLASSTYPE_TI_ARGS (type);
|
||||||
|
}
|
||||||
|
|
||||||
/* If the template we're instantiating is incomplete, then clearly
|
/* If the template we're instantiating is incomplete, then clearly
|
||||||
there's nothing we can do. */
|
there's nothing we can do. */
|
||||||
|
@ -5541,34 +5541,6 @@ instantiate_class_template (tree type)
|
||||||
|
|
||||||
push_to_top_level ();
|
push_to_top_level ();
|
||||||
|
|
||||||
if (t)
|
|
||||||
{
|
|
||||||
/* This TYPE is actually an instantiation of a partial
|
|
||||||
specialization. We replace the innermost set of ARGS with
|
|
||||||
the arguments appropriate for substitution. For example,
|
|
||||||
given:
|
|
||||||
|
|
||||||
template <class T> struct S {};
|
|
||||||
template <class T> struct S<T*> {};
|
|
||||||
|
|
||||||
and supposing that we are instantiating S<int*>, ARGS will
|
|
||||||
present be {int*} but we need {int}. */
|
|
||||||
tree inner_args
|
|
||||||
= get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t),
|
|
||||||
args);
|
|
||||||
|
|
||||||
/* If there were multiple levels in ARGS, replacing the
|
|
||||||
innermost level would alter CLASSTYPE_TI_ARGS, which we don't
|
|
||||||
want, so we make a copy first. */
|
|
||||||
if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
|
|
||||||
{
|
|
||||||
args = copy_node (args);
|
|
||||||
SET_TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args), inner_args);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
args = inner_args;
|
|
||||||
}
|
|
||||||
|
|
||||||
SET_CLASSTYPE_INTERFACE_UNKNOWN (type);
|
SET_CLASSTYPE_INTERFACE_UNKNOWN (type);
|
||||||
|
|
||||||
/* Set the input location to the template definition. This is needed
|
/* Set the input location to the template definition. This is needed
|
||||||
|
@ -9734,34 +9706,6 @@ try_one_overload (tree tparms,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Verify that nondeduce template argument agrees with the type
|
|
||||||
obtained from argument deduction. Return nonzero if the
|
|
||||||
verification fails.
|
|
||||||
|
|
||||||
For example:
|
|
||||||
|
|
||||||
struct A { typedef int X; };
|
|
||||||
template <class T, class U> struct C {};
|
|
||||||
template <class T> struct C<T, typename T::X> {};
|
|
||||||
|
|
||||||
Then with the instantiation `C<A, int>', we can deduce that
|
|
||||||
`T' is `A' but unify () does not check whether `typename T::X'
|
|
||||||
is `int'. This function ensure that they agree.
|
|
||||||
|
|
||||||
TARGS, PARMS are the same as the arguments of unify.
|
|
||||||
ARGS contains template arguments from all levels. */
|
|
||||||
|
|
||||||
static int
|
|
||||||
verify_class_unification (tree targs, tree parms, tree args)
|
|
||||||
{
|
|
||||||
parms = tsubst (parms, add_outermost_template_args (args, targs),
|
|
||||||
tf_none, NULL_TREE);
|
|
||||||
if (parms == error_mark_node)
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
return !comp_template_args (parms, INNERMOST_TEMPLATE_ARGS (args));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* PARM is a template class (perhaps with unbound template
|
/* PARM is a template class (perhaps with unbound template
|
||||||
parameters). ARG is a fully instantiated type. If ARG can be
|
parameters). ARG is a fully instantiated type. If ARG can be
|
||||||
bound to PARM, return ARG, otherwise return NULL_TREE. TPARMS and
|
bound to PARM, return ARG, otherwise return NULL_TREE. TPARMS and
|
||||||
|
@ -9924,9 +9868,18 @@ check_cv_quals_for_unify (int strict, tree arg, tree parm)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Takes parameters as for type_unification. Returns 0 if the
|
/* Deduce the value of template parameters. TPARMS is the (innermost)
|
||||||
type deduction succeeds, 1 otherwise. The parameter STRICT is a
|
set of template parameters to a template. TARGS is the bindings
|
||||||
bitwise or of the following flags:
|
for those template parameters, as determined thus far; TARGS may
|
||||||
|
include template arguments for outer levels of template parameters
|
||||||
|
as well. PARM is a parameter to a template function, or a
|
||||||
|
subcomponent of that parameter; ARG is the corresponding argument.
|
||||||
|
This function attempts to match PARM with ARG in a manner
|
||||||
|
consistent with the existing assignments in TARGS. If more values
|
||||||
|
are deduced, then TARGS is updated.
|
||||||
|
|
||||||
|
Returns 0 if the type deduction succeeds, 1 otherwise. The
|
||||||
|
parameter STRICT is a bitwise or of the following flags:
|
||||||
|
|
||||||
UNIFY_ALLOW_NONE:
|
UNIFY_ALLOW_NONE:
|
||||||
Require an exact match between PARM and ARG.
|
Require an exact match between PARM and ARG.
|
||||||
|
@ -10031,7 +9984,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
|
||||||
return (TREE_CODE (arg) == TREE_CODE (parm)
|
return (TREE_CODE (arg) == TREE_CODE (parm)
|
||||||
&& same_type_p (parm, arg)) ? 0 : 1;
|
&& same_type_p (parm, arg)) ? 0 : 1;
|
||||||
idx = TEMPLATE_TYPE_IDX (parm);
|
idx = TEMPLATE_TYPE_IDX (parm);
|
||||||
targ = TREE_VEC_ELT (targs, idx);
|
targ = TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx);
|
||||||
tparm = TREE_VALUE (TREE_VEC_ELT (tparms, idx));
|
tparm = TREE_VALUE (TREE_VEC_ELT (tparms, idx));
|
||||||
|
|
||||||
/* Check for mixed types and values. */
|
/* Check for mixed types and values. */
|
||||||
|
@ -10132,7 +10085,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
TREE_VEC_ELT (targs, idx) = arg;
|
TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case TEMPLATE_PARM_INDEX:
|
case TEMPLATE_PARM_INDEX:
|
||||||
|
@ -10146,7 +10099,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
|
||||||
&& cp_tree_equal (parm, arg));
|
&& cp_tree_equal (parm, arg));
|
||||||
|
|
||||||
idx = TEMPLATE_PARM_IDX (parm);
|
idx = TEMPLATE_PARM_IDX (parm);
|
||||||
targ = TREE_VEC_ELT (targs, idx);
|
targ = TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx);
|
||||||
|
|
||||||
if (targ)
|
if (targ)
|
||||||
return !cp_tree_equal (targ, arg);
|
return !cp_tree_equal (targ, arg);
|
||||||
|
@ -10180,7 +10133,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
|
||||||
else
|
else
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
TREE_VEC_ELT (targs, idx) = arg;
|
TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
case PTRMEM_CST:
|
case PTRMEM_CST:
|
||||||
|
@ -10705,33 +10658,44 @@ more_specialized_fn (tree pat1, tree pat2, int len)
|
||||||
return (better1 > 0) - (better2 > 0);
|
return (better1 > 0) - (better2 > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Given two class template specialization list nodes PAT1 and PAT2, return:
|
/* Determine which of two partial specializations is more specialized.
|
||||||
|
|
||||||
1 if PAT1 is more specialized than PAT2 as described in [temp.class.order].
|
PAT1 is a TREE_LIST whose TREE_TYPE is the _TYPE node corresponding
|
||||||
-1 if PAT2 is more specialized than PAT1.
|
to the first partial specialization. The TREE_VALUE is the
|
||||||
0 if neither is more specialized.
|
innermost set of template parameters for the partial
|
||||||
|
specialization. PAT2 is similar, but for the second template.
|
||||||
|
|
||||||
FULL_ARGS is the full set of template arguments that triggers this
|
Return 1 if the first partial specialization is more specialized;
|
||||||
partial ordering. */
|
-1 if the second is more specialized; 0 if neither is more
|
||||||
|
specialized.
|
||||||
|
|
||||||
|
See [temp.class.order] for information about determining which of
|
||||||
|
two templates is more specialized. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
more_specialized_class (tree pat1, tree pat2, tree full_args)
|
more_specialized_class (tree pat1, tree pat2)
|
||||||
{
|
{
|
||||||
tree targs;
|
tree targs;
|
||||||
|
tree tmpl1, tmpl2;
|
||||||
int winner = 0;
|
int winner = 0;
|
||||||
|
|
||||||
|
tmpl1 = TREE_TYPE (pat1);
|
||||||
|
tmpl2 = TREE_TYPE (pat2);
|
||||||
|
|
||||||
/* Just like what happens for functions, if we are ordering between
|
/* Just like what happens for functions, if we are ordering between
|
||||||
different class template specializations, we may encounter dependent
|
different class template specializations, we may encounter dependent
|
||||||
types in the arguments, and we need our dependency check functions
|
types in the arguments, and we need our dependency check functions
|
||||||
to behave correctly. */
|
to behave correctly. */
|
||||||
++processing_template_decl;
|
++processing_template_decl;
|
||||||
targs = get_class_bindings (TREE_VALUE (pat1), TREE_PURPOSE (pat1),
|
targs = get_class_bindings (TREE_VALUE (pat1),
|
||||||
add_outermost_template_args (full_args, TREE_PURPOSE (pat2)));
|
CLASSTYPE_TI_ARGS (tmpl1),
|
||||||
|
CLASSTYPE_TI_ARGS (tmpl2));
|
||||||
if (targs)
|
if (targs)
|
||||||
--winner;
|
--winner;
|
||||||
|
|
||||||
targs = get_class_bindings (TREE_VALUE (pat2), TREE_PURPOSE (pat2),
|
targs = get_class_bindings (TREE_VALUE (pat2),
|
||||||
add_outermost_template_args (full_args, TREE_PURPOSE (pat1)));
|
CLASSTYPE_TI_ARGS (tmpl2),
|
||||||
|
CLASSTYPE_TI_ARGS (tmpl1));
|
||||||
if (targs)
|
if (targs)
|
||||||
++winner;
|
++winner;
|
||||||
--processing_template_decl;
|
--processing_template_decl;
|
||||||
|
@ -10806,28 +10770,59 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
|
||||||
template <class T> struct S<T*, int> {};
|
template <class T> struct S<T*, int> {};
|
||||||
|
|
||||||
Then, suppose we want to get `S<double*, int>'. The TPARMS will be
|
Then, suppose we want to get `S<double*, int>'. The TPARMS will be
|
||||||
{T}, the PARMS will be {T*, int} and the ARGS will be {double*,
|
{T}, the SPEC_ARGS will be {T*, int} and the ARGS will be {double*,
|
||||||
int}. The resulting vector will be {double}, indicating that `T'
|
int}. The resulting vector will be {double}, indicating that `T'
|
||||||
is bound to `double'. */
|
is bound to `double'. */
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
get_class_bindings (tree tparms, tree parms, tree args)
|
get_class_bindings (tree tparms, tree spec_args, tree args)
|
||||||
{
|
{
|
||||||
int i, ntparms = TREE_VEC_LENGTH (tparms);
|
int i, ntparms = TREE_VEC_LENGTH (tparms);
|
||||||
tree vec = make_tree_vec (ntparms);
|
tree deduced_args;
|
||||||
|
tree innermost_deduced_args;
|
||||||
|
|
||||||
if (unify (tparms, vec, parms, INNERMOST_TEMPLATE_ARGS (args),
|
innermost_deduced_args = make_tree_vec (ntparms);
|
||||||
|
if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (args))
|
||||||
|
{
|
||||||
|
deduced_args = copy_node (args);
|
||||||
|
SET_TMPL_ARGS_LEVEL (deduced_args,
|
||||||
|
TMPL_ARGS_DEPTH (deduced_args),
|
||||||
|
innermost_deduced_args);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
deduced_args = innermost_deduced_args;
|
||||||
|
|
||||||
|
if (unify (tparms, deduced_args,
|
||||||
|
INNERMOST_TEMPLATE_ARGS (spec_args),
|
||||||
|
INNERMOST_TEMPLATE_ARGS (args),
|
||||||
UNIFY_ALLOW_NONE))
|
UNIFY_ALLOW_NONE))
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
|
|
||||||
for (i = 0; i < ntparms; ++i)
|
for (i = 0; i < ntparms; ++i)
|
||||||
if (! TREE_VEC_ELT (vec, i))
|
if (! TREE_VEC_ELT (innermost_deduced_args, i))
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
|
|
||||||
if (verify_class_unification (vec, parms, args))
|
/* Verify that nondeduced template arguments agree with the type
|
||||||
|
obtained from argument deduction.
|
||||||
|
|
||||||
|
For example:
|
||||||
|
|
||||||
|
struct A { typedef int X; };
|
||||||
|
template <class T, class U> struct C {};
|
||||||
|
template <class T> struct C<T, typename T::X> {};
|
||||||
|
|
||||||
|
Then with the instantiation `C<A, int>', we can deduce that
|
||||||
|
`T' is `A' but unify () does not check whether `typename T::X'
|
||||||
|
is `int'. */
|
||||||
|
spec_args = tsubst (spec_args, deduced_args, tf_none, NULL_TREE);
|
||||||
|
if (spec_args == error_mark_node
|
||||||
|
/* We only need to check the innermost arguments; the other
|
||||||
|
arguments will always agree. */
|
||||||
|
|| !comp_template_args (INNERMOST_TEMPLATE_ARGS (spec_args),
|
||||||
|
INNERMOST_TEMPLATE_ARGS (args)))
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
|
|
||||||
return vec;
|
return deduced_args;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TEMPLATES is a TREE_LIST. Each TREE_VALUE is a TEMPLATE_DECL.
|
/* TEMPLATES is a TREE_LIST. Each TREE_VALUE is a TEMPLATE_DECL.
|
||||||
|
@ -10957,26 +10952,42 @@ most_general_template (tree decl)
|
||||||
return decl;
|
return decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return the most specialized of the class template specializations
|
/* Return the most specialized of the class template partial
|
||||||
of TMPL which can produce an instantiation matching ARGS, or
|
specializations of TMPL which can produce TYPE, a specialization of
|
||||||
error_mark_node if the choice is ambiguous. */
|
TMPL. The value returned is actually a TREE_LIST; the TREE_TYPE is
|
||||||
|
a _TYPE node corresponding to the partial specialization, while the
|
||||||
|
TREE_PURPOSE is the set of template arguments that must be
|
||||||
|
substituted into the TREE_TYPE in order to generate TYPE.
|
||||||
|
|
||||||
|
If the choice of partial specialization is ambiguous, a diagnostic
|
||||||
|
is issued, and the error_mark_node is returned. If there are no
|
||||||
|
partial specializations of TMPL matching TYPE, then NULL_TREE is
|
||||||
|
returned. */
|
||||||
|
|
||||||
static tree
|
static tree
|
||||||
most_specialized_class (tree tmpl, tree args)
|
most_specialized_class (tree type, tree tmpl)
|
||||||
{
|
{
|
||||||
tree list = NULL_TREE;
|
tree list = NULL_TREE;
|
||||||
tree t;
|
tree t;
|
||||||
tree champ;
|
tree champ;
|
||||||
int fate;
|
int fate;
|
||||||
|
bool ambiguous_p;
|
||||||
|
tree args;
|
||||||
|
|
||||||
tmpl = most_general_template (tmpl);
|
tmpl = most_general_template (tmpl);
|
||||||
|
args = CLASSTYPE_TI_ARGS (type);
|
||||||
for (t = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); t; t = TREE_CHAIN (t))
|
for (t = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); t; t = TREE_CHAIN (t))
|
||||||
{
|
{
|
||||||
tree spec_args
|
tree partial_spec_args;
|
||||||
= get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args);
|
tree spec_args;
|
||||||
|
|
||||||
|
partial_spec_args = CLASSTYPE_TI_ARGS (TREE_TYPE (t));
|
||||||
|
spec_args = get_class_bindings (TREE_VALUE (t),
|
||||||
|
partial_spec_args,
|
||||||
|
args);
|
||||||
if (spec_args)
|
if (spec_args)
|
||||||
{
|
{
|
||||||
list = tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list);
|
list = tree_cons (spec_args, TREE_VALUE (t), list);
|
||||||
TREE_TYPE (list) = TREE_TYPE (t);
|
TREE_TYPE (list) = TREE_TYPE (t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10984,12 +10995,13 @@ most_specialized_class (tree tmpl, tree args)
|
||||||
if (! list)
|
if (! list)
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
|
|
||||||
|
ambiguous_p = false;
|
||||||
t = list;
|
t = list;
|
||||||
champ = t;
|
champ = t;
|
||||||
t = TREE_CHAIN (t);
|
t = TREE_CHAIN (t);
|
||||||
for (; t; t = TREE_CHAIN (t))
|
for (; t; t = TREE_CHAIN (t))
|
||||||
{
|
{
|
||||||
fate = more_specialized_class (champ, t, args);
|
fate = more_specialized_class (champ, t);
|
||||||
if (fate == 1)
|
if (fate == 1)
|
||||||
;
|
;
|
||||||
else
|
else
|
||||||
|
@ -10998,17 +11010,36 @@ most_specialized_class (tree tmpl, tree args)
|
||||||
{
|
{
|
||||||
t = TREE_CHAIN (t);
|
t = TREE_CHAIN (t);
|
||||||
if (! t)
|
if (! t)
|
||||||
return error_mark_node;
|
{
|
||||||
|
ambiguous_p = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
champ = t;
|
champ = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (t = list; t && t != champ; t = TREE_CHAIN (t))
|
if (!ambiguous_p)
|
||||||
|
for (t = list; t && t != champ; t = TREE_CHAIN (t))
|
||||||
|
{
|
||||||
|
fate = more_specialized_class (champ, t);
|
||||||
|
if (fate != 1)
|
||||||
|
{
|
||||||
|
ambiguous_p = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ambiguous_p)
|
||||||
{
|
{
|
||||||
fate = more_specialized_class (champ, t, args);
|
const char *str = "candidates are:";
|
||||||
if (fate != 1)
|
error ("ambiguous class template instantiation for %q#T", type);
|
||||||
return error_mark_node;
|
for (t = list; t; t = TREE_CHAIN (t))
|
||||||
|
{
|
||||||
|
error ("%s %+#T", str, TREE_TYPE (t));
|
||||||
|
str = " ";
|
||||||
|
}
|
||||||
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
return champ;
|
return champ;
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
2006-01-31 Mark Mitchell <mark@codesourcery.com>
|
||||||
|
|
||||||
|
PR c++/25342
|
||||||
|
* g++.gd/template/partial4.C: New test.
|
||||||
|
|
||||||
2006-01-31 Andrew Pinski <pinskia@physics.uc.edu>
|
2006-01-31 Andrew Pinski <pinskia@physics.uc.edu>
|
||||||
|
|
||||||
PR middle-end/26001
|
PR middle-end/26001
|
||||||
|
|
16
gcc/testsuite/g++.dg/template/partial4.C
Normal file
16
gcc/testsuite/g++.dg/template/partial4.C
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// PR c++/25342
|
||||||
|
|
||||||
|
template < typename eval >
|
||||||
|
struct tpl_seq_search {
|
||||||
|
typedef typename eval::enum_type Enum;
|
||||||
|
template < Enum first, Enum last >
|
||||||
|
struct range {
|
||||||
|
};
|
||||||
|
template < Enum val >
|
||||||
|
struct range<val,val> {
|
||||||
|
};
|
||||||
|
};
|
||||||
|
struct xxx {
|
||||||
|
typedef int enum_type;
|
||||||
|
tpl_seq_search<xxx>::range<0, 1> a;
|
||||||
|
};
|
Loading…
Add table
Reference in a new issue