aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog17
-rw-r--r--gcc/cp/cp-tree.h7
-rw-r--r--gcc/cp/decl.c9
-rw-r--r--gcc/cp/error.c4
-rw-r--r--gcc/cp/parser.c1
-rw-r--r--gcc/cp/pt.c211
6 files changed, 177 insertions, 72 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 756c8d8..9c64279 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,20 @@
+2014-11-26 Jason Merrill <jason@redhat.com>
+
+ Allow partial specialization of variable templates.
+ * cp-tree.h (TINFO_USED_TEMPLATE_ID): New.
+ * decl.c (duplicate_decls): Copy it.
+ * error.c (dump_decl) [TEMPLATE_ID_EXPR]: Handle variables.
+ * parser.c (cp_parser_decltype_expr): Do call finish_id_expression
+ on template-ids.
+ * pt.c (register_specialization): Remember variable template insts.
+ (instantiate_template_1): Find the matching partial specialization.
+ (check_explicit_specialization): Allow variable partial specialization.
+ (process_partial_specialization): Likewise.
+ (push_template_decl_real): Likewise.
+ (more_specialized_partial_spec): Rename from more_specialized_class.
+ (most_specialized_partial_spec): Rename from most_specialized_class.
+ (get_partial_spec_bindings): Rename from get_class_bindings.
+
2014-11-26 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/63757
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index f1064e9..edd1d5d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -99,6 +99,7 @@ c-common.h, not after.
QUALIFIED_NAME_IS_TEMPLATE (in SCOPE_REF)
DECLTYPE_FOR_INIT_CAPTURE (in DECLTYPE_TYPE)
CONSTRUCTOR_NO_IMPLICIT_ZERO (in CONSTRUCTOR)
+ TINFO_USED_TEMPLATE_ID (in TEMPLATE_INFO)
2: IDENTIFIER_OPNAME_P (in IDENTIFIER_NODE)
ICS_THIS_FLAG (in _CONV)
DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (in VAR_DECL)
@@ -801,6 +802,12 @@ typedef struct qualified_typedef_usage_s qualified_typedef_usage_t;
#define FNDECL_HAS_ACCESS_ERRORS(NODE) \
(TINFO_HAS_ACCESS_ERRORS (DECL_TEMPLATE_INFO (NODE)))
+/* Non-zero if this variable template specialization was specified using a
+ template-id, so it's a partial or full specialization and not a definition
+ of the member template of a particular class specialization. */
+#define TINFO_USED_TEMPLATE_ID(NODE) \
+ (TREE_LANG_FLAG_1 (TEMPLATE_INFO_CHECK (NODE)))
+
struct GTY(()) tree_template_info {
struct tree_common common;
vec<qualified_typedef_usage_t, va_gc> *typedefs_needing_access_checking;
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 4ce4645..455097e 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -2137,7 +2137,14 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
DECL_LANG_SPECIFIC (newdecl)->u.min.u2 =
DECL_LANG_SPECIFIC (olddecl)->u.min.u2;
if (DECL_TEMPLATE_INFO (newdecl))
- new_template_info = DECL_TEMPLATE_INFO (newdecl);
+ {
+ new_template_info = DECL_TEMPLATE_INFO (newdecl);
+ if (DECL_TEMPLATE_INSTANTIATION (olddecl)
+ && DECL_TEMPLATE_SPECIALIZATION (newdecl))
+ /* Remember the presence of explicit specialization args. */
+ TINFO_USED_TEMPLATE_ID (DECL_TEMPLATE_INFO (olddecl))
+ = TINFO_USED_TEMPLATE_ID (new_template_info);
+ }
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
}
/* Only functions have these fields. */
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 7d79771..5dcc149 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1212,7 +1212,9 @@ dump_decl (cxx_pretty_printer *pp, tree t, int flags)
tree args = TREE_OPERAND (t, 1);
if (is_overloaded_fn (name))
- name = DECL_NAME (get_first_fn (name));
+ name = get_first_fn (name);
+ if (DECL_P (name))
+ name = DECL_NAME (name);
dump_decl (pp, name, flags);
pp_cxx_begin_template_argument_list (pp);
if (args == error_mark_node)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index b8e182a..d1cd63f 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -12175,7 +12175,6 @@ cp_parser_decltype_expr (cp_parser *parser,
if (expr
&& expr != error_mark_node
- && TREE_CODE (expr) != TEMPLATE_ID_EXPR
&& TREE_CODE (expr) != TYPE_DECL
&& (TREE_CODE (expr) != BIT_NOT_EXPR
|| !TYPE_P (TREE_OPERAND (expr, 0)))
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 29fb2e1..8e71fcb 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -129,7 +129,7 @@ static int unify (tree, tree, tree, tree, int, bool);
static void add_pending_template (tree);
static tree reopen_tinst_level (struct tinst_level *);
static tree tsubst_initializer_list (tree, tree);
-static tree get_class_bindings (tree, tree, tree, tree);
+static tree get_partial_spec_bindings (tree, tree, tree, tree);
static tree coerce_template_parms (tree, tree, tree, tsubst_flags_t,
bool, bool);
static tree coerce_innermost_template_parms (tree, tree, tree, tsubst_flags_t,
@@ -173,7 +173,7 @@ static tree tsubst_template_arg (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_args (tree, tree, tsubst_flags_t, tree);
static tree tsubst_template_parms (tree, tree, tsubst_flags_t);
static void regenerate_decl_from_template (tree, tree);
-static tree most_specialized_class (tree, tsubst_flags_t);
+static tree most_specialized_partial_spec (tree, tsubst_flags_t);
static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int);
static tree tsubst_arg_types (tree, tree, tree, tsubst_flags_t, tree);
static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree);
@@ -1485,12 +1485,17 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend,
gcc_assert (tmpl && args && spec);
*entry = elt;
*slot = entry;
- if (TREE_CODE (spec) == FUNCTION_DECL && DECL_NAMESPACE_SCOPE_P (spec)
- && PRIMARY_TEMPLATE_P (tmpl)
- && DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (tmpl)) == NULL_TREE)
- /* TMPL is a forward declaration of a template function; keep a list
+ if ((TREE_CODE (spec) == FUNCTION_DECL && DECL_NAMESPACE_SCOPE_P (spec)
+ && PRIMARY_TEMPLATE_P (tmpl)
+ && DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (tmpl)) == NULL_TREE)
+ || variable_template_p (tmpl))
+ /* If TMPL is a forward declaration of a template function, keep a list
of all specializations in case we need to reassign them to a friend
- template later in tsubst_friend_function. */
+ template later in tsubst_friend_function.
+
+ Also keep a list of all variable template instantiations so that
+ process_partial_specialization can check whether a later partial
+ specialization would have used it. */
DECL_TEMPLATE_INSTANTIATIONS (tmpl)
= tree_cons (args, spec, DECL_TEMPLATE_INSTANTIATIONS (tmpl));
}
@@ -2471,13 +2476,24 @@ check_explicit_specialization (tree declarator,
/* This case handles bogus declarations like template <>
template <class T> void f<int>(); */
- if (uses_template_parms (declarator))
+ if (!uses_template_parms (declarator))
+ error ("template-id %qD in declaration of primary template",
+ declarator);
+ else if (variable_template_p (TREE_OPERAND (declarator, 0)))
+ {
+ /* Partial specialization of variable template. */
+ SET_DECL_TEMPLATE_SPECIALIZATION (decl);
+ specialization = 1;
+ goto ok;
+ }
+ else if (cxx_dialect < cxx14)
error ("non-type partial specialization %qD "
"is not allowed", declarator);
else
- error ("template-id %qD in declaration of primary template",
- declarator);
+ error ("non-class, non-variable partial specialization %qD "
+ "is not allowed", declarator);
return decl;
+ ok:;
}
if (ctype && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype))
@@ -2516,9 +2532,10 @@ check_explicit_specialization (tree declarator,
{
tree tmpl = NULL_TREE;
tree targs = NULL_TREE;
+ bool was_template_id = (TREE_CODE (declarator) == TEMPLATE_ID_EXPR);
/* Make sure that the declarator is a TEMPLATE_ID_EXPR. */
- if (TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
+ if (!was_template_id)
{
tree fns;
@@ -2585,7 +2602,7 @@ check_explicit_specialization (tree declarator,
else if (ctype != NULL_TREE
&& (identifier_p (TREE_OPERAND (declarator, 0))))
{
- // Ignore variable templates.
+ // We'll match variable templates in start_decl.
if (VAR_P (decl))
return decl;
@@ -2722,7 +2739,7 @@ check_explicit_specialization (tree declarator,
/* If this is a specialization of a member template of a
template class, we want to return the TEMPLATE_DECL, not
the specialization of it. */
- if (tsk == tsk_template)
+ if (tsk == tsk_template && !was_template_id)
{
tree result = DECL_TEMPLATE_RESULT (tmpl);
SET_DECL_TEMPLATE_SPECIALIZATION (tmpl);
@@ -2747,6 +2764,9 @@ check_explicit_specialization (tree declarator,
/* Set up the DECL_TEMPLATE_INFO for DECL. */
DECL_TEMPLATE_INFO (decl) = build_template_info (tmpl, targs);
+ if (was_template_id)
+ TINFO_USED_TEMPLATE_ID (DECL_TEMPLATE_INFO (decl)) = true;
+
/* Inherit default function arguments from the template
DECL is specializing. */
if (DECL_FUNCTION_TEMPLATE_P (tmpl))
@@ -4087,8 +4107,9 @@ static tree
process_partial_specialization (tree decl)
{
tree type = TREE_TYPE (decl);
- tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
- tree specargs = CLASSTYPE_TI_ARGS (type);
+ tree tinfo = get_template_info (decl);
+ tree maintmpl = TI_TEMPLATE (tinfo);
+ tree specargs = TI_ARGS (tinfo);
tree inner_args = INNERMOST_TEMPLATE_ARGS (specargs);
tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl);
tree inner_parms;
@@ -4173,11 +4194,11 @@ process_partial_specialization (tree decl)
The argument list of the specialization shall not be identical to
the implicit argument list of the primary template. */
- if (comp_template_args
- (inner_args,
- INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (TREE_TYPE
- (maintmpl)))))
- error ("partial specialization %qT does not specialize any template arguments", type);
+ tree main_args
+ = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (maintmpl)));
+ if (comp_template_args (inner_args, INNERMOST_TEMPLATE_ARGS (main_args)))
+ error ("partial specialization %qD does not specialize "
+ "any template arguments", decl);
/* A partial specialization that replaces multiple parameters of the
primary template with a pack expansion is less specialized for those
@@ -4317,7 +4338,8 @@ process_partial_specialization (tree decl)
}
/* We should only get here once. */
- gcc_assert (!COMPLETE_TYPE_P (type));
+ if (TREE_CODE (decl) == TYPE_DECL)
+ gcc_assert (!COMPLETE_TYPE_P (type));
tree tmpl = build_template_decl (decl, current_template_parms,
DECL_MEMBER_TEMPLATE_P (maintmpl));
@@ -4335,15 +4357,21 @@ process_partial_specialization (tree decl)
for (inst = DECL_TEMPLATE_INSTANTIATIONS (maintmpl); inst;
inst = TREE_CHAIN (inst))
{
- tree inst_type = TREE_VALUE (inst);
- if (COMPLETE_TYPE_P (inst_type)
- && CLASSTYPE_IMPLICIT_INSTANTIATION (inst_type))
+ tree instance = TREE_VALUE (inst);
+ if (TYPE_P (instance)
+ ? (COMPLETE_TYPE_P (instance)
+ && CLASSTYPE_IMPLICIT_INSTANTIATION (instance))
+ : DECL_TEMPLATE_INSTANTIATION (instance))
{
- tree spec = most_specialized_class (inst_type, tf_none);
- if (spec && TREE_TYPE (spec) == type)
- permerror (input_location,
- "partial specialization of %qT after instantiation "
- "of %qT", type, inst_type);
+ tree spec = most_specialized_partial_spec (instance, tf_none);
+ if (spec && TREE_VALUE (spec) == tmpl)
+ {
+ tree inst_decl = (DECL_P (instance)
+ ? instance : TYPE_NAME (instance));
+ permerror (input_location,
+ "partial specialization of %qD after instantiation "
+ "of %qD", decl, inst_decl);
+ }
}
}
@@ -4692,9 +4720,13 @@ push_template_decl_real (tree decl, bool is_friend)
return error_mark_node;
/* See if this is a partial specialization. */
- is_partial = (DECL_IMPLICIT_TYPEDEF_P (decl)
- && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
- && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)));
+ is_partial = ((DECL_IMPLICIT_TYPEDEF_P (decl)
+ && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE
+ && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
+ || (TREE_CODE (decl) == VAR_DECL
+ && DECL_LANG_SPECIFIC (decl)
+ && DECL_TEMPLATE_SPECIALIZATION (decl)
+ && TINFO_USED_TEMPLATE_ID (DECL_TEMPLATE_INFO (decl))));
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_FRIEND_P (decl))
is_friend = true;
@@ -9057,7 +9089,7 @@ instantiate_class_template_1 (tree type)
/* Determine what specialization of the original template to
instantiate. */
- t = most_specialized_class (type, tf_warning_or_error);
+ t = most_specialized_partial_spec (type, tf_warning_or_error);
if (t == error_mark_node)
{
TYPE_BEING_DEFINED (type) = 1;
@@ -10519,7 +10551,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
if (new_type == error_mark_node)
RETURN (error_mark_node);
/* If we get a real template back, return it. This can happen in
- the context of most_specialized_class. */
+ the context of most_specialized_partial_spec. */
if (TREE_CODE (new_type) == TEMPLATE_DECL)
return new_type;
@@ -15878,9 +15910,28 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
complain, gen_tmpl, true);
push_nested_class (ctx);
}
+
+ tree pattern = DECL_TEMPLATE_RESULT (gen_tmpl);
+
+ if (VAR_P (pattern))
+ {
+ /* We need to determine if we're using a partial or explicit
+ specialization now, because the type of the variable could be
+ different. */
+ tree tid = lookup_template_variable (gen_tmpl, targ_ptr);
+ tree elt = most_specialized_partial_spec (tid, complain);
+ if (elt == error_mark_node)
+ pattern = error_mark_node;
+ else if (elt)
+ {
+ tmpl = TREE_VALUE (elt);
+ pattern = DECL_TEMPLATE_RESULT (tmpl);
+ targ_ptr = TREE_PURPOSE (elt);
+ }
+ }
+
/* Substitute template parameters to obtain the specialization. */
- fndecl = tsubst (DECL_TEMPLATE_RESULT (gen_tmpl),
- targ_ptr, complain, gen_tmpl);
+ fndecl = tsubst (pattern, targ_ptr, complain, gen_tmpl);
if (DECL_CLASS_SCOPE_P (gen_tmpl))
pop_nested_class ();
pop_from_top_level ();
@@ -18881,8 +18932,8 @@ more_specialized_fn (tree pat1, tree pat2, int len)
/* Determine which of two partial specializations of TMPL is more
specialized.
- PAT1 is a TREE_LIST whose TREE_TYPE is the _TYPE node corresponding
- to the first partial specialization. The TREE_VALUE is the
+ PAT1 is a TREE_LIST whose TREE_VALUE is the TEMPLATE_DECL corresponding
+ to the first partial specialization. The TREE_PURPOSE is the
innermost set of template parameters for the partial
specialization. PAT2 is similar, but for the second template.
@@ -18894,33 +18945,32 @@ more_specialized_fn (tree pat1, tree pat2, int len)
two templates is more specialized. */
static int
-more_specialized_class (tree tmpl, tree pat1, tree pat2)
+more_specialized_partial_spec (tree tmpl, tree pat1, tree pat2)
{
tree targs;
- tree tmpl1, tmpl2;
int winner = 0;
bool any_deductions = false;
- tmpl1 = TREE_TYPE (pat1);
- tmpl2 = TREE_TYPE (pat2);
+ tree tmpl1 = TREE_VALUE (pat1);
+ tree tmpl2 = TREE_VALUE (pat2);
+ tree parms1 = DECL_INNERMOST_TEMPLATE_PARMS (tmpl1);
+ tree parms2 = DECL_INNERMOST_TEMPLATE_PARMS (tmpl2);
+ tree specargs1 = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (tmpl1)));
+ tree specargs2 = TI_ARGS (get_template_info (DECL_TEMPLATE_RESULT (tmpl2)));
/* Just like what happens for functions, if we are ordering between
- different class template specializations, we may encounter dependent
+ different template specializations, we may encounter dependent
types in the arguments, and we need our dependency check functions
to behave correctly. */
++processing_template_decl;
- targs = get_class_bindings (tmpl, TREE_VALUE (pat1),
- CLASSTYPE_TI_ARGS (tmpl1),
- CLASSTYPE_TI_ARGS (tmpl2));
+ targs = get_partial_spec_bindings (tmpl, parms1, specargs1, specargs2);
if (targs)
{
--winner;
any_deductions = true;
}
- targs = get_class_bindings (tmpl, TREE_VALUE (pat2),
- CLASSTYPE_TI_ARGS (tmpl2),
- CLASSTYPE_TI_ARGS (tmpl1));
+ targs = get_partial_spec_bindings (tmpl, parms2, specargs2, specargs1);
if (targs)
{
++winner;
@@ -18928,7 +18978,7 @@ more_specialized_class (tree tmpl, tree pat1, tree pat2)
}
--processing_template_decl;
- /* In the case of a tie where at least one of the class templates
+ /* In the case of a tie where at least one of the templates
has a parameter pack at the end, the template with the most
non-packed parameters wins. */
if (winner == 0
@@ -19014,7 +19064,7 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
is bound to `double'. */
static tree
-get_class_bindings (tree tmpl, tree tparms, tree spec_args, tree args)
+get_partial_spec_bindings (tree tmpl, tree tparms, tree spec_args, tree args)
{
int i, ntparms = TREE_VEC_LENGTH (tparms);
tree deduced_args;
@@ -19197,20 +19247,20 @@ most_general_template (tree decl)
return decl;
}
-/* Return the most specialized of the class template partial
- specializations which can produce TYPE, a specialization of some class
- template. 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.
+/* Return the most specialized of the template partial specializations
+ which can produce TARGET, a specialization of some class or variable
+ template. The value returned is actually a TREE_LIST; the TREE_VALUE is
+ a TEMPLATE_DECL node corresponding to the partial specialization, while
+ the TREE_PURPOSE is the set of template arguments that must be
+ substituted into the template pattern in order to generate TARGET.
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 matching TYPE, then NULL_TREE is
+ partial specializations matching TARGET, then NULL_TREE is
returned, indicating that the primary template should be used. */
static tree
-most_specialized_class (tree type, tsubst_flags_t complain)
+most_specialized_partial_spec (tree target, tsubst_flags_t complain)
{
tree list = NULL_TREE;
tree t;
@@ -19218,10 +19268,29 @@ most_specialized_class (tree type, tsubst_flags_t complain)
int fate;
bool ambiguous_p;
tree outer_args = NULL_TREE;
+ tree tmpl, args;
+
+ if (TYPE_P (target))
+ {
+ tree tinfo = CLASSTYPE_TEMPLATE_INFO (target);
+ tmpl = TI_TEMPLATE (tinfo);
+ args = TI_ARGS (tinfo);
+ }
+ else if (TREE_CODE (target) == TEMPLATE_ID_EXPR)
+ {
+ tmpl = TREE_OPERAND (target, 0);
+ args = TREE_OPERAND (target, 1);
+ }
+ else if (VAR_P (target))
+ {
+ tree tinfo = DECL_TEMPLATE_INFO (target);
+ tmpl = TI_TEMPLATE (tinfo);
+ args = TI_ARGS (tinfo);
+ }
+ else
+ gcc_unreachable ();
- tree tmpl = CLASSTYPE_TI_TEMPLATE (type);
tree main_tmpl = most_general_template (tmpl);
- tree args = CLASSTYPE_TI_ARGS (type);
/* For determining which partial specialization to use, only the
innermost args are interesting. */
@@ -19236,9 +19305,8 @@ most_specialized_class (tree type, tsubst_flags_t complain)
tree partial_spec_args;
tree spec_args;
tree spec_tmpl = TREE_VALUE (t);
- tree orig_parms = DECL_INNERMOST_TEMPLATE_PARMS (spec_tmpl);
- partial_spec_args = CLASSTYPE_TI_ARGS (TREE_TYPE (t));
+ partial_spec_args = TREE_PURPOSE (t);
++processing_template_decl;
@@ -19269,14 +19337,14 @@ most_specialized_class (tree type, tsubst_flags_t complain)
return error_mark_node;
tree parms = DECL_INNERMOST_TEMPLATE_PARMS (spec_tmpl);
- spec_args = get_class_bindings (tmpl, parms,
+ spec_args = get_partial_spec_bindings (tmpl, parms,
partial_spec_args,
args);
if (spec_args)
{
if (outer_args)
spec_args = add_to_template_args (outer_args, spec_args);
- list = tree_cons (spec_args, orig_parms, list);
+ list = tree_cons (spec_args, TREE_VALUE (t), list);
TREE_TYPE (list) = TREE_TYPE (t);
}
}
@@ -19290,7 +19358,7 @@ most_specialized_class (tree type, tsubst_flags_t complain)
t = TREE_CHAIN (t);
for (; t; t = TREE_CHAIN (t))
{
- fate = more_specialized_class (tmpl, champ, t);
+ fate = more_specialized_partial_spec (tmpl, champ, t);
if (fate == 1)
;
else
@@ -19311,7 +19379,7 @@ most_specialized_class (tree type, tsubst_flags_t complain)
if (!ambiguous_p)
for (t = list; t && t != champ; t = TREE_CHAIN (t))
{
- fate = more_specialized_class (tmpl, champ, t);
+ fate = more_specialized_partial_spec (tmpl, champ, t);
if (fate != 1)
{
ambiguous_p = true;
@@ -19325,11 +19393,16 @@ most_specialized_class (tree type, tsubst_flags_t complain)
char *spaces = NULL;
if (!(complain & tf_error))
return error_mark_node;
- error ("ambiguous class template instantiation for %q#T", type);
+ if (TYPE_P (target))
+ error ("ambiguous template instantiation for %q#T", target);
+ else
+ error ("ambiguous template instantiation for %q#D", target);
str = ngettext ("candidate is:", "candidates are:", list_length (list));
for (t = list; t; t = TREE_CHAIN (t))
{
- error ("%s %+#T", spaces ? spaces : str, TREE_TYPE (t));
+ tree subst = build_tree_list (TREE_VALUE (t), TREE_PURPOSE (t));
+ inform (DECL_SOURCE_LOCATION (TREE_VALUE (t)),
+ "%s %#S", spaces ? spaces : str, subst);
spaces = spaces ? spaces : get_spaces (str);
}
free (spaces);