/* Handle parameterized types (templates) for GNU C++. Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. Written by Ken Raeburn (raeburn@cygnus.com) while at Watchmaker Computing. Rewritten by Jason Merrill (jason@cygnus.com). This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* Known bugs or deficiencies include: all methods must be provided in header files; can't use a source file that contains only the method templates and "just win". */ #include "config.h" #include "system.h" #include "coretypes.h" #include "tm.h" #include "obstack.h" #include "tree.h" #include "pointer-set.h" #include "flags.h" #include "cp-tree.h" #include "tree-inline.h" #include "decl.h" #include "output.h" #include "except.h" #include "toplev.h" #include "rtl.h" #include "timevar.h" #include "tree-iterator.h" /* The type of functions taking a tree, and some additional data, and returning an int. */ typedef int (*tree_fn_t) (tree, void*); /* The PENDING_TEMPLATES is a TREE_LIST of templates whose instantiations have been deferred, either because their definitions were not yet available, or because we were putting off doing the work. The TREE_PURPOSE of each entry is either a DECL (for a function or static data member), or a TYPE (for a class) indicating what we are hoping to instantiate. The TREE_VALUE is not used. */ static GTY(()) tree pending_templates; static GTY(()) tree last_pending_template; int processing_template_parmlist; static int template_header_count; static GTY(()) tree saved_trees; static GTY(()) varray_type inline_parm_levels; static size_t inline_parm_levels_used; static GTY(()) tree current_tinst_level; static GTY(()) tree saved_access_scope; /* Live only within one (recursive) call to tsubst_expr. We use this to pass the statement expression node from the STMT_EXPR to the EXPR_STMT that is its result. */ static tree cur_stmt_expr; /* A map from local variable declarations in the body of the template presently being instantiated to the corresponding instantiated local variables. */ static htab_t local_specializations; #define UNIFY_ALLOW_NONE 0 #define UNIFY_ALLOW_MORE_CV_QUAL 1 #define UNIFY_ALLOW_LESS_CV_QUAL 2 #define UNIFY_ALLOW_DERIVED 4 #define UNIFY_ALLOW_INTEGER 8 #define UNIFY_ALLOW_OUTER_LEVEL 16 #define UNIFY_ALLOW_OUTER_MORE_CV_QUAL 32 #define UNIFY_ALLOW_OUTER_LESS_CV_QUAL 64 #define UNIFY_ALLOW_MAX_CORRECTION 128 static void push_access_scope (tree); static void pop_access_scope (tree); static int resolve_overloaded_unification (tree, tree, tree, tree, unification_kind_t, int); static int try_one_overload (tree, tree, tree, tree, tree, unification_kind_t, int, bool); static int unify (tree, tree, tree, tree, int); static void add_pending_template (tree); static void reopen_tinst_level (tree); static tree classtype_mangled_name (tree); static char* mangle_class_name_for_template (const char *, tree, tree); static tree tsubst_initializer_list (tree, tree); static tree get_class_bindings (tree, tree, tree); static tree coerce_template_parms (tree, tree, tree, tsubst_flags_t, int); static void tsubst_enum (tree, tree, tree); static tree add_to_template_args (tree, tree); static tree add_outermost_template_args (tree, tree); static bool check_instantiated_args (tree, tree, tsubst_flags_t); static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*); static int type_unification_real (tree, tree, tree, tree, int, unification_kind_t, int, int); static void note_template_header (int); static tree convert_nontype_argument_function (tree, tree); static tree convert_nontype_argument (tree, tree); static tree convert_template_argument (tree, tree, tree, tsubst_flags_t, int, tree); static tree get_bindings_overload (tree, tree, tree); static int for_each_template_parm (tree, tree_fn_t, void*, struct pointer_set_t*); static tree build_template_parm_index (int, int, int, tree, tree); static int inline_needs_template_parms (tree); static void push_inline_template_parms_recursive (tree, int); static tree retrieve_local_specialization (tree); static void register_local_specialization (tree, tree); static tree reduce_template_parm_level (tree, tree, int); static int mark_template_parm (tree, void *); static int template_parm_this_level_p (tree, void *); static tree tsubst_friend_function (tree, tree); static tree tsubst_friend_class (tree, tree); static int can_complete_type_without_circularity (tree); static tree get_bindings (tree, tree, tree); static tree get_bindings_real (tree, tree, tree, int, int, int); static int template_decl_level (tree); static int check_cv_quals_for_unify (int, tree, tree); 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 (tree, tree, tree); static tree most_specialized_class (tree, tree); static int template_class_depth_real (tree, int); static tree tsubst_aggr_type (tree, tree, tsubst_flags_t, tree, int); static tree tsubst_arg_types (tree, tree, tsubst_flags_t, tree); static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree); static void check_specialization_scope (void); static tree process_partial_specialization (tree); static void set_current_access_from_decl (tree); static void check_default_tmpl_args (tree, tree, int, int); static tree tsubst_call_declarator_parms (tree, tree, tsubst_flags_t, 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 int coerce_template_template_parms (tree, tree, tsubst_flags_t, tree, tree); static tree determine_specialization (tree, tree, tree *, int, int); static int template_args_equal (tree, tree); static void tsubst_default_arguments (tree); static tree for_each_template_parm_r (tree *, int *, void *); static tree copy_default_args_to_explicit_spec_1 (tree, tree); static void copy_default_args_to_explicit_spec (tree); static int invalid_nontype_parm_type_p (tree, tsubst_flags_t); static int eq_local_specializations (const void *, const void *); static bool dependent_type_p_r (tree); static tree tsubst (tree, tree, tsubst_flags_t, tree); static tree tsubst_expr (tree, tree, tsubst_flags_t, tree); static tree tsubst_copy (tree, tree, tsubst_flags_t, tree); /* Make the current scope suitable for access checking when we are processing T. T can be FUNCTION_DECL for instantiated function template, or VAR_DECL for static member variable (need by instantiate_decl). */ static void push_access_scope (tree t) { gcc_assert (TREE_CODE (t) == FUNCTION_DECL || TREE_CODE (t) == VAR_DECL); if (DECL_FRIEND_CONTEXT (t)) push_nested_class (DECL_FRIEND_CONTEXT (t)); else if (DECL_CLASS_SCOPE_P (t)) push_nested_class (DECL_CONTEXT (t)); else push_to_top_level (); if (TREE_CODE (t) == FUNCTION_DECL) { saved_access_scope = tree_cons (NULL_TREE, current_function_decl, saved_access_scope); current_function_decl = t; } } /* Restore the scope set up by push_access_scope. T is the node we are processing. */ static void pop_access_scope (tree t) { if (TREE_CODE (t) == FUNCTION_DECL) { current_function_decl = TREE_VALUE (saved_access_scope); saved_access_scope = TREE_CHAIN (saved_access_scope); } if (DECL_FRIEND_CONTEXT (t) || DECL_CLASS_SCOPE_P (t)) pop_nested_class (); else pop_from_top_level (); } /* Do any processing required when DECL (a member template declaration) is finished. Returns the TEMPLATE_DECL corresponding to DECL, unless it is a specialization, in which case the DECL itself is returned. */ tree finish_member_template_decl (tree decl) { if (decl == error_mark_node) return error_mark_node; gcc_assert (DECL_P (decl)); if (TREE_CODE (decl) == TYPE_DECL) { tree type; type = TREE_TYPE (decl); if (IS_AGGR_TYPE (type) && CLASSTYPE_TEMPLATE_INFO (type) && !CLASSTYPE_TEMPLATE_SPECIALIZATION (type)) { tree tmpl = CLASSTYPE_TI_TEMPLATE (type); check_member_template (tmpl); return tmpl; } return NULL_TREE; } else if (TREE_CODE (decl) == FIELD_DECL) error ("data member %qD cannot be a member template", decl); else if (DECL_TEMPLATE_INFO (decl)) { if (!DECL_TEMPLATE_SPECIALIZATION (decl)) { check_member_template (DECL_TI_TEMPLATE (decl)); return DECL_TI_TEMPLATE (decl); } else return decl; } else error ("invalid member template declaration %qD", decl); return error_mark_node; } /* Returns the template nesting level of the indicated class TYPE. For example, in: template struct A { template struct B {}; }; A::B has depth two, while A has depth one. Both A::B and A::B have depth one, if COUNT_SPECIALIZATIONS is 0 or if they are instantiations, not specializations. This function is guaranteed to return 0 if passed NULL_TREE so that, for example, `template_class_depth (current_class_type)' is always safe. */ static int template_class_depth_real (tree type, int count_specializations) { int depth; for (depth = 0; type && TREE_CODE (type) != NAMESPACE_DECL; type = (TREE_CODE (type) == FUNCTION_DECL) ? CP_DECL_CONTEXT (type) : TYPE_CONTEXT (type)) { if (TREE_CODE (type) != FUNCTION_DECL) { if (CLASSTYPE_TEMPLATE_INFO (type) && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type)) && ((count_specializations && CLASSTYPE_TEMPLATE_SPECIALIZATION (type)) || uses_template_parms (CLASSTYPE_TI_ARGS (type)))) ++depth; } else { if (DECL_TEMPLATE_INFO (type) && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (type)) && ((count_specializations && DECL_TEMPLATE_SPECIALIZATION (type)) || uses_template_parms (DECL_TI_ARGS (type)))) ++depth; } } return depth; } /* Returns the template nesting level of the indicated class TYPE. Like template_class_depth_real, but instantiations do not count in the depth. */ int template_class_depth (tree type) { return template_class_depth_real (type, /*count_specializations=*/0); } /* Returns 1 if processing DECL as part of do_pending_inlines needs us to push template parms. */ static int inline_needs_template_parms (tree decl) { if (! DECL_TEMPLATE_INFO (decl)) return 0; return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (most_general_template (decl))) > (processing_template_decl + DECL_TEMPLATE_SPECIALIZATION (decl))); } /* Subroutine of maybe_begin_member_template_processing. Push the template parms in PARMS, starting from LEVELS steps into the chain, and ending at the beginning, since template parms are listed innermost first. */ static void push_inline_template_parms_recursive (tree parmlist, int levels) { tree parms = TREE_VALUE (parmlist); int i; if (levels > 1) push_inline_template_parms_recursive (TREE_CHAIN (parmlist), levels - 1); ++processing_template_decl; current_template_parms = tree_cons (size_int (processing_template_decl), parms, current_template_parms); TEMPLATE_PARMS_FOR_INLINE (current_template_parms) = 1; begin_scope (TREE_VEC_LENGTH (parms) ? sk_template_parms : sk_template_spec, NULL); for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) { tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i)); gcc_assert (DECL_P (parm)); switch (TREE_CODE (parm)) { case TYPE_DECL: case TEMPLATE_DECL: pushdecl (parm); break; case PARM_DECL: { /* Make a CONST_DECL as is done in process_template_parm. It is ugly that we recreate this here; the original version built in process_template_parm is no longer available. */ tree decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm)); DECL_ARTIFICIAL (decl) = 1; TREE_CONSTANT (decl) = 1; TREE_INVARIANT (decl) = 1; TREE_READONLY (decl) = 1; DECL_INITIAL (decl) = DECL_INITIAL (parm); SET_DECL_TEMPLATE_PARM_P (decl); pushdecl (decl); } break; default: gcc_unreachable (); } } } /* Restore the template parameter context for a member template or a friend template defined in a class definition. */ void maybe_begin_member_template_processing (tree decl) { tree parms; int levels = 0; if (inline_needs_template_parms (decl)) { parms = DECL_TEMPLATE_PARMS (most_general_template (decl)); levels = TMPL_PARMS_DEPTH (parms) - processing_template_decl; if (DECL_TEMPLATE_SPECIALIZATION (decl)) { --levels; parms = TREE_CHAIN (parms); } push_inline_template_parms_recursive (parms, levels); } /* Remember how many levels of template parameters we pushed so that we can pop them later. */ if (!inline_parm_levels) VARRAY_INT_INIT (inline_parm_levels, 4, "inline_parm_levels"); if (inline_parm_levels_used == inline_parm_levels->num_elements) VARRAY_GROW (inline_parm_levels, 2 * inline_parm_levels_used); VARRAY_INT (inline_parm_levels, inline_parm_levels_used) = levels; ++inline_parm_levels_used; } /* Undo the effects of begin_member_template_processing. */ void maybe_end_member_template_processing (void) { int i; if (!inline_parm_levels_used) return; --inline_parm_levels_used; for (i = 0; i < VARRAY_INT (inline_parm_levels, inline_parm_levels_used); ++i) { --processing_template_decl; current_template_parms = TREE_CHAIN (current_template_parms); poplevel (0, 0, 0); } } /* Return a new template argument vector which contains all of ARGS, but has as its innermost set of arguments the EXTRA_ARGS. */ static tree add_to_template_args (tree args, tree extra_args) { tree new_args; int extra_depth; int i; int j; extra_depth = TMPL_ARGS_DEPTH (extra_args); new_args = make_tree_vec (TMPL_ARGS_DEPTH (args) + extra_depth); for (i = 1; i <= TMPL_ARGS_DEPTH (args); ++i) SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (args, i)); for (j = 1; j <= extra_depth; ++j, ++i) SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (extra_args, j)); return new_args; } /* Like add_to_template_args, but only the outermost ARGS are added to the EXTRA_ARGS. In particular, all but TMPL_ARGS_DEPTH (EXTRA_ARGS) levels are added. This function is used to combine the template arguments from a partial instantiation with the template arguments used to attain the full instantiation from the partial instantiation. */ static tree add_outermost_template_args (tree args, tree extra_args) { tree new_args; /* If there are more levels of EXTRA_ARGS than there are ARGS, something very fishy is going on. */ gcc_assert (TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args)); /* If *all* the new arguments will be the EXTRA_ARGS, just return them. */ if (TMPL_ARGS_DEPTH (args) == TMPL_ARGS_DEPTH (extra_args)) return extra_args; /* For the moment, we make ARGS look like it contains fewer levels. */ TREE_VEC_LENGTH (args) -= TMPL_ARGS_DEPTH (extra_args); new_args = add_to_template_args (args, extra_args); /* Now, we restore ARGS to its full dimensions. */ TREE_VEC_LENGTH (args) += TMPL_ARGS_DEPTH (extra_args); return new_args; } /* Return the N levels of innermost template arguments from the ARGS. */ tree get_innermost_template_args (tree args, int n) { tree new_args; int extra_levels; int i; gcc_assert (n >= 0); /* If N is 1, just return the innermost set of template arguments. */ if (n == 1) return TMPL_ARGS_LEVEL (args, TMPL_ARGS_DEPTH (args)); /* If we're not removing anything, just return the arguments we were given. */ extra_levels = TMPL_ARGS_DEPTH (args) - n; gcc_assert (extra_levels >= 0); if (extra_levels == 0) return args; /* Make a new set of arguments, not containing the outer arguments. */ new_args = make_tree_vec (n); for (i = 1; i <= n; ++i) SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (args, i + extra_levels)); return new_args; } /* We've got a template header coming up; push to a new level for storing the parms. */ void begin_template_parm_list (void) { /* We use a non-tag-transparent scope here, which causes pushtag to put tags in this scope, rather than in the enclosing class or namespace scope. This is the right thing, since we want TEMPLATE_DECLS, and not TYPE_DECLS for template classes. For a global template class, push_template_decl handles putting the TEMPLATE_DECL into top-level scope. For a nested template class, e.g.: template struct S1 { template struct S2 {}; }; pushtag contains special code to call pushdecl_with_scope on the TEMPLATE_DECL for S2. */ begin_scope (sk_template_parms, NULL); ++processing_template_decl; ++processing_template_parmlist; note_template_header (0); } /* This routine is called when a specialization is declared. If it is invalid to declare a specialization here, an error is reported. */ static void check_specialization_scope (void) { tree scope = current_scope (); /* [temp.expl.spec] An explicit specialization shall be declared in the namespace of which the template is a member, or, for member templates, in the namespace of which the enclosing class or enclosing class template is a member. An explicit specialization of a member function, member class or static data member of a class template shall be declared in the namespace of which the class template is a member. */ if (scope && TREE_CODE (scope) != NAMESPACE_DECL) error ("explicit specialization in non-namespace scope %qD", scope); /* [temp.expl.spec] In an explicit specialization declaration for a member of a class template or a member template that appears in namespace scope, the member template and some of its enclosing class templates may remain unspecialized, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well. */ if (current_template_parms) error ("enclosing class templates are not explicitly specialized"); } /* We've just seen template <>. */ void begin_specialization (void) { begin_scope (sk_template_spec, NULL); note_template_header (1); check_specialization_scope (); } /* Called at then end of processing a declaration preceded by template<>. */ void end_specialization (void) { finish_scope (); reset_specialization (); } /* Any template <>'s that we have seen thus far are not referring to a function specialization. */ void reset_specialization (void) { processing_specialization = 0; template_header_count = 0; } /* We've just seen a template header. If SPECIALIZATION is nonzero, it was of the form template <>. */ static void note_template_header (int specialization) { processing_specialization = specialization; template_header_count++; } /* We're beginning an explicit instantiation. */ void begin_explicit_instantiation (void) { gcc_assert (!processing_explicit_instantiation); processing_explicit_instantiation = true; } void end_explicit_instantiation (void) { gcc_assert (processing_explicit_instantiation); processing_explicit_instantiation = false; } /* A explicit specialization or partial specialization TMPL is being declared. Check that the namespace in which the specialization is occurring is permissible. Returns false iff it is invalid to specialize TMPL in the current namespace. */ static bool check_specialization_namespace (tree tmpl) { tree tpl_ns = decl_namespace_context (tmpl); /* [tmpl.expl.spec] An explicit specialization shall be declared in the namespace of which the template is a member, or, for member templates, in the namespace of which the enclosing class or enclosing class template is a member. An explicit specialization of a member function, member class or static data member of a class template shall be declared in the namespace of which the class template is a member. */ if (is_associated_namespace (current_namespace, tpl_ns)) /* Same or super-using namespace. */ return true; else { pedwarn ("specialization of %qD in different namespace", tmpl); cp_pedwarn_at (" from definition of %q#D", tmpl); return false; } } /* The TYPE is being declared. If it is a template type, that means it is a partial specialization. Do appropriate error-checking. */ void maybe_process_partial_specialization (tree type) { /* TYPE maybe an ERROR_MARK_NODE. */ tree context = TYPE_P (type) ? TYPE_CONTEXT (type) : NULL_TREE; if (CLASS_TYPE_P (type) && CLASSTYPE_USE_TEMPLATE (type)) { /* This is for ordinary explicit specialization and partial specialization of a template class such as: template <> class C; or: template class C; Make sure that `C' and `C' are implicit instantiations. */ if (CLASSTYPE_IMPLICIT_INSTANTIATION (type) && !COMPLETE_TYPE_P (type)) { check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (type)); SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type); if (processing_template_decl) push_template_decl (TYPE_MAIN_DECL (type)); } else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type)) error ("specialization of %qT after instantiation", type); } else if (CLASS_TYPE_P (type) && !CLASSTYPE_USE_TEMPLATE (type) && CLASSTYPE_TEMPLATE_INFO (type) && context && CLASS_TYPE_P (context) && CLASSTYPE_TEMPLATE_INFO (context)) { /* This is for an explicit specialization of member class template according to [temp.expl.spec/18]: template <> template class C::D; The context `C' must be an implicit instantiation. Otherwise this is just a member class template declared earlier like: template <> class C { template class D; }; template <> template class C::D; In the first case, `C::D' is a specialization of `C::D' while in the second case, `C::D' is a primary template and `C::D' may not exist. */ if (CLASSTYPE_IMPLICIT_INSTANTIATION (context) && !COMPLETE_TYPE_P (type)) { tree t; if (current_namespace != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type))) { pedwarn ("specializing %q#T in different namespace", type); cp_pedwarn_at (" from definition of %q#D", CLASSTYPE_TI_TEMPLATE (type)); } /* Check for invalid specialization after instantiation: template <> template <> class C::D; template <> template class C::D; */ for (t = DECL_TEMPLATE_INSTANTIATIONS (most_general_template (CLASSTYPE_TI_TEMPLATE (type))); t; t = TREE_CHAIN (t)) if (TREE_VALUE (t) != type && TYPE_CONTEXT (TREE_VALUE (t)) == context) error ("specialization %qT after instantiation %qT", type, TREE_VALUE (t)); /* Mark TYPE as a specialization. And as a result, we only have one level of template argument for the innermost class template. */ SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type); CLASSTYPE_TI_ARGS (type) = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type)); } } else if (processing_specialization) error ("explicit specialization of non-template %qT", type); } /* Returns nonzero if we can optimize the retrieval of specializations for TMPL, a TEMPLATE_DECL. In particular, for such a template, we do not use DECL_TEMPLATE_SPECIALIZATIONS at all. */ static inline bool optimize_specialization_lookup_p (tree tmpl) { return (DECL_FUNCTION_TEMPLATE_P (tmpl) && DECL_CLASS_SCOPE_P (tmpl) /* DECL_CLASS_SCOPE_P holds of T::f even if T is a template parameter. */ && CLASS_TYPE_P (DECL_CONTEXT (tmpl)) /* The optimized lookup depends on the fact that the template arguments for the member function template apply purely to the containing class, which is not true if the containing class is an explicit or partial specialization. */ && !CLASSTYPE_TEMPLATE_SPECIALIZATION (DECL_CONTEXT (tmpl)) && !DECL_MEMBER_TEMPLATE_P (tmpl) && !DECL_CONV_FN_P (tmpl) /* It is possible to have a template that is not a member template and is not a member of a template class: template struct S { friend A::f(); }; Here, the friend function is a template, but the context does not have template information. The optimized lookup relies on having ARGS be the template arguments for both the class and the function template. */ && !DECL_FRIEND_P (DECL_TEMPLATE_RESULT (tmpl))); } /* Retrieve the specialization (in the sense of [temp.spec] - a specialization is either an instantiation or an explicit specialization) of TMPL for the given template ARGS. If there is no such specialization, return NULL_TREE. The ARGS are a vector of arguments, or a vector of vectors of arguments, in the case of templates with more than one level of parameters. If TMPL is a type template and CLASS_SPECIALIZATIONS_P is true, then we search for a partial specialization matching ARGS. This parameter is ignored if TMPL is not a class template. */ static tree retrieve_specialization (tree tmpl, tree args, bool class_specializations_p) { gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL); /* There should be as many levels of arguments as there are levels of parameters. */ gcc_assert (TMPL_ARGS_DEPTH (args) == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))); if (optimize_specialization_lookup_p (tmpl)) { tree class_template; tree class_specialization; VEC(tree) *methods; tree fns; int idx; /* The template arguments actually apply to the containing class. Find the class specialization with those arguments. */ class_template = CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (tmpl)); class_specialization = retrieve_specialization (class_template, args, /*class_specializations_p=*/false); if (!class_specialization) return NULL_TREE; /* Now, find the appropriate entry in the CLASSTYPE_METHOD_VEC for the specialization. */ idx = class_method_index_for_fn (class_specialization, tmpl); if (idx == -1) return NULL_TREE; /* Iterate through the methods with the indicated name, looking for the one that has an instance of TMPL. */ methods = CLASSTYPE_METHOD_VEC (class_specialization); for (fns = VEC_index (tree, methods, idx); fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); if (DECL_TEMPLATE_INFO (fn) && DECL_TI_TEMPLATE (fn) == tmpl) return fn; } return NULL_TREE; } else { tree *sp; tree *head; /* Class templates store their instantiations on the DECL_TEMPLATE_INSTANTIATIONS list; other templates use the DECL_TEMPLATE_SPECIALIZATIONS list. */ if (!class_specializations_p && TREE_CODE (DECL_TEMPLATE_RESULT (tmpl)) == TYPE_DECL) sp = &DECL_TEMPLATE_INSTANTIATIONS (tmpl); else sp = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl); head = sp; /* Iterate through the list until we find a matching template. */ while (*sp != NULL_TREE) { tree spec = *sp; if (comp_template_args (TREE_PURPOSE (spec), args)) { /* Use the move-to-front heuristic to speed up future searches. */ if (spec != *head) { *sp = TREE_CHAIN (*sp); TREE_CHAIN (spec) = *head; *head = spec; } return TREE_VALUE (spec); } sp = &TREE_CHAIN (spec); } } return NULL_TREE; } /* Like retrieve_specialization, but for local declarations. */ static tree retrieve_local_specialization (tree tmpl) { tree spec = htab_find_with_hash (local_specializations, tmpl, htab_hash_pointer (tmpl)); return spec ? TREE_PURPOSE (spec) : NULL_TREE; } /* Returns nonzero iff DECL is a specialization of TMPL. */ int is_specialization_of (tree decl, tree tmpl) { tree t; if (TREE_CODE (decl) == FUNCTION_DECL) { for (t = decl; t != NULL_TREE; t = DECL_TEMPLATE_INFO (t) ? DECL_TI_TEMPLATE (t) : NULL_TREE) if (t == tmpl) return 1; } else { gcc_assert (TREE_CODE (decl) == TYPE_DECL); for (t = TREE_TYPE (decl); t != NULL_TREE; t = CLASSTYPE_USE_TEMPLATE (t) ? TREE_TYPE (CLASSTYPE_TI_TEMPLATE (t)) : NULL_TREE) if (same_type_ignoring_top_level_qualifiers_p (t, TREE_TYPE (tmpl))) return 1; } return 0; } /* Returns nonzero iff DECL is a specialization of friend declaration FRIEND according to [temp.friend]. */ bool is_specialization_of_friend (tree decl, tree friend) { bool need_template = true; int template_depth; gcc_assert (TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == TYPE_DECL); /* For [temp.friend/6] when FRIEND is an ordinary member function of a template class, we want to check if DECL is a specialization if this. */ if (TREE_CODE (friend) == FUNCTION_DECL && DECL_TEMPLATE_INFO (friend) && !DECL_USE_TEMPLATE (friend)) { /* We want a TEMPLATE_DECL for `is_specialization_of'. */ friend = DECL_TI_TEMPLATE (friend); need_template = false; } else if (TREE_CODE (friend) == TEMPLATE_DECL && !PRIMARY_TEMPLATE_P (friend)) need_template = false; /* There is nothing to do if this is not a template friend. */ if (TREE_CODE (friend) != TEMPLATE_DECL) return false; if (is_specialization_of (decl, friend)) return true; /* [temp.friend/6] A member of a class template may be declared to be a friend of a non-template class. In this case, the corresponding member of every specialization of the class template is a friend of the class granting friendship. For example, given a template friend declaration template friend void A::f(); the member function below is considered a friend template <> struct A { void f(); }; For this type of template friend, TEMPLATE_DEPTH below will be nonzero. To determine if DECL is a friend of FRIEND, we first check if the enclosing class is a specialization of another. */ template_depth = template_class_depth (DECL_CONTEXT (friend)); if (template_depth && DECL_CLASS_SCOPE_P (decl) && is_specialization_of (TYPE_NAME (DECL_CONTEXT (decl)), CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (friend)))) { /* Next, we check the members themselves. In order to handle a few tricky cases, such as when FRIEND's are template friend void A::g(T t); template template friend void A::h(); and DECL's are void A::g(int); template void A::h(); we need to figure out ARGS, the template arguments from the context of DECL. This is required for template substitution of `T' in the function parameter of `g' and template parameter of `h' in the above examples. Here ARGS corresponds to `int'. */ tree context = DECL_CONTEXT (decl); tree args = NULL_TREE; int current_depth = 0; while (current_depth < template_depth) { if (CLASSTYPE_TEMPLATE_INFO (context)) { if (current_depth == 0) args = TYPE_TI_ARGS (context); else args = add_to_template_args (TYPE_TI_ARGS (context), args); current_depth++; } context = TYPE_CONTEXT (context); } if (TREE_CODE (decl) == FUNCTION_DECL) { bool is_template; tree friend_type; tree decl_type; tree friend_args_type; tree decl_args_type; /* Make sure that both DECL and FRIEND are templates or non-templates. */ is_template = DECL_TEMPLATE_INFO (decl) && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl)); if (need_template ^ is_template) return false; else if (is_template) { /* If both are templates, check template parameter list. */ tree friend_parms = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend), args, tf_none); if (!comp_template_parms (DECL_TEMPLATE_PARMS (DECL_TI_TEMPLATE (decl)), friend_parms)) return false; decl_type = TREE_TYPE (DECL_TI_TEMPLATE (decl)); } else decl_type = TREE_TYPE (decl); friend_type = tsubst_function_type (TREE_TYPE (friend), args, tf_none, NULL_TREE); if (friend_type == error_mark_node) return false; /* Check if return types match. */ if (!same_type_p (TREE_TYPE (decl_type), TREE_TYPE (friend_type))) return false; /* Check if function parameter types match, ignoring the `this' parameter. */ friend_args_type = TYPE_ARG_TYPES (friend_type); decl_args_type = TYPE_ARG_TYPES (decl_type); if (DECL_NONSTATIC_MEMBER_FUNCTION_P (friend)) friend_args_type = TREE_CHAIN (friend_args_type); if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) decl_args_type = TREE_CHAIN (decl_args_type); return compparms (decl_args_type, friend_args_type); } else { /* DECL is a TYPE_DECL */ bool is_template; tree decl_type = TREE_TYPE (decl); /* Make sure that both DECL and FRIEND are templates or non-templates. */ is_template = CLASSTYPE_TEMPLATE_INFO (decl_type) && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (decl_type)); if (need_template ^ is_template) return false; else if (is_template) { tree friend_parms; /* If both are templates, check the name of the two TEMPLATE_DECL's first because is_friend didn't. */ if (DECL_NAME (CLASSTYPE_TI_TEMPLATE (decl_type)) != DECL_NAME (friend)) return false; /* Now check template parameter list. */ friend_parms = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend), args, tf_none); return comp_template_parms (DECL_TEMPLATE_PARMS (CLASSTYPE_TI_TEMPLATE (decl_type)), friend_parms); } else return (DECL_NAME (decl) == DECL_NAME (friend)); } } return false; } /* Register the specialization SPEC as a specialization of TMPL with the indicated ARGS. Returns SPEC, or an equivalent prior declaration, if available. */ static tree register_specialization (tree spec, tree tmpl, tree args) { tree fn; gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL); if (TREE_CODE (spec) == FUNCTION_DECL && uses_template_parms (DECL_TI_ARGS (spec))) /* This is the FUNCTION_DECL for a partial instantiation. Don't register it; we want the corresponding TEMPLATE_DECL instead. We use `uses_template_parms (DECL_TI_ARGS (spec))' rather than the more obvious `uses_template_parms (spec)' to avoid problems with default function arguments. In particular, given something like this: template void f(T t1, T t = T()) the default argument expression is not substituted for in an instantiation unless and until it is actually needed. */ return spec; /* There should be as many levels of arguments as there are levels of parameters. */ gcc_assert (TMPL_ARGS_DEPTH (args) == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl))); fn = retrieve_specialization (tmpl, args, /*class_specializations_p=*/false); /* We can sometimes try to re-register a specialization that we've already got. In particular, regenerate_decl_from_template calls duplicate_decls which will update the specialization list. But, we'll still get called again here anyhow. It's more convenient to simply allow this than to try to prevent it. */ if (fn == spec) return spec; else if (fn && DECL_TEMPLATE_SPECIALIZATION (spec)) { if (DECL_TEMPLATE_INSTANTIATION (fn)) { if (TREE_USED (fn) || DECL_EXPLICIT_INSTANTIATION (fn)) { error ("specialization of %qD after instantiation", fn); return spec; } else { /* This situation should occur only if the first specialization is an implicit instantiation, the second is an explicit specialization, and the implicit instantiation has not yet been used. That situation can occur if we have implicitly instantiated a member function and then specialized it later. We can also wind up here if a friend declaration that looked like an instantiation turns out to be a specialization: template void foo(T); class S { friend void foo<>(int) }; template <> void foo(int); We transform the existing DECL in place so that any pointers to it become pointers to the updated declaration. If there was a definition for the template, but not for the specialization, we want this to look as if there were no definition, and vice versa. */ DECL_INITIAL (fn) = NULL_TREE; duplicate_decls (spec, fn); return fn; } } else if (DECL_TEMPLATE_SPECIALIZATION (fn)) { if (!duplicate_decls (spec, fn) && DECL_INITIAL (spec)) /* Dup decl failed, but this is a new definition. Set the line number so any errors match this new definition. */ DECL_SOURCE_LOCATION (fn) = DECL_SOURCE_LOCATION (spec); return fn; } } /* A specialization must be declared in the same namespace as the template it is specializing. */ if (DECL_TEMPLATE_SPECIALIZATION (spec) && !check_specialization_namespace (tmpl)) DECL_CONTEXT (spec) = decl_namespace_context (tmpl); if (!optimize_specialization_lookup_p (tmpl)) DECL_TEMPLATE_SPECIALIZATIONS (tmpl) = tree_cons (args, spec, DECL_TEMPLATE_SPECIALIZATIONS (tmpl)); return spec; } /* Unregister the specialization SPEC as a specialization of TMPL. Replace it with NEW_SPEC, if NEW_SPEC is non-NULL. Returns true if the SPEC was listed as a specialization of TMPL. */ bool reregister_specialization (tree spec, tree tmpl, tree new_spec) { tree* s; for (s = &DECL_TEMPLATE_SPECIALIZATIONS (tmpl); *s != NULL_TREE; s = &TREE_CHAIN (*s)) if (TREE_VALUE (*s) == spec) { if (!new_spec) *s = TREE_CHAIN (*s); else TREE_VALUE (*s) = new_spec; return 1; } return 0; } /* Compare an entry in the local specializations hash table P1 (which is really a pointer to a TREE_LIST) with P2 (which is really a DECL). */ static int eq_local_specializations (const void *p1, const void *p2) { return TREE_VALUE ((tree) p1) == (tree) p2; } /* Hash P1, an entry in the local specializations table. */ static hashval_t hash_local_specialization (const void* p1) { return htab_hash_pointer (TREE_VALUE ((tree) p1)); } /* Like register_specialization, but for local declarations. We are registering SPEC, an instantiation of TMPL. */ static void register_local_specialization (tree spec, tree tmpl) { void **slot; slot = htab_find_slot_with_hash (local_specializations, tmpl, htab_hash_pointer (tmpl), INSERT); *slot = build_tree_list (spec, tmpl); } /* Print the list of candidate FNS in an error message. */ void print_candidates (tree fns) { tree fn; const char *str = "candidates are:"; for (fn = fns; fn != NULL_TREE; fn = TREE_CHAIN (fn)) { tree f; for (f = TREE_VALUE (fn); f; f = OVL_NEXT (f)) cp_error_at ("%s %+#D", str, OVL_CURRENT (f)); str = " "; } } /* Returns the template (one of the functions given by TEMPLATE_ID) which can be specialized to match the indicated DECL with the explicit template args given in TEMPLATE_ID. The DECL may be NULL_TREE if none is available. In that case, the functions in TEMPLATE_ID are non-members. If NEED_MEMBER_TEMPLATE is nonzero the function is known to be a specialization of a member template. The TEMPLATE_COUNT is the number of references to qualifying template classes that appeared in the name of the function. See check_explicit_specialization for a more accurate description. The template args (those explicitly specified and those deduced) are output in a newly created vector *TARGS_OUT. If it is impossible to determine the result, an error message is issued. The error_mark_node is returned to indicate failure. */ static tree determine_specialization (tree template_id, tree decl, tree* targs_out, int need_member_template, int template_count) { tree fns; tree targs; tree explicit_targs; tree candidates = NULL_TREE; tree templates = NULL_TREE; int header_count; struct cp_binding_level *b; *targs_out = NULL_TREE; if (template_id == error_mark_node) return error_mark_node; fns = TREE_OPERAND (template_id, 0); explicit_targs = TREE_OPERAND (template_id, 1); if (fns == error_mark_node) return error_mark_node; /* Check for baselinks. */ if (BASELINK_P (fns)) fns = BASELINK_FUNCTIONS (fns); if (!is_overloaded_fn (fns)) { error ("%qD is not a function template", fns); return error_mark_node; } /* Count the number of template headers specified for this specialization. */ header_count = 0; for (b = current_binding_level; b->kind == sk_template_parms || b->kind == sk_template_spec; b = b->level_chain) ++header_count; for (; fns; fns = OVL_NEXT (fns)) { tree fn = OVL_CURRENT (fns); if (TREE_CODE (fn) == TEMPLATE_DECL) { tree decl_arg_types; tree fn_arg_types; /* DECL might be a specialization of FN. */ /* Adjust the type of DECL in case FN is a static member. */ decl_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl)); if (DECL_STATIC_FUNCTION_P (fn) && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) decl_arg_types = TREE_CHAIN (decl_arg_types); /* Check that the number of function parameters matches. For example, template void f(int i = 0); template <> void f(); The specialization f is invalid but is not caught by get_bindings below. */ fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); if (list_length (fn_arg_types) != list_length (decl_arg_types)) continue; /* For a non-static member function, we need to make sure that the const qualification is the same. This can be done by checking the 'this' in the argument list. */ if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn) && !same_type_p (TREE_VALUE (fn_arg_types), TREE_VALUE (decl_arg_types))) continue; /* In case of explicit specialization, we need to check if the number of template headers appearing in the specialization is correct. This is usually done in check_explicit_specialization, but the check done there cannot be exhaustive when specializing member functions. Consider the following code: template <> void A::f(int); template <> template <> void A::f(int); Assuming that A is not itself an explicit specialization already, the first line specializes "f" which is a non-template member function, whilst the second line specializes "f" which is a template member function. So both lines are syntactically correct, and check_explicit_specialization does not reject them. Here, we can do better, as we are matching the specialization against the declarations. We count the number of template headers, and we check if they match TEMPLATE_COUNT + 1 (TEMPLATE_COUNT is the number of qualifying template classes, plus there must be another header for the member template itself). Notice that if header_count is zero, this is not a specialization but rather a template instantiation, so there is no check we can perform here. */ if (header_count && header_count != template_count + 1) continue; /* See whether this function might be a specialization of this template. */ targs = get_bindings (fn, decl, explicit_targs); if (!targs) /* We cannot deduce template arguments that when used to specialize TMPL will produce DECL. */ continue; /* Save this template, and the arguments deduced. */ templates = tree_cons (targs, fn, templates); } else if (need_member_template) /* FN is an ordinary member function, and we need a specialization of a member template. */ ; else if (TREE_CODE (fn) != FUNCTION_DECL) /* We can get IDENTIFIER_NODEs here in certain erroneous cases. */ ; else if (!DECL_FUNCTION_MEMBER_P (fn)) /* This is just an ordinary non-member function. Nothing can be a specialization of that. */ ; else if (DECL_ARTIFICIAL (fn)) /* Cannot specialize functions that are created implicitly. */ ; else { tree decl_arg_types; /* This is an ordinary member function. However, since we're here, we can assume it's enclosing class is a template class. For example, template struct S { void f(); }; template <> void S::f() {} Here, S::f is a non-template, but S is a template class. If FN has the same type as DECL, we might be in business. */ if (!DECL_TEMPLATE_INFO (fn)) /* Its enclosing class is an explicit specialization of a template class. This is not a candidate. */ continue; if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)), TREE_TYPE (TREE_TYPE (fn)))) /* The return types differ. */ continue; /* Adjust the type of DECL in case FN is a static member. */ decl_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl)); if (DECL_STATIC_FUNCTION_P (fn) && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) decl_arg_types = TREE_CHAIN (decl_arg_types); if (compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)), decl_arg_types)) /* They match! */ candidates = tree_cons (NULL_TREE, fn, candidates); } } if (templates && TREE_CHAIN (templates)) { /* We have: [temp.expl.spec] It is possible for a specialization with a given function signature to be instantiated from more than one function template. In such cases, explicit specification of the template arguments must be used to uniquely identify the function template specialization being specialized. Note that here, there's no suggestion that we're supposed to determine which of the candidate templates is most specialized. However, we, also have: [temp.func.order] Partial ordering of overloaded function template declarations is used in the following contexts to select the function template to which a function template specialization refers: -- when an explicit specialization refers to a function template. So, we do use the partial ordering rules, at least for now. This extension can only serve to make invalid programs valid, so it's safe. And, there is strong anecdotal evidence that the committee intended the partial ordering rules to apply; the EDG front-end has that behavior, and John Spicer claims that the committee simply forgot to delete the wording in [temp.expl.spec]. */ tree tmpl = most_specialized (templates, decl, explicit_targs); if (tmpl && tmpl != error_mark_node) { targs = get_bindings (tmpl, decl, explicit_targs); templates = tree_cons (targs, tmpl, NULL_TREE); } } if (templates == NULL_TREE && candidates == NULL_TREE) { cp_error_at ("template-id %qD for %q+D does not match any template " "declaration", template_id, decl); return error_mark_node; } else if ((templates && TREE_CHAIN (templates)) || (candidates && TREE_CHAIN (candidates)) || (templates && candidates)) { cp_error_at ("ambiguous template specialization %qD for %q+D", template_id, decl); chainon (candidates, templates); print_candidates (candidates); return error_mark_node; } /* We have one, and exactly one, match. */ if (candidates) { /* It was a specialization of an ordinary member function in a template class. */ *targs_out = copy_node (DECL_TI_ARGS (TREE_VALUE (candidates))); return DECL_TI_TEMPLATE (TREE_VALUE (candidates)); } /* It was a specialization of a template. */ targs = DECL_TI_ARGS (DECL_TEMPLATE_RESULT (TREE_VALUE (templates))); if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (targs)) { *targs_out = copy_node (targs); SET_TMPL_ARGS_LEVEL (*targs_out, TMPL_ARGS_DEPTH (*targs_out), TREE_PURPOSE (templates)); } else *targs_out = TREE_PURPOSE (templates); return TREE_VALUE (templates); } /* Returns a chain of parameter types, exactly like the SPEC_TYPES, but with the default argument values filled in from those in the TMPL_TYPES. */ static tree copy_default_args_to_explicit_spec_1 (tree spec_types, tree tmpl_types) { tree new_spec_types; if (!spec_types) return NULL_TREE; if (spec_types == void_list_node) return void_list_node; /* Substitute into the rest of the list. */ new_spec_types = copy_default_args_to_explicit_spec_1 (TREE_CHAIN (spec_types), TREE_CHAIN (tmpl_types)); /* Add the default argument for this parameter. */ return hash_tree_cons (TREE_PURPOSE (tmpl_types), TREE_VALUE (spec_types), new_spec_types); } /* DECL is an explicit specialization. Replicate default arguments from the template it specializes. (That way, code like: template void f(T = 3); template <> void f(double); void g () { f (); } works, as required.) An alternative approach would be to look up the correct default arguments at the call-site, but this approach is consistent with how implicit instantiations are handled. */ static void copy_default_args_to_explicit_spec (tree decl) { tree tmpl; tree spec_types; tree tmpl_types; tree new_spec_types; tree old_type; tree new_type; tree t; tree object_type = NULL_TREE; tree in_charge = NULL_TREE; tree vtt = NULL_TREE; /* See if there's anything we need to do. */ tmpl = DECL_TI_TEMPLATE (decl); tmpl_types = TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (tmpl))); for (t = tmpl_types; t; t = TREE_CHAIN (t)) if (TREE_PURPOSE (t)) break; if (!t) return; old_type = TREE_TYPE (decl); spec_types = TYPE_ARG_TYPES (old_type); if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) { /* Remove the this pointer, but remember the object's type for CV quals. */ object_type = TREE_TYPE (TREE_VALUE (spec_types)); spec_types = TREE_CHAIN (spec_types); tmpl_types = TREE_CHAIN (tmpl_types); if (DECL_HAS_IN_CHARGE_PARM_P (decl)) { /* DECL may contain more parameters than TMPL due to the extra in-charge parameter in constructors and destructors. */ in_charge = spec_types; spec_types = TREE_CHAIN (spec_types); } if (DECL_HAS_VTT_PARM_P (decl)) { vtt = spec_types; spec_types = TREE_CHAIN (spec_types); } } /* Compute the merged default arguments. */ new_spec_types = copy_default_args_to_explicit_spec_1 (spec_types, tmpl_types); /* Compute the new FUNCTION_TYPE. */ if (object_type) { if (vtt) new_spec_types = hash_tree_cons (TREE_PURPOSE (vtt), TREE_VALUE (vtt), new_spec_types); if (in_charge) /* Put the in-charge parameter back. */ new_spec_types = hash_tree_cons (TREE_PURPOSE (in_charge), TREE_VALUE (in_charge), new_spec_types); new_type = build_method_type_directly (object_type, TREE_TYPE (old_type), new_spec_types); } else new_type = build_function_type (TREE_TYPE (old_type), new_spec_types); new_type = cp_build_type_attribute_variant (new_type, TYPE_ATTRIBUTES (old_type)); new_type = build_exception_variant (new_type, TYPE_RAISES_EXCEPTIONS (old_type)); TREE_TYPE (decl) = new_type; } /* Check to see if the function just declared, as indicated in DECLARATOR, and in DECL, is a specialization of a function template. We may also discover that the declaration is an explicit instantiation at this point. Returns DECL, or an equivalent declaration that should be used instead if all goes well. Issues an error message if something is amiss. Returns error_mark_node if the error is not easily recoverable. FLAGS is a bitmask consisting of the following flags: 2: The function has a definition. 4: The function is a friend. The TEMPLATE_COUNT is the number of references to qualifying template classes that appeared in the name of the function. For example, in template struct S { void f(); }; void S::f(); the TEMPLATE_COUNT would be 1. However, explicitly specialized classes are not counted in the TEMPLATE_COUNT, so that in template struct S {}; template <> struct S { void f(); } template <> void S::f(); the TEMPLATE_COUNT would be 0. (Note that this declaration is invalid; there should be no template <>.) If the function is a specialization, it is marked as such via DECL_TEMPLATE_SPECIALIZATION. Furthermore, its DECL_TEMPLATE_INFO is set up correctly, and it is added to the list of specializations for that template. */ tree check_explicit_specialization (tree declarator, tree decl, int template_count, int flags) { int have_def = flags & 2; int is_friend = flags & 4; int specialization = 0; int explicit_instantiation = 0; int member_specialization = 0; tree ctype = DECL_CLASS_CONTEXT (decl); tree dname = DECL_NAME (decl); tmpl_spec_kind tsk; if (is_friend) { if (!processing_specialization) tsk = tsk_none; else tsk = tsk_excessive_parms; } else tsk = current_tmpl_spec_kind (template_count); switch (tsk) { case tsk_none: if (processing_specialization) { specialization = 1; SET_DECL_TEMPLATE_SPECIALIZATION (decl); } else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR) { if (is_friend) /* This could be something like: template void f(T); class S { friend void f<>(int); } */ specialization = 1; else { /* This case handles bogus declarations like template <> template void f(); */ error ("template-id %qD in declaration of primary template", declarator); return decl; } } break; case tsk_invalid_member_spec: /* The error has already been reported in check_specialization_scope. */ return error_mark_node; case tsk_invalid_expl_inst: error ("template parameter list used in explicit instantiation"); /* Fall through. */ case tsk_expl_inst: if (have_def) error ("definition provided for explicit instantiation"); explicit_instantiation = 1; break; case tsk_excessive_parms: case tsk_insufficient_parms: if (tsk == tsk_excessive_parms) error ("too many template parameter lists in declaration of %qD", decl); else if (template_header_count) error("too few template parameter lists in declaration of %qD", decl); else error("explicit specialization of %qD must be introduced by " "%