| /* Handle parameterized types (templates) for GNU -*- C++ -*-. |
| Copyright (C) 1992-2022 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 3, 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 COPYING3. If not see |
| <http://www.gnu.org/licenses/>. */ |
| |
| /* 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". |
| |
| Fixed by: C++20 modules. */ |
| |
| #include "config.h" |
| #include "system.h" |
| #include "coretypes.h" |
| #include "cp-tree.h" |
| #include "timevar.h" |
| #include "stringpool.h" |
| #include "varasm.h" |
| #include "attribs.h" |
| #include "stor-layout.h" |
| #include "intl.h" |
| #include "c-family/c-objc.h" |
| #include "cp-objcp-common.h" |
| #include "toplev.h" |
| #include "tree-iterator.h" |
| #include "type-utils.h" |
| #include "gimplify.h" |
| #include "gcc-rich-location.h" |
| #include "selftest.h" |
| #include "target.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 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. */ |
| struct GTY ((chain_next ("%h.next"))) pending_template |
| { |
| struct pending_template *next; |
| struct tinst_level *tinst; |
| }; |
| |
| static GTY(()) struct pending_template *pending_templates; |
| static GTY(()) struct pending_template *last_pending_template; |
| |
| int processing_template_parmlist; |
| static int template_header_count; |
| |
| static vec<int> inline_parm_levels; |
| |
| static GTY(()) struct tinst_level *current_tinst_level; |
| |
| static GTY(()) vec<tree, va_gc> *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; |
| |
| // -------------------------------------------------------------------------- // |
| // Local Specialization Stack |
| // |
| // Implementation of the RAII helper for creating new local |
| // specializations. |
| local_specialization_stack::local_specialization_stack (lss_policy policy) |
| : saved (local_specializations) |
| { |
| if (policy == lss_nop) |
| ; |
| else if (policy == lss_blank || !saved) |
| local_specializations = new hash_map<tree, tree>; |
| else |
| local_specializations = new hash_map<tree, tree>(*saved); |
| } |
| |
| local_specialization_stack::~local_specialization_stack () |
| { |
| if (local_specializations != saved) |
| { |
| delete local_specializations; |
| local_specializations = saved; |
| } |
| } |
| |
| /* True if we've recursed into fn_type_unification too many times. */ |
| static bool excessive_deduction_depth; |
| |
| struct spec_hasher : ggc_ptr_hash<spec_entry> |
| { |
| static hashval_t hash (spec_entry *); |
| static bool equal (spec_entry *, spec_entry *); |
| }; |
| |
| /* The general template is not in these tables. */ |
| typedef hash_table<spec_hasher> spec_hash_table; |
| static GTY (()) spec_hash_table *decl_specializations; |
| static GTY (()) spec_hash_table *type_specializations; |
| |
| /* Contains canonical template parameter types. The vector is indexed by |
| the TEMPLATE_TYPE_IDX of the template parameter. Each element is a |
| TREE_LIST, whose TREE_VALUEs contain the canonical template |
| parameters of various types and levels. */ |
| static GTY(()) vec<tree, va_gc> *canonical_template_parms; |
| |
| #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 |
| |
| enum template_base_result { |
| tbr_incomplete_type, |
| tbr_ambiguous_baseclass, |
| tbr_success |
| }; |
| |
| static bool resolve_overloaded_unification (tree, tree, tree, tree, |
| unification_kind_t, int, |
| bool); |
| static int try_one_overload (tree, tree, tree, tree, tree, |
| unification_kind_t, int, bool, bool); |
| 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_partial_spec_bindings (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, |
| bool, bool); |
| static void tsubst_enum (tree, tree, tree); |
| static bool check_instantiated_args (tree, tree, tsubst_flags_t); |
| static int check_non_deducible_conversion (tree, tree, unification_kind_t, int, |
| struct conversion **, bool); |
| static int maybe_adjust_types_for_deduction (tree, unification_kind_t, |
| tree*, tree*, tree); |
| static int type_unification_real (tree, tree, tree, const tree *, |
| unsigned int, int, unification_kind_t, |
| vec<deferred_access_check, va_gc> **, |
| bool); |
| static void note_template_header (int); |
| static tree convert_nontype_argument_function (tree, tree, tsubst_flags_t); |
| static tree convert_nontype_argument (tree, tree, tsubst_flags_t); |
| static tree convert_template_argument (tree, tree, tree, |
| tsubst_flags_t, int, tree); |
| static tree for_each_template_parm (tree, tree_fn_t, void*, |
| hash_set<tree> *, bool, tree_fn_t = NULL); |
| static tree expand_template_argument_pack (tree); |
| static tree build_template_parm_index (int, int, int, tree, tree); |
| static bool inline_needs_template_parms (tree, bool); |
| static void push_inline_template_parms_recursive (tree, int); |
| static tree reduce_template_parm_level (tree, tree, int, tree, tsubst_flags_t); |
| 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, bool); |
| static int template_decl_level (tree); |
| static int check_cv_quals_for_unify (int, tree, tree); |
| static int unify_pack_expansion (tree, tree, tree, |
| tree, unification_kind_t, bool, bool); |
| static tree copy_template_args (tree); |
| static tree tsubst_template_parms (tree, tree, tsubst_flags_t); |
| 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); |
| static bool check_specialization_scope (void); |
| static tree process_partial_specialization (tree); |
| static enum template_base_result get_template_base (tree, tree, tree, tree, |
| bool , tree *); |
| static tree try_class_unification (tree, tree, tree, tree, bool); |
| static bool class_nttp_const_wrapper_p (tree t); |
| static int coerce_template_template_parms (tree, tree, tsubst_flags_t, |
| tree, tree); |
| static bool template_template_parm_bindings_ok_p (tree, tree); |
| static void tsubst_default_arguments (tree, tsubst_flags_t); |
| 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 bool invalid_nontype_parm_type_p (tree, tsubst_flags_t); |
| static bool dependent_template_arg_p (tree); |
| static bool any_template_arguments_need_structural_equality_p (tree); |
| static bool dependent_type_p_r (tree); |
| static tree tsubst_copy (tree, tree, tsubst_flags_t, tree); |
| static tree tsubst_decl (tree, tree, tsubst_flags_t); |
| static void perform_instantiation_time_access_checks (tree, tree); |
| static tree listify (tree); |
| static tree listify_autos (tree, tree); |
| static tree tsubst_template_parm (tree, tree, tsubst_flags_t); |
| static tree instantiate_alias_template (tree, tree, tsubst_flags_t); |
| static bool complex_alias_template_p (const_tree tmpl); |
| static tree get_underlying_template (tree); |
| static tree tsubst_attributes (tree, tree, tsubst_flags_t, tree); |
| static tree canonicalize_expr_argument (tree, tsubst_flags_t); |
| static tree make_argument_pack (tree); |
| static void register_parameter_specializations (tree, tree); |
| static tree enclosing_instantiation_of (tree tctx); |
| static void instantiate_body (tree pattern, tree args, tree d, bool nested); |
| |
| /* Make the current scope suitable for access checking when we are |
| processing T. T can be FUNCTION_DECL for instantiated function |
| template, VAR_DECL for static member variable, or TYPE_DECL for |
| for a class or alias template (needed by instantiate_decl). */ |
| |
| void |
| push_access_scope (tree t) |
| { |
| gcc_assert (VAR_OR_FUNCTION_DECL_P (t) |
| || TREE_CODE (t) == TYPE_DECL); |
| |
| if (DECL_FRIEND_CONTEXT (t)) |
| push_nested_class (DECL_FRIEND_CONTEXT (t)); |
| else if (DECL_IMPLICIT_TYPEDEF_P (t) |
| && CLASS_TYPE_P (TREE_TYPE (t))) |
| push_nested_class (TREE_TYPE (t)); |
| else if (DECL_CLASS_SCOPE_P (t)) |
| push_nested_class (DECL_CONTEXT (t)); |
| else if (deduction_guide_p (t) && DECL_ARTIFICIAL (t)) |
| /* An artificial deduction guide should have the same access as |
| the constructor. */ |
| push_nested_class (TREE_TYPE (TREE_TYPE (t))); |
| else |
| push_to_top_level (); |
| |
| if (TREE_CODE (t) == FUNCTION_DECL) |
| { |
| vec_safe_push (saved_access_scope, current_function_decl); |
| current_function_decl = t; |
| } |
| } |
| |
| /* Restore the scope set up by push_access_scope. T is the node we |
| are processing. */ |
| |
| void |
| pop_access_scope (tree t) |
| { |
| if (TREE_CODE (t) == FUNCTION_DECL) |
| current_function_decl = saved_access_scope->pop(); |
| |
| if (DECL_FRIEND_CONTEXT (t) |
| || (DECL_IMPLICIT_TYPEDEF_P (t) |
| && CLASS_TYPE_P (TREE_TYPE (t))) |
| || DECL_CLASS_SCOPE_P (t) |
| || (deduction_guide_p (t) && DECL_ARTIFICIAL (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 (type == error_mark_node) |
| return error_mark_node; |
| if (MAYBE_CLASS_TYPE_P (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_at (DECL_SOURCE_LOCATION (decl), |
| "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_at (DECL_SOURCE_LOCATION (decl), |
| "invalid member template declaration %qD", decl); |
| |
| return error_mark_node; |
| } |
| |
| /* Create a template info node. */ |
| |
| tree |
| build_template_info (tree template_decl, tree template_args) |
| { |
| tree result = make_node (TEMPLATE_INFO); |
| TI_TEMPLATE (result) = template_decl; |
| TI_ARGS (result) = template_args; |
| return result; |
| } |
| |
| /* Return the template info node corresponding to T, whatever T is. */ |
| |
| tree |
| get_template_info (const_tree t) |
| { |
| tree tinfo = NULL_TREE; |
| |
| if (!t || t == error_mark_node) |
| return NULL; |
| |
| if (TREE_CODE (t) == NAMESPACE_DECL |
| || TREE_CODE (t) == PARM_DECL) |
| return NULL; |
| |
| if (DECL_P (t) && DECL_LANG_SPECIFIC (t)) |
| tinfo = DECL_TEMPLATE_INFO (t); |
| |
| if (!tinfo && DECL_IMPLICIT_TYPEDEF_P (t)) |
| t = TREE_TYPE (t); |
| |
| if (OVERLOAD_TYPE_P (t)) |
| tinfo = TYPE_TEMPLATE_INFO (t); |
| else if (TREE_CODE (t) == BOUND_TEMPLATE_TEMPLATE_PARM) |
| tinfo = TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t); |
| |
| return tinfo; |
| } |
| |
| /* Returns the template nesting level of the indicated class TYPE. |
| |
| For example, in: |
| template <class T> |
| struct A |
| { |
| template <class U> |
| struct B {}; |
| }; |
| |
| A<T>::B<U> has depth two, while A<T> has depth one. |
| Both A<T>::B<int> and A<int>::B<U> have depth one, 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. */ |
| |
| int |
| template_class_depth (tree type) |
| { |
| int depth; |
| |
| for (depth = 0; type && TREE_CODE (type) != NAMESPACE_DECL; ) |
| { |
| tree tinfo = get_template_info (type); |
| |
| if (tinfo && PRIMARY_TEMPLATE_P (TI_TEMPLATE (tinfo)) |
| && uses_template_parms (INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo)))) |
| ++depth; |
| |
| if (DECL_P (type)) |
| { |
| if (tree fctx = DECL_FRIEND_CONTEXT (type)) |
| type = fctx; |
| else |
| type = CP_DECL_CONTEXT (type); |
| } |
| else if (LAMBDA_TYPE_P (type) && LAMBDA_TYPE_EXTRA_SCOPE (type)) |
| type = LAMBDA_TYPE_EXTRA_SCOPE (type); |
| else |
| type = CP_TYPE_CONTEXT (type); |
| } |
| |
| return depth; |
| } |
| |
| /* Return TRUE if NODE instantiates a template that has arguments of |
| its own, be it directly a primary template or indirectly through a |
| partial specializations. */ |
| static bool |
| instantiates_primary_template_p (tree node) |
| { |
| tree tinfo = get_template_info (node); |
| if (!tinfo) |
| return false; |
| |
| tree tmpl = TI_TEMPLATE (tinfo); |
| if (PRIMARY_TEMPLATE_P (tmpl)) |
| return true; |
| |
| if (!DECL_TEMPLATE_SPECIALIZATION (tmpl)) |
| return false; |
| |
| /* So now we know we have a specialization, but it could be a full |
| or a partial specialization. To tell which, compare the depth of |
| its template arguments with those of its context. */ |
| |
| tree ctxt = DECL_CONTEXT (tmpl); |
| tree ctinfo = get_template_info (ctxt); |
| if (!ctinfo) |
| return true; |
| |
| return (TMPL_ARGS_DEPTH (TI_ARGS (tinfo)) |
| > TMPL_ARGS_DEPTH (TI_ARGS (ctinfo))); |
| } |
| |
| /* Subroutine of maybe_begin_member_template_processing. |
| Returns true if processing DECL needs us to push template parms. */ |
| |
| static bool |
| inline_needs_template_parms (tree decl, bool nsdmi) |
| { |
| if (!decl || (!nsdmi && ! DECL_TEMPLATE_INFO (decl))) |
| return false; |
| |
| return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (most_general_template (decl))) |
| > (current_template_depth + 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 (current_template_depth + 1), |
| 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)); |
| |
| if (error_operand_p (parm)) |
| continue; |
| |
| gcc_assert (DECL_P (parm)); |
| |
| switch (TREE_CODE (parm)) |
| { |
| case TYPE_DECL: |
| case TEMPLATE_DECL: |
| pushdecl (parm); |
| break; |
| |
| case PARM_DECL: |
| /* Push the CONST_DECL. */ |
| pushdecl (TEMPLATE_PARM_DECL (DECL_INITIAL (parm))); |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| } |
| } |
| |
| /* Restore the template parameter context for a member template, a |
| friend template defined in a class definition, or a non-template |
| member of template class. */ |
| |
| void |
| maybe_begin_member_template_processing (tree decl) |
| { |
| tree parms; |
| int levels = 0; |
| bool nsdmi = TREE_CODE (decl) == FIELD_DECL; |
| |
| if (nsdmi) |
| { |
| tree ctx = DECL_CONTEXT (decl); |
| decl = (CLASSTYPE_TEMPLATE_INFO (ctx) |
| /* Disregard full specializations (c++/60999). */ |
| && uses_template_parms (ctx) |
| ? CLASSTYPE_TI_TEMPLATE (ctx) : NULL_TREE); |
| } |
| |
| if (inline_needs_template_parms (decl, nsdmi)) |
| { |
| parms = DECL_TEMPLATE_PARMS (most_general_template (decl)); |
| levels = TMPL_PARMS_DEPTH (parms) - current_template_depth; |
| |
| 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. */ |
| inline_parm_levels.safe_push (levels); |
| } |
| |
| /* Undo the effects of maybe_begin_member_template_processing. */ |
| |
| void |
| maybe_end_member_template_processing (void) |
| { |
| int i; |
| int last; |
| |
| if (inline_parm_levels.length () == 0) |
| return; |
| |
| last = inline_parm_levels.pop (); |
| for (i = 0; i < last; ++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. */ |
| |
| tree |
| add_to_template_args (tree args, tree extra_args) |
| { |
| tree new_args; |
| int extra_depth; |
| int i; |
| int j; |
| |
| if (args == NULL_TREE || extra_args == error_mark_node) |
| return extra_args; |
| |
| 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. |
| |
| If ARGS is a TEMPLATE_DECL, use its parameters as args. */ |
| |
| tree |
| add_outermost_template_args (tree args, tree extra_args) |
| { |
| tree new_args; |
| |
| if (!args) |
| return extra_args; |
| if (TREE_CODE (args) == TEMPLATE_DECL) |
| { |
| tree ti = get_template_info (DECL_TEMPLATE_RESULT (args)); |
| args = TI_ARGS (ti); |
| } |
| |
| /* 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; |
| } |
| |
| /* The inverse of get_innermost_template_args: Return all but the innermost |
| EXTRA_LEVELS levels of template arguments from the ARGS. */ |
| |
| static tree |
| strip_innermost_template_args (tree args, int extra_levels) |
| { |
| tree new_args; |
| int n = TMPL_ARGS_DEPTH (args) - extra_levels; |
| int i; |
| |
| gcc_assert (n >= 0); |
| |
| /* If N is 1, just return the outermost set of template arguments. */ |
| if (n == 1) |
| return TMPL_ARGS_LEVEL (args, 1); |
| |
| /* If we're not removing anything, just return the arguments we were |
| given. */ |
| gcc_assert (extra_levels >= 0); |
| if (extra_levels == 0) |
| return args; |
| |
| /* Make a new set of arguments, not containing the inner 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)); |
| |
| 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 <class T> struct S1 { |
| template <class T> struct S2 {}; |
| }; |
| |
| pushtag contains special code to insert the TEMPLATE_DECL for S2 |
| at the right scope. */ |
| begin_scope (sk_template_parms, NULL); |
| ++processing_template_decl; |
| ++processing_template_parmlist; |
| note_template_header (0); |
| |
| /* Add a dummy parameter level while we process the parameter list. */ |
| current_template_parms |
| = tree_cons (size_int (current_template_depth + 1), |
| make_tree_vec (0), |
| current_template_parms); |
| } |
| |
| /* This routine is called when a specialization is declared. If it is |
| invalid to declare a specialization here, an error is reported and |
| false is returned, otherwise this routine will return true. */ |
| |
| static bool |
| 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); |
| return false; |
| } |
| |
| /* [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"); |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /* We've just seen template <>. */ |
| |
| bool |
| begin_specialization (void) |
| { |
| begin_scope (sk_template_spec, NULL); |
| note_template_header (1); |
| return 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; |
| } |
| |
| /* An explicit specialization or partial specialization of 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 a namespace enclosing the |
| specialized template. An explicit specialization whose declarator-id is |
| not qualified shall be declared in the nearest enclosing namespace of the |
| template, or, if the namespace is inline (7.3.1), any namespace from its |
| enclosing namespace set. */ |
| if (current_scope() != DECL_CONTEXT (tmpl) |
| && !at_namespace_scope_p ()) |
| { |
| error ("specialization of %qD must appear at namespace scope", tmpl); |
| return false; |
| } |
| |
| if (is_nested_namespace (current_namespace, tpl_ns, cxx_dialect < cxx11)) |
| /* Same or enclosing namespace. */ |
| return true; |
| else |
| { |
| auto_diagnostic_group d; |
| if (permerror (input_location, |
| "specialization of %qD in different namespace", tmpl)) |
| inform (DECL_SOURCE_LOCATION (tmpl), |
| " from definition of %q#D", tmpl); |
| return false; |
| } |
| } |
| |
| /* SPEC is an explicit instantiation. Check that it is valid to |
| perform this explicit instantiation in the current namespace. */ |
| |
| static void |
| check_explicit_instantiation_namespace (tree spec) |
| { |
| tree ns; |
| |
| /* DR 275: An explicit instantiation shall appear in an enclosing |
| namespace of its template. */ |
| ns = decl_namespace_context (spec); |
| if (!is_nested_namespace (current_namespace, ns)) |
| permerror (input_location, "explicit instantiation of %qD in namespace %qD " |
| "(which does not enclose namespace %qD)", |
| spec, current_namespace, ns); |
| } |
| |
| /* Returns the type of a template specialization only if that |
| specialization needs to be defined. Otherwise (e.g., if the type has |
| already been defined), the function returns NULL_TREE. */ |
| |
| static tree |
| maybe_new_partial_specialization (tree type) |
| { |
| /* An implicit instantiation of an incomplete type implies |
| the definition of a new class template. |
| |
| template<typename T> |
| struct S; |
| |
| template<typename T> |
| struct S<T*>; |
| |
| Here, S<T*> is an implicit instantiation of S whose type |
| is incomplete. */ |
| if (CLASSTYPE_IMPLICIT_INSTANTIATION (type) && !COMPLETE_TYPE_P (type)) |
| return type; |
| |
| /* It can also be the case that TYPE is a completed specialization. |
| Continuing the previous example, suppose we also declare: |
| |
| template<typename T> |
| requires Integral<T> |
| struct S<T*>; |
| |
| Here, S<T*> refers to the specialization S<T*> defined |
| above. However, we need to differentiate definitions because |
| we intend to define a new partial specialization. In this case, |
| we rely on the fact that the constraints are different for |
| this declaration than that above. |
| |
| Note that we also get here for injected class names and |
| late-parsed template definitions. We must ensure that we |
| do not create new type declarations for those cases. */ |
| if (flag_concepts && CLASSTYPE_TEMPLATE_SPECIALIZATION (type)) |
| { |
| tree tmpl = CLASSTYPE_TI_TEMPLATE (type); |
| tree args = CLASSTYPE_TI_ARGS (type); |
| |
| /* If there are no template parameters, this cannot be a new |
| partial template specialization? */ |
| if (!current_template_parms) |
| return NULL_TREE; |
| |
| /* The injected-class-name is not a new partial specialization. */ |
| if (DECL_SELF_REFERENCE_P (TYPE_NAME (type))) |
| return NULL_TREE; |
| |
| /* If the constraints are not the same as those of the primary |
| then, we can probably create a new specialization. */ |
| tree type_constr = current_template_constraints (); |
| |
| if (type == TREE_TYPE (tmpl)) |
| { |
| tree main_constr = get_constraints (tmpl); |
| if (equivalent_constraints (type_constr, main_constr)) |
| return NULL_TREE; |
| } |
| |
| /* Also, if there's a pre-existing specialization with matching |
| constraints, then this also isn't new. */ |
| tree specs = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); |
| while (specs) |
| { |
| tree spec_tmpl = TREE_VALUE (specs); |
| tree spec_args = TREE_PURPOSE (specs); |
| tree spec_constr = get_constraints (spec_tmpl); |
| if (comp_template_args (args, spec_args) |
| && equivalent_constraints (type_constr, spec_constr)) |
| return NULL_TREE; |
| specs = TREE_CHAIN (specs); |
| } |
| |
| /* Create a new type node (and corresponding type decl) |
| for the newly declared specialization. */ |
| tree t = make_class_type (TREE_CODE (type)); |
| CLASSTYPE_DECLARED_CLASS (t) = CLASSTYPE_DECLARED_CLASS (type); |
| SET_TYPE_TEMPLATE_INFO (t, build_template_info (tmpl, args)); |
| |
| /* We only need a separate type node for storing the definition of this |
| partial specialization; uses of S<T*> are unconstrained, so all are |
| equivalent. So keep TYPE_CANONICAL the same. */ |
| TYPE_CANONICAL (t) = TYPE_CANONICAL (type); |
| |
| /* Build the corresponding type decl. */ |
| tree d = create_implicit_typedef (DECL_NAME (tmpl), t); |
| DECL_CONTEXT (d) = TYPE_CONTEXT (t); |
| DECL_SOURCE_LOCATION (d) = input_location; |
| TREE_PRIVATE (d) = (current_access_specifier == access_private_node); |
| TREE_PROTECTED (d) = (current_access_specifier == access_protected_node); |
| |
| set_instantiating_module (d); |
| DECL_MODULE_EXPORT_P (d) = DECL_MODULE_EXPORT_P (tmpl); |
| |
| return t; |
| } |
| |
| return NULL_TREE; |
| } |
| |
| /* The TYPE is being declared. If it is a template type, that means it |
| is a partial specialization. Do appropriate error-checking. */ |
| |
| tree |
| maybe_process_partial_specialization (tree type) |
| { |
| tree context; |
| |
| if (type == error_mark_node) |
| return error_mark_node; |
| |
| /* A lambda that appears in specialization context is not itself a |
| specialization. */ |
| if (CLASS_TYPE_P (type) && CLASSTYPE_LAMBDA_EXPR (type)) |
| return type; |
| |
| /* An injected-class-name is not a specialization. */ |
| if (DECL_SELF_REFERENCE_P (TYPE_NAME (type))) |
| return type; |
| |
| if (TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM) |
| { |
| error ("name of class shadows template template parameter %qD", |
| TYPE_NAME (type)); |
| return error_mark_node; |
| } |
| |
| context = TYPE_CONTEXT (type); |
| |
| if (TYPE_ALIAS_P (type)) |
| { |
| tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (type); |
| |
| if (tinfo && DECL_ALIAS_TEMPLATE_P (TI_TEMPLATE (tinfo))) |
| error ("specialization of alias template %qD", |
| TI_TEMPLATE (tinfo)); |
| else |
| error ("explicit specialization of non-template %qT", type); |
| return error_mark_node; |
| } |
| else 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<int>; |
| |
| or: |
| |
| template <class T> class C<T*>; |
| |
| Make sure that `C<int>' and `C<T*>' are implicit instantiations. */ |
| |
| if (tree t = maybe_new_partial_specialization (type)) |
| { |
| if (!check_specialization_namespace (CLASSTYPE_TI_TEMPLATE (t)) |
| && !at_namespace_scope_p ()) |
| return error_mark_node; |
| SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t); |
| DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (t)) = input_location; |
| if (processing_template_decl) |
| { |
| tree decl = push_template_decl (TYPE_MAIN_DECL (t)); |
| if (decl == error_mark_node) |
| return error_mark_node; |
| return TREE_TYPE (decl); |
| } |
| } |
| else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type)) |
| error ("specialization of %qT after instantiation", type); |
| else if (errorcount && !processing_specialization |
| && CLASSTYPE_TEMPLATE_SPECIALIZATION (type) |
| && !uses_template_parms (CLASSTYPE_TI_ARGS (type))) |
| /* Trying to define a specialization either without a template<> header |
| or in an inappropriate place. We've already given an error, so just |
| bail now so we don't actually define the specialization. */ |
| return error_mark_node; |
| } |
| 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 U> class C<int>::D; |
| |
| The context `C<int>' must be an implicit instantiation. |
| Otherwise this is just a member class template declared |
| earlier like: |
| |
| template <> class C<int> { template <class U> class D; }; |
| template <> template <class U> class C<int>::D; |
| |
| In the first case, `C<int>::D' is a specialization of `C<T>::D' |
| while in the second case, `C<int>::D' is a primary template |
| and `C<T>::D' may not exist. */ |
| |
| if (CLASSTYPE_IMPLICIT_INSTANTIATION (context) |
| && !COMPLETE_TYPE_P (type)) |
| { |
| tree t; |
| tree tmpl = CLASSTYPE_TI_TEMPLATE (type); |
| |
| if (current_namespace |
| != decl_namespace_context (tmpl)) |
| { |
| if (permerror (input_location, |
| "specialization of %qD in different namespace", |
| type)) |
| inform (DECL_SOURCE_LOCATION (tmpl), |
| "from definition of %q#D", tmpl); |
| } |
| |
| /* Check for invalid specialization after instantiation: |
| |
| template <> template <> class C<int>::D<int>; |
| template <> template <class U> class C<int>::D; */ |
| |
| for (t = DECL_TEMPLATE_INSTANTIATIONS (tmpl); |
| t; t = TREE_CHAIN (t)) |
| { |
| tree inst = TREE_VALUE (t); |
| if (CLASSTYPE_TEMPLATE_SPECIALIZATION (inst) |
| || !COMPLETE_OR_OPEN_TYPE_P (inst)) |
| { |
| /* We already have a full specialization of this partial |
| instantiation, or a full specialization has been |
| looked up but not instantiated. Reassign it to the |
| new member specialization template. */ |
| spec_entry elt; |
| spec_entry *entry; |
| |
| elt.tmpl = most_general_template (tmpl); |
| elt.args = CLASSTYPE_TI_ARGS (inst); |
| elt.spec = inst; |
| |
| type_specializations->remove_elt (&elt); |
| |
| elt.tmpl = tmpl; |
| CLASSTYPE_TI_ARGS (inst) |
| = elt.args = INNERMOST_TEMPLATE_ARGS (elt.args); |
| |
| spec_entry **slot |
| = type_specializations->find_slot (&elt, INSERT); |
| entry = ggc_alloc<spec_entry> (); |
| *entry = elt; |
| *slot = entry; |
| } |
| else |
| /* But if we've had an implicit instantiation, that's a |
| problem ([temp.expl.spec]/6). */ |
| error ("specialization %qT after instantiation %qT", |
| type, inst); |
| } |
| |
| /* 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); |
| DECL_SOURCE_LOCATION (TYPE_MAIN_DECL (type)) = input_location; |
| CLASSTYPE_TI_ARGS (type) |
| = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type)); |
| } |
| } |
| else if (processing_specialization) |
| { |
| /* Someday C++0x may allow for enum template specialization. */ |
| if (cxx_dialect > cxx98 && TREE_CODE (type) == ENUMERAL_TYPE |
| && CLASS_TYPE_P (context) && CLASSTYPE_USE_TEMPLATE (context)) |
| pedwarn (input_location, OPT_Wpedantic, "template specialization " |
| "of %qD not allowed by ISO C++", type); |
| else |
| { |
| error ("explicit specialization of non-template %qT", type); |
| return error_mark_node; |
| } |
| } |
| |
| return 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 <typename T> |
| 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_UNIQUE_FRIEND_P (DECL_TEMPLATE_RESULT (tmpl))); |
| } |
| |
| /* Make sure ARGS doesn't use any inappropriate typedefs; we should have |
| gone through coerce_template_parms by now. */ |
| |
| static void |
| verify_unstripped_args_1 (tree inner) |
| { |
| for (int i = 0; i < TREE_VEC_LENGTH (inner); ++i) |
| { |
| tree arg = TREE_VEC_ELT (inner, i); |
| if (TREE_CODE (arg) == TEMPLATE_DECL) |
| /* OK */; |
| else if (TYPE_P (arg)) |
| gcc_assert (strip_typedefs (arg, NULL) == arg); |
| else if (ARGUMENT_PACK_P (arg)) |
| verify_unstripped_args_1 (ARGUMENT_PACK_ARGS (arg)); |
| else if (strip_typedefs (TREE_TYPE (arg), NULL) != TREE_TYPE (arg)) |
| /* Allow typedefs on the type of a non-type argument, since a |
| parameter can have them. */; |
| else |
| gcc_assert (strip_typedefs_expr (arg, NULL) == arg); |
| } |
| } |
| |
| static void |
| verify_unstripped_args (tree args) |
| { |
| ++processing_template_decl; |
| if (!any_dependent_template_arguments_p (args)) |
| verify_unstripped_args_1 (INNERMOST_TEMPLATE_ARGS (args)); |
| --processing_template_decl; |
| } |
| |
| /* 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. |
| |
| We can also look up a FIELD_DECL, if it is a lambda capture pack; the |
| result is a NONTYPE_ARGUMENT_PACK. */ |
| |
| static tree |
| retrieve_specialization (tree tmpl, tree args, hashval_t hash) |
| { |
| if (tmpl == NULL_TREE) |
| return NULL_TREE; |
| |
| if (args == error_mark_node) |
| return NULL_TREE; |
| |
| gcc_assert (TREE_CODE (tmpl) == TEMPLATE_DECL |
| || TREE_CODE (tmpl) == FIELD_DECL); |
| |
| /* There should be as many levels of arguments as there are |
| levels of parameters. */ |
| gcc_assert (TMPL_ARGS_DEPTH (args) |
| == (TREE_CODE (tmpl) == TEMPLATE_DECL |
| ? TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)) |
| : template_class_depth (DECL_CONTEXT (tmpl)))); |
| |
| if (flag_checking) |
| verify_unstripped_args (args); |
| |
| /* Lambda functions in templates aren't instantiated normally, but through |
| tsubst_lambda_expr. */ |
| if (lambda_fn_in_template_p (tmpl)) |
| return NULL_TREE; |
| |
| if (optimize_specialization_lookup_p (tmpl)) |
| { |
| /* The template arguments actually apply to the containing |
| class. Find the class specialization with those |
| arguments. */ |
| tree class_template = CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (tmpl)); |
| tree class_specialization |
| = retrieve_specialization (class_template, args, 0); |
| if (!class_specialization) |
| return NULL_TREE; |
| |
| /* Find the instance of TMPL. */ |
| tree fns = get_class_binding (class_specialization, DECL_NAME (tmpl)); |
| for (ovl_iterator iter (fns); iter; ++iter) |
| { |
| tree fn = *iter; |
| if (tree ti = get_template_info (fn)) |
| if (TI_TEMPLATE (ti) == tmpl |
| /* using-declarations can bring in a different |
| instantiation of tmpl as a member of a different |
| instantiation of tmpl's class. We don't want those |
| here. */ |
| && DECL_CONTEXT (fn) == class_specialization) |
| return fn; |
| } |
| return NULL_TREE; |
| } |
| else |
| { |
| spec_entry *found; |
| spec_entry elt; |
| spec_hash_table *specializations; |
| |
| elt.tmpl = tmpl; |
| elt.args = args; |
| elt.spec = NULL_TREE; |
| |
| if (DECL_CLASS_TEMPLATE_P (tmpl)) |
| specializations = type_specializations; |
| else |
| specializations = decl_specializations; |
| |
| if (hash == 0) |
| hash = spec_hasher::hash (&elt); |
| found = specializations->find_with_hash (&elt, hash); |
| if (found) |
| return found->spec; |
| } |
| |
| return NULL_TREE; |
| } |
| |
| /* Like retrieve_specialization, but for local declarations. */ |
| |
| tree |
| retrieve_local_specialization (tree tmpl) |
| { |
| if (local_specializations == NULL) |
| return NULL_TREE; |
| |
| tree *slot = local_specializations->get (tmpl); |
| return slot ? *slot : 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_DECL according to [temp.friend]. */ |
| |
| bool |
| is_specialization_of_friend (tree decl, tree friend_decl) |
| { |
| 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_DECL is an ordinary member function |
| of a template class, we want to check if DECL is a specialization |
| if this. */ |
| if (TREE_CODE (friend_decl) == FUNCTION_DECL |
| && DECL_TEMPLATE_INFO (friend_decl) |
| && !DECL_USE_TEMPLATE (friend_decl)) |
| { |
| /* We want a TEMPLATE_DECL for `is_specialization_of'. */ |
| friend_decl = DECL_TI_TEMPLATE (friend_decl); |
| need_template = false; |
| } |
| else if (TREE_CODE (friend_decl) == TEMPLATE_DECL |
| && !PRIMARY_TEMPLATE_P (friend_decl)) |
| need_template = false; |
| |
| /* There is nothing to do if this is not a template friend. */ |
| if (TREE_CODE (friend_decl) != TEMPLATE_DECL) |
| return false; |
| |
| if (is_specialization_of (decl, friend_decl)) |
| 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 <class T> friend void A<T>::f(); |
| |
| the member function below is considered a friend |
| |
| template <> struct A<int> { |
| 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 (CP_DECL_CONTEXT (friend_decl)); |
| if (template_depth |
| && DECL_CLASS_SCOPE_P (decl) |
| && is_specialization_of (TYPE_NAME (DECL_CONTEXT (decl)), |
| CLASSTYPE_TI_TEMPLATE (DECL_CONTEXT (friend_decl)))) |
| { |
| /* Next, we check the members themselves. In order to handle |
| a few tricky cases, such as when FRIEND_DECL's are |
| |
| template <class T> friend void A<T>::g(T t); |
| template <class T> template <T t> friend void A<T>::h(); |
| |
| and DECL's are |
| |
| void A<int>::g(int); |
| template <int> void A<int>::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_DECL 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_decl), |
| 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_decl), 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_decl)) |
| 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_DECL 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_decl)) |
| return false; |
| |
| /* Now check template parameter list. */ |
| friend_parms |
| = tsubst_template_parms (DECL_TEMPLATE_PARMS (friend_decl), |
| 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_decl)); |
| } |
| } |
| return false; |
| } |
| |
| /* Register the specialization SPEC as a specialization of TMPL with |
| the indicated ARGS. IS_FRIEND indicates whether the specialization |
| is actually just a friend declaration. ATTRLIST is the list of |
| attributes that the specialization is declared with or NULL when |
| it isn't. Returns SPEC, or an equivalent prior declaration, if |
| available. |
| |
| We also store instantiations of field packs in the hash table, even |
| though they are not themselves templates, to make lookup easier. */ |
| |
| static tree |
| register_specialization (tree spec, tree tmpl, tree args, bool is_friend, |
| hashval_t hash) |
| { |
| tree fn; |
| spec_entry **slot = NULL; |
| spec_entry elt; |
| |
| gcc_assert ((TREE_CODE (tmpl) == TEMPLATE_DECL && DECL_P (spec)) |
| || (TREE_CODE (tmpl) == FIELD_DECL |
| && TREE_CODE (spec) == NONTYPE_ARGUMENT_PACK)); |
| |
| 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 <class T> 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; |
| |
| if (optimize_specialization_lookup_p (tmpl)) |
| /* We don't put these specializations in the hash table, but we might |
| want to give an error about a mismatch. */ |
| fn = retrieve_specialization (tmpl, args, 0); |
| else |
| { |
| elt.tmpl = tmpl; |
| elt.args = args; |
| elt.spec = spec; |
| |
| if (hash == 0) |
| hash = spec_hasher::hash (&elt); |
| |
| slot = decl_specializations->find_slot_with_hash (&elt, hash, INSERT); |
| if (*slot) |
| fn = (*slot)->spec; |
| else |
| fn = NULL_TREE; |
| } |
| |
| /* 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 (DECL_ODR_USED (fn) |
| || DECL_EXPLICIT_INSTANTIATION (fn)) |
| { |
| error ("specialization of %qD after instantiation", |
| fn); |
| return error_mark_node; |
| } |
| else |
| { |
| tree clone; |
| /* 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 <class T> 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, /*hiding=*/is_friend); |
| /* The call to duplicate_decls will have applied |
| [temp.expl.spec]: |
| |
| An explicit specialization of a function template |
| is inline only if it is explicitly declared to be, |
| and independently of whether its function template |
| is. |
| |
| to the primary function; now copy the inline bits to |
| the various clones. */ |
| FOR_EACH_CLONE (clone, fn) |
| { |
| DECL_DECLARED_INLINE_P (clone) |
| = DECL_DECLARED_INLINE_P (fn); |
| DECL_SOURCE_LOCATION (clone) |
| = DECL_SOURCE_LOCATION (fn); |
| DECL_DELETED_FN (clone) |
| = DECL_DELETED_FN (fn); |
| } |
| check_specialization_namespace (tmpl); |
| |
| return fn; |
| } |
| } |
| else if (DECL_TEMPLATE_SPECIALIZATION (fn)) |
| { |
| tree dd = duplicate_decls (spec, fn, /*hiding=*/is_friend); |
| if (dd == error_mark_node) |
| /* We've already complained in duplicate_decls. */ |
| return error_mark_node; |
| |
| if (dd == NULL_TREE && 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; |
| } |
| } |
| else if (fn) |
| return duplicate_decls (spec, fn, /*hiding=*/is_friend); |
| |
| /* A specialization must be declared in the same namespace as the |
| template it is specializing. */ |
| if (DECL_P (spec) && DECL_TEMPLATE_SPECIALIZATION (spec) |
| && !check_specialization_namespace (tmpl)) |
| DECL_CONTEXT (spec) = DECL_CONTEXT (tmpl); |
| |
| if (slot != NULL /* !optimize_specialization_lookup_p (tmpl) */) |
| { |
| spec_entry *entry = ggc_alloc<spec_entry> (); |
| 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) |
| || 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. |
| |
| 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)); |
| } |
| |
| return spec; |
| } |
| |
| /* Restricts tree and type comparisons. */ |
| int comparing_specializations; |
| int comparing_dependent_aliases; |
| |
| /* Returns true iff two spec_entry nodes are equivalent. */ |
| |
| bool |
| spec_hasher::equal (spec_entry *e1, spec_entry *e2) |
| { |
| int equal; |
| |
| ++comparing_specializations; |
| ++comparing_dependent_aliases; |
| ++processing_template_decl; |
| equal = (e1->tmpl == e2->tmpl |
| && comp_template_args (e1->args, e2->args)); |
| if (equal && flag_concepts |
| /* tmpl could be a FIELD_DECL for a capture pack. */ |
| && TREE_CODE (e1->tmpl) == TEMPLATE_DECL |
| && VAR_P (DECL_TEMPLATE_RESULT (e1->tmpl)) |
| && uses_template_parms (e1->args)) |
| { |
| /* Partial specializations of a variable template can be distinguished by |
| constraints. */ |
| tree c1 = e1->spec ? get_constraints (e1->spec) : NULL_TREE; |
| tree c2 = e2->spec ? get_constraints (e2->spec) : NULL_TREE; |
| equal = equivalent_constraints (c1, c2); |
| } |
| --processing_template_decl; |
| --comparing_dependent_aliases; |
| --comparing_specializations; |
| |
| return equal; |
| } |
| |
| /* Returns a hash for a template TMPL and template arguments ARGS. */ |
| |
| static hashval_t |
| hash_tmpl_and_args (tree tmpl, tree args) |
| { |
| hashval_t val = iterative_hash_object (DECL_UID (tmpl), 0); |
| return iterative_hash_template_arg (args, val); |
| } |
| |
| /* Returns a hash for a spec_entry node based on the TMPL and ARGS members, |
| ignoring SPEC. */ |
| |
| hashval_t |
| spec_hasher::hash (spec_entry *e) |
| { |
| return hash_tmpl_and_args (e->tmpl, e->args); |
| } |
| |
| /* Recursively calculate a hash value for a template argument ARG, for use |
| in the hash tables of template specializations. We must be |
| careful to (at least) skip the same entities template_args_equal |
| does. */ |
| |
| hashval_t |
| iterative_hash_template_arg (tree arg, hashval_t val) |
| { |
| if (arg == NULL_TREE) |
| return iterative_hash_object (arg, val); |
| |
| if (!TYPE_P (arg)) |
| /* Strip nop-like things, but not the same as STRIP_NOPS. */ |
| while (CONVERT_EXPR_P (arg) |
| || TREE_CODE (arg) == NON_LVALUE_EXPR |
| || class_nttp_const_wrapper_p (arg)) |
| arg = TREE_OPERAND (arg, 0); |
| |
| enum tree_code code = TREE_CODE (arg); |
| |
| val = iterative_hash_object (code, val); |
| |
| switch (code) |
| { |
| case ARGUMENT_PACK_SELECT: |
| /* Getting here with an ARGUMENT_PACK_SELECT means we're probably |
| preserving it in a hash table, which is bad because it will change |
| meaning when gen_elem_of_pack_expansion_instantiation changes the |
| ARGUMENT_PACK_SELECT_INDEX. */ |
| gcc_unreachable (); |
| |
| case ERROR_MARK: |
| return val; |
| |
| case IDENTIFIER_NODE: |
| return iterative_hash_object (IDENTIFIER_HASH_VALUE (arg), val); |
| |
| case TREE_VEC: |
| for (int i = 0, len = TREE_VEC_LENGTH (arg); i < len; ++i) |
| val = iterative_hash_template_arg (TREE_VEC_ELT (arg, i), val); |
| return val; |
| |
| case TYPE_PACK_EXPANSION: |
| case EXPR_PACK_EXPANSION: |
| val = iterative_hash_template_arg (PACK_EXPANSION_PATTERN (arg), val); |
| return iterative_hash_template_arg (PACK_EXPANSION_EXTRA_ARGS (arg), val); |
| |
| case TYPE_ARGUMENT_PACK: |
| case NONTYPE_ARGUMENT_PACK: |
| return iterative_hash_template_arg (ARGUMENT_PACK_ARGS (arg), val); |
| |
| case TREE_LIST: |
| for (; arg; arg = TREE_CHAIN (arg)) |
| val = iterative_hash_template_arg (TREE_VALUE (arg), val); |
| return val; |
| |
| case OVERLOAD: |
| for (lkp_iterator iter (arg); iter; ++iter) |
| val = iterative_hash_template_arg (*iter, val); |
| return val; |
| |
| case CONSTRUCTOR: |
| { |
| iterative_hash_template_arg (TREE_TYPE (arg), val); |
| for (auto &e: CONSTRUCTOR_ELTS (arg)) |
| { |
| val = iterative_hash_template_arg (e.index, val); |
| val = iterative_hash_template_arg (e.value, val); |
| } |
| return val; |
| } |
| |
| case PARM_DECL: |
| if (!DECL_ARTIFICIAL (arg)) |
| { |
| val = iterative_hash_object (DECL_PARM_INDEX (arg), val); |
| val = iterative_hash_object (DECL_PARM_LEVEL (arg), val); |
| } |
| return iterative_hash_template_arg (TREE_TYPE (arg), val); |
| |
| case TARGET_EXPR: |
| return iterative_hash_template_arg (TARGET_EXPR_INITIAL (arg), val); |
| |
| case PTRMEM_CST: |
| val = iterative_hash_template_arg (PTRMEM_CST_CLASS (arg), val); |
| return iterative_hash_template_arg (PTRMEM_CST_MEMBER (arg), val); |
| |
| case TEMPLATE_PARM_INDEX: |
| val = iterative_hash_template_arg |
| (TREE_TYPE (TEMPLATE_PARM_DECL (arg)), val); |
| val = iterative_hash_object (TEMPLATE_PARM_LEVEL (arg), val); |
| return iterative_hash_object (TEMPLATE_PARM_IDX (arg), val); |
| |
| case TRAIT_EXPR: |
| val = iterative_hash_object (TRAIT_EXPR_KIND (arg), val); |
| val = iterative_hash_template_arg (TRAIT_EXPR_TYPE1 (arg), val); |
| return iterative_hash_template_arg (TRAIT_EXPR_TYPE2 (arg), val); |
| |
| case BASELINK: |
| val = iterative_hash_template_arg (BINFO_TYPE (BASELINK_BINFO (arg)), |
| val); |
| return iterative_hash_template_arg (DECL_NAME (get_first_fn (arg)), |
| val); |
| |
| case MODOP_EXPR: |
| val = iterative_hash_template_arg (TREE_OPERAND (arg, 0), val); |
| code = TREE_CODE (TREE_OPERAND (arg, 1)); |
| val = iterative_hash_object (code, val); |
| return iterative_hash_template_arg (TREE_OPERAND (arg, 2), val); |
| |
| case LAMBDA_EXPR: |
| /* [temp.over.link] Two lambda-expressions are never considered |
| equivalent. |
| |
| So just hash the closure type. */ |
| return iterative_hash_template_arg (TREE_TYPE (arg), val); |
| |
| case CAST_EXPR: |
| case IMPLICIT_CONV_EXPR: |
| case STATIC_CAST_EXPR: |
| case REINTERPRET_CAST_EXPR: |
| case CONST_CAST_EXPR: |
| case DYNAMIC_CAST_EXPR: |
| case NEW_EXPR: |
| val = iterative_hash_template_arg (TREE_TYPE (arg), val); |
| /* Now hash operands as usual. */ |
| break; |
| |
| case CALL_EXPR: |
| { |
| tree fn = CALL_EXPR_FN (arg); |
| if (tree name = dependent_name (fn)) |
| { |
| if (TREE_CODE (fn) == TEMPLATE_ID_EXPR) |
| val = iterative_hash_template_arg (TREE_OPERAND (fn, 1), val); |
| fn = name; |
| } |
| val = iterative_hash_template_arg (fn, val); |
| call_expr_arg_iterator ai; |
| for (tree x = first_call_expr_arg (arg, &ai); x; |
| x = next_call_expr_arg (&ai)) |
| val = iterative_hash_template_arg (x, val); |
| return val; |
| } |
| |
| default: |
| break; |
| } |
| |
| char tclass = TREE_CODE_CLASS (code); |
| switch (tclass) |
| { |
| case tcc_type: |
| if (tree ats = alias_template_specialization_p (arg, nt_transparent)) |
| { |
| // We want an alias specialization that survived strip_typedefs |
| // to hash differently from its TYPE_CANONICAL, to avoid hash |
| // collisions that compare as different in template_args_equal. |
| // These could be dependent specializations that strip_typedefs |
| // left alone, or untouched specializations because |
| // coerce_template_parms returns the unconverted template |
| // arguments if it sees incomplete argument packs. |
| tree ti = TYPE_ALIAS_TEMPLATE_INFO (ats); |
| return hash_tmpl_and_args (TI_TEMPLATE (ti), TI_ARGS (ti)); |
| } |
| |
| switch (TREE_CODE (arg)) |
| { |
| case TEMPLATE_TEMPLATE_PARM: |
| { |
| tree tpi = TEMPLATE_TYPE_PARM_INDEX (arg); |
| |
| /* Do not recurse with TPI directly, as that is unbounded |
| recursion. */ |
| val = iterative_hash_object (TEMPLATE_PARM_LEVEL (tpi), val); |
| val = iterative_hash_object (TEMPLATE_PARM_IDX (tpi), val); |
| } |
| break; |
| |
| case DECLTYPE_TYPE: |
| val = iterative_hash_template_arg (DECLTYPE_TYPE_EXPR (arg), val); |
| break; |
| |
| default: |
| if (tree canonical = TYPE_CANONICAL (arg)) |
| val = iterative_hash_object (TYPE_HASH (canonical), val); |
| break; |
| } |
| |
| return val; |
| |
| case tcc_declaration: |
| case tcc_constant: |
| return iterative_hash_expr (arg, val); |
| |
| default: |
| gcc_assert (IS_EXPR_CODE_CLASS (tclass)); |
| for (int i = 0, n = cp_tree_operand_length (arg); i < n; ++i) |
| val = iterative_hash_template_arg (TREE_OPERAND (arg, i), val); |
| return val; |
| } |
| } |
| |
| /* 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. |
| |
| Note that SPEC has been ggc_freed, so we can't look inside it. */ |
| |
| bool |
| reregister_specialization (tree spec, tree tinfo, tree new_spec) |
| { |
| spec_entry *entry; |
| spec_entry elt; |
| |
| elt.tmpl = most_general_template (TI_TEMPLATE (tinfo)); |
| elt.args = TI_ARGS (tinfo); |
| elt.spec = NULL_TREE; |
| |
| entry = decl_specializations->find (&elt); |
| if (entry != NULL) |
| { |
| gcc_assert (entry->spec == spec || entry->spec == new_spec); |
| gcc_assert (new_spec != NULL_TREE); |
| entry->spec = new_spec; |
| return 1; |
| } |
| |
| return 0; |
| } |
| |
| /* Like register_specialization, but for local declarations. We are |
| registering SPEC, an instantiation of TMPL. */ |
| |
| void |
| register_local_specialization (tree spec, tree tmpl) |
| { |
| gcc_assert (tmpl != spec); |
| local_specializations->put (tmpl, spec); |
| } |
| |
| /* TYPE is a class type. Returns true if TYPE is an explicitly |
| specialized class. */ |
| |
| bool |
| explicit_class_specialization_p (tree type) |
| { |
| if (!CLASSTYPE_TEMPLATE_SPECIALIZATION (type)) |
| return false; |
| return !uses_template_parms (CLASSTYPE_TI_ARGS (type)); |
| } |
| |
| /* Print the list of functions at FNS, going through all the overloads |
| for each element of the list. Alternatively, FNS cannot be a |
| TREE_LIST, in which case it will be printed together with all the |
| overloads. |
| |
| MORE and *STR should respectively be FALSE and NULL when the function |
| is called from the outside. They are used internally on recursive |
| calls. print_candidates manages the two parameters and leaves NULL |
| in *STR when it ends. */ |
| |
| static void |
| print_candidates_1 (tree fns, char **str, bool more = false) |
| { |
| if (TREE_CODE (fns) == TREE_LIST) |
| for (; fns; fns = TREE_CHAIN (fns)) |
| print_candidates_1 (TREE_VALUE (fns), str, more || TREE_CHAIN (fns)); |
| else |
| for (lkp_iterator iter (fns); iter;) |
| { |
| tree cand = *iter; |
| ++iter; |
| |
| const char *pfx = *str; |
| if (!pfx) |
| { |
| if (more || iter) |
| pfx = _("candidates are:"); |
| else |
| pfx = _("candidate is:"); |
| *str = get_spaces (pfx); |
| } |
| inform (DECL_SOURCE_LOCATION (cand), "%s %#qD", pfx, cand); |
| } |
| } |
| |
| /* Print the list of candidate FNS in an error message. FNS can also |
| be a TREE_LIST of non-functions in the case of an ambiguous lookup. */ |
| |
| void |
| print_candidates (tree fns) |
| { |
| char *str = NULL; |
| print_candidates_1 (fns, &str); |
| free (str); |
| } |
| |
| /* Get a (possibly) constrained template declaration for the |
| purpose of ordering candidates. */ |
| static tree |
| get_template_for_ordering (tree list) |
| { |
| gcc_assert (TREE_CODE (list) == TREE_LIST); |
| tree f = TREE_VALUE (list); |
| if (tree ti = DECL_TEMPLATE_INFO (f)) |
| return TI_TEMPLATE (ti); |
| return f; |
| } |
| |
| /* Among candidates having the same signature, return the |
| most constrained or NULL_TREE if there is no best candidate. |
| If the signatures of candidates vary (e.g., template |
| specialization vs. member function), then there can be no |
| most constrained. |
| |
| Note that we don't compare constraints on the functions |
| themselves, but rather those of their templates. */ |
| static tree |
| most_constrained_function (tree candidates) |
| { |
| // Try to find the best candidate in a first pass. |
| tree champ = candidates; |
| for (tree c = TREE_CHAIN (champ); c; c = TREE_CHAIN (c)) |
| { |
| int winner = more_constrained (get_template_for_ordering (champ), |
| get_template_for_ordering (c)); |
| if (winner == -1) |
| champ = c; // The candidate is more constrained |
| else if (winner == 0) |
| return NULL_TREE; // Neither is more constrained |
| } |
| |
| // Verify that the champ is better than previous candidates. |
| for (tree c = candidates; c != champ; c = TREE_CHAIN (c)) { |
| if (!more_constrained (get_template_for_ordering (champ), |
| get_template_for_ordering (c))) |
| return NULL_TREE; |
| } |
| |
| return champ; |
| } |
| |
| |
| /* 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. |
| |
| TSK indicates what kind of template declaration (if any) is being |
| declared. TSK_TEMPLATE indicates that the declaration given by |
| DECL, though a FUNCTION_DECL, has template parameters, and is |
| therefore a template function. |
| |
| 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, |
| tmpl_spec_kind tsk) |
| { |
| tree fns; |
| tree targs; |
| tree explicit_targs; |
| tree candidates = NULL_TREE; |
| |
| /* A TREE_LIST of templates of which DECL may be a specialization. |
| The TREE_VALUE of each node is a TEMPLATE_DECL. The |
| corresponding TREE_PURPOSE is the set of template arguments that, |
| when used to instantiate the template, would produce a function |
| with the signature of DECL. */ |
| tree templates = NULL_TREE; |
| int header_count; |
| cp_binding_level *b; |
| |
| *targs_out = NULL_TREE; |
| |
| if (template_id == error_mark_node || decl == error_mark_node) |
| return error_mark_node; |
| |
| /* We shouldn't be specializing a member template of an |
| unspecialized class template; we already gave an error in |
| check_specialization_scope, now avoid crashing. */ |
| if (!VAR_P (decl) |
| && template_count && DECL_CLASS_SCOPE_P (decl) |
| && template_class_depth (DECL_CONTEXT (decl)) > 0) |
| { |
| gcc_assert (errorcount); |
| 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 (TREE_CODE (decl) == FUNCTION_DECL && !is_overloaded_fn (fns)) |
| { |
| error_at (DECL_SOURCE_LOCATION (decl), |
| "%qD is not a function template", fns); |
| return error_mark_node; |
| } |
| else if (VAR_P (decl) && !variable_template_p (fns)) |
| { |
| error ("%qD is not a variable 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 = b->level_chain) |
| ++header_count; |
| |
| tree orig_fns = fns; |
| bool header_mismatch = false; |
| |
| if (variable_template_p (fns)) |
| { |
| tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (fns)); |
| targs = coerce_template_parms (parms, explicit_targs, fns, |
| tf_warning_or_error, |
| /*req_all*/true, /*use_defarg*/true); |
| if (targs != error_mark_node |
| && constraints_satisfied_p (fns, targs)) |
| templates = tree_cons (targs, fns, templates); |
| } |
| else for (lkp_iterator iter (fns); iter; ++iter) |
| { |
| tree fn = *iter; |
| |
| if (TREE_CODE (fn) == TEMPLATE_DECL) |
| { |
| tree decl_arg_types; |
| tree fn_arg_types; |
| |
| /* 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<int>::f(int); |
| template <> template <> void A<int>::f(int); |
| |
| Assuming that A<int> 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) |
| { |
| header_mismatch = true; |
| continue; |
| } |
| |
| /* Check that the number of template arguments at the |
| innermost level for DECL is the same as for FN. */ |
| if (current_binding_level->kind == sk_template_parms |
| && !current_binding_level->explicit_spec_p |
| && (TREE_VEC_LENGTH (DECL_INNERMOST_TEMPLATE_PARMS (fn)) |
| != TREE_VEC_LENGTH (INNERMOST_TEMPLATE_PARMS |
| (current_template_parms)))) |
| continue; |
| |
| /* DECL might be a specialization of FN. */ |
| decl_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl)); |
| fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn)); |
| |
| /* For a non-static member function, we need to make sure |
| that the const qualification is the same. Since |
| get_bindings does not try to merge the "this" parameter, |
| we must do the comparison explicitly. */ |
| if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)) |
| { |
| if (!same_type_p (TREE_VALUE (fn_arg_types), |
| TREE_VALUE (decl_arg_types))) |
| continue; |
| |
| /* And the ref-qualification. */ |
| if (type_memfn_rqual (TREE_TYPE (decl)) |
| != type_memfn_rqual (TREE_TYPE (fn))) |
| continue; |
| } |
| |
| /* Skip the "this" parameter and, for constructors of |
| classes with virtual bases, the VTT parameter. A |
| full specialization of a constructor will have a VTT |
| parameter, but a template never will. */ |
| decl_arg_types |
| = skip_artificial_parms_for (decl, decl_arg_types); |
| fn_arg_types |
| = skip_artificial_parms_for (fn, fn_arg_types); |
| |
| /* Function templates cannot be specializations; there are |
| no partial specializations of functions. Therefore, if |
| the type of DECL does not match FN, there is no |
| match. |
| |
| Note that it should never be the case that we have both |
| candidates added here, and for regular member functions |
| below. */ |
| if (tsk == tsk_template) |
| { |
| if (!comp_template_parms (DECL_TEMPLATE_PARMS (fn), |
| current_template_parms)) |
| continue; |
| if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)), |
| TREE_TYPE (TREE_TYPE (fn)))) |
| continue; |
| if (!compparms (fn_arg_types, decl_arg_types)) |
| continue; |
| |
| tree freq = get_trailing_function_requirements (fn); |
| tree dreq = get_trailing_function_requirements (decl); |
| if (!freq != !dreq) |
| continue; |
| if (freq) |
| { |
| /* C++20 CA104: Substitute directly into the |
| constraint-expression. */ |
| tree fargs = DECL_TI_ARGS (fn); |
| tsubst_flags_t complain = tf_none; |
| freq = tsubst_constraint (freq, fargs, complain, fn); |
| if (!cp_tree_equal (freq, dreq)) |
| continue; |
| } |
| |
| candidates = tree_cons (NULL_TREE, fn, candidates); |
| continue; |
| } |
| |
| /* See whether this function might be a specialization of this |
| template. Suppress access control because we might be trying |
| to make this specialization a friend, and we have already done |
| access control for the declaration of the specialization. */ |
| push_deferring_access_checks (dk_no_check); |
| targs = get_bindings (fn, decl, explicit_targs, /*check_ret=*/true); |
| pop_deferring_access_checks (); |
| |
| if (!targs) |
| /* We cannot deduce template arguments that when used to |
| specialize TMPL will produce DECL. */ |
| continue; |
| |
| if (uses_template_parms (targs)) |
| /* We deduced something involving 'auto', which isn't a valid |
| template argument. */ |
| 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 its enclosing class is a |
| template class. For example, |
| |
| template <typename T> struct S { void f(); }; |
| template <> void S<int>::f() {} |
| |
| Here, S<int>::f is a non-template, but S<int> 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)) |
| continue; |
| |
| if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fn) |
| && (type_memfn_rqual (TREE_TYPE (decl)) |
| != type_memfn_rqual (TREE_TYPE (fn)))) |
| continue; |
| |
| // If the deduced arguments do not satisfy the constraints, |
| // this is not a candidate. |
| if (flag_concepts && !constraints_satisfied_p (fn)) |
| continue; |
| |
| // Add the candidate. |
| 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_instantiation (templates); |
| if (tmpl != error_mark_node) |
| { |
| templates = tmpl; |
| TREE_CHAIN (templates) = NULL_TREE; |
| } |
| } |
| |
| // Concepts allows multiple declarations of member functions |
| // with the same signature. Like above, we need to rely on |
| // on the partial ordering of those candidates to determine which |
| // is the best. |
| if (flag_concepts && candidates && TREE_CHAIN (candidates)) |
| { |
| if (tree cand = most_constrained_function (candidates)) |
| { |
| candidates = cand; |
| TREE_CHAIN (cand) = NULL_TREE; |
| } |
| } |
| |
| if (templates == NULL_TREE && candidates == NULL_TREE) |
| { |
| error ("template-id %qD for %q+D does not match any template " |
| "declaration", template_id, decl); |
| if (header_mismatch) |
| inform (DECL_SOURCE_LOCATION (decl), |
| "saw %d %<template<>%>, need %d for " |
| "specializing a member function template", |
| header_count, template_count + 1); |
| print_candidates (orig_fns); |
| return error_mark_node; |
| } |
| else if ((templates && TREE_CHAIN (templates)) |
| || (candidates && TREE_CHAIN (candidates)) |
| || (templates && candidates)) |
| { |
| error ("ambiguous template specialization %qD for %q+D", |
| template_id, decl); |
| candidates = chainon (candidates, templates); |
| print_candidates (candidates); |
| return error_mark_node; |
| } |
| |
| /* We have one, and exactly one, match. */ |
| if (candidates) |
| { |
| tree fn = TREE_VALUE (candidates); |
| *targs_out = copy_node (DECL_TI_ARGS (fn)); |
| |
| /* Propagate the candidate's constraints to the declaration. */ |
| if (tsk != tsk_template) |
| set_constraints (decl, get_constraints (fn)); |
| |
| /* DECL is a re-declaration or partial instantiation of a template |
| function. */ |
| if (TREE_CODE (fn) == TEMPLATE_DECL) |
| return fn; |
| /* It was a specialization of an ordinary member function in a |
| template class. */ |
| return DECL_TI_TEMPLATE (fn); |
| } |
| |
| /* 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 <class T> 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 = cxx_copy_lang_qualifiers (new_type, old_type); |
| |
| TREE_TYPE (decl) = new_type; |
| } |
| |
| /* Return the number of template headers we expect to see for a definition |
| or specialization of CTYPE or one of its non-template members. */ |
| |
| int |
| num_template_headers_for_class (tree ctype) |
| { |
| int num_templates = 0; |
| |
| while (ctype && CLASS_TYPE_P (ctype)) |
| { |
| /* You're supposed to have one `template <...>' for every |
| template class, but you don't need one for a full |
| specialization. For example: |
| |
| template <class T> struct S{}; |
| template <> struct S<int> { void f(); }; |
| void S<int>::f () {} |
| |
| is correct; there shouldn't be a `template <>' for the |
| definition of `S<int>::f'. */ |
| if (!CLASSTYPE_TEMPLATE_INFO (ctype)) |
| /* If CTYPE does not have template information of any |
| kind, then it is not a template, nor is it nested |
| within a template. */ |
| break; |
| if (explicit_class_specialization_p (ctype)) |
| break; |
| if (PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (ctype))) |
| ++num_templates; |
| |
| ctype = TYPE_CONTEXT (ctype); |
| } |
| |
| return num_templates; |
| } |
| |
| /* Do a simple sanity check on the template headers that precede the |
| variable declaration DECL. */ |
| |
| void |
| check_template_variable (tree decl) |
| { |
| tree ctx = CP_DECL_CONTEXT (decl); |
| int wanted = num_template_headers_for_class (ctx); |
| if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl) |
| && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (decl))) |
| { |
| if (cxx_dialect < cxx14) |
| pedwarn (DECL_SOURCE_LOCATION (decl), OPT_Wc__14_extensions, |
| "variable templates only available with " |
| "%<-std=c++14%> or %<-std=gnu++14%>"); |
| |
| // Namespace-scope variable templates should have a template header. |
| ++wanted; |
| } |
| if (template_header_count > wanted) |
| { |
| auto_diagnostic_group d; |
| bool warned = pedwarn (DECL_SOURCE_LOCATION (decl), 0, |
| "too many template headers for %qD " |
| "(should be %d)", |
| decl, wanted); |
| if (warned && CLASS_TYPE_P (ctx) |
| && CLASSTYPE_TEMPLATE_SPECIALIZATION (ctx)) |
| inform (DECL_SOURCE_LOCATION (decl), |
| "members of an explicitly specialized class are defined " |
| "without a template header"); |
| } |
| } |
| |
| /* An explicit specialization whose declarator-id or class-head-name is not |
| qualified shall be declared in the nearest enclosing namespace of the |
| template, or, if the namespace is inline (7.3.1), any namespace from its |
| enclosing namespace set. |
| |
| If the name declared in the explicit instantiation is an unqualified name, |
| the explicit instantiation shall appear in the namespace where its template |
| is declared or, if that namespace is inline (7.3.1), any namespace from its |
| enclosing namespace set. */ |
| |
| void |
| check_unqualified_spec_or_inst (tree t, location_t loc) |
| { |
| tree tmpl = most_general_template (t); |
| if (DECL_NAMESPACE_SCOPE_P (tmpl) |
| && !is_nested_namespace (current_namespace, |
| CP_DECL_CONTEXT (tmpl), true)) |
| { |
| if (processing_specialization) |
| permerror (loc, "explicit specialization of %qD outside its " |
| "namespace must use a nested-name-specifier", tmpl); |
| else if (processing_explicit_instantiation |
| && cxx_dialect >= cxx11) |
| /* This was allowed in C++98, so only pedwarn. */ |
| pedwarn (loc, OPT_Wpedantic, "explicit instantiation of %qD " |
| "outside its namespace must use a nested-name-" |
| "specifier", tmpl); |
| } |
| } |
| |
| /* Warn for a template specialization SPEC that is missing some of a set |
| of function or type attributes that the template TEMPL is declared with. |
| ATTRLIST is a list of additional attributes that SPEC should be taken |
| to ultimately be declared with. */ |
| |
| static void |
| warn_spec_missing_attributes (tree tmpl, tree spec, tree attrlist) |
| { |
| if (DECL_FUNCTION_TEMPLATE_P (tmpl)) |
| tmpl = DECL_TEMPLATE_RESULT (tmpl); |
| |
| /* Avoid warning if the difference between the primary and |
| the specialization is not in one of the attributes below. */ |
| const char* const blacklist[] = { |
| "alloc_align", "alloc_size", "assume_aligned", "format", |
| "format_arg", "malloc", "nonnull", NULL |
| }; |
| |
| /* Put together a list of the black listed attributes that the primary |
| template is declared with that the specialization is not, in case |
| it's not apparent from the most recent declaration of the primary. */ |
| pretty_printer str; |
| unsigned nattrs = decls_mismatched_attributes (tmpl, spec, attrlist, |
| blacklist, &str); |
| |
| if (!nattrs) |
| return; |
| |
| auto_diagnostic_group d; |
| if (warning_at (DECL_SOURCE_LOCATION (spec), OPT_Wmissing_attributes, |
| "explicit specialization %q#D may be missing attributes", |
| spec)) |
| inform (DECL_SOURCE_LOCATION (tmpl), |
| nattrs > 1 |
| ? G_("missing primary template attributes %s") |
| : G_("missing primary template attribute %s"), |
| pp_formatted_text (&str)); |
| } |
| |
| /* 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 <class T> struct S { void f(); }; |
| void S<int>::f(); |
| |
| the TEMPLATE_COUNT would be 1. However, explicitly specialized |
| classes are not counted in the TEMPLATE_COUNT, so that in |
| |
| template <class T> struct S {}; |
| template <> struct S<int> { void f(); } |
| template <> void S<int>::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, |
| tree attrlist) |
| { |
| int have_def = flags & 2; |
| int is_friend = flags & 4; |
| bool is_concept = flags & 8; |
| 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 && !VAR_P (decl)) |
| { |
| specialization = 1; |
| SET_DECL_TEMPLATE_SPECIALIZATION (decl); |
| } |
| else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR |
| || (DECL_LANG_SPECIFIC (decl) |
| && DECL_IMPLICIT_INSTANTIATION (decl))) |
| { |
| if (is_friend) |
| /* This could be something like: |
| |
| template <class T> void f(T); |
| class S { friend void f<>(int); } */ |
| specialization = 1; |
| else |
| { |
| /* This case handles bogus declarations like template <> |
| template <class T> void f<int>(); */ |
| |
| error_at (cp_expr_loc_or_input_loc (declarator), |
| "template-id %qE 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 " |
| "%<template <>%>", decl); |
| |
| /* Fall through. */ |
| case tsk_expl_spec: |
| if (is_concept) |
| error ("explicit specialization declared %<concept%>"); |
| |
| if (VAR_P (decl) && TREE_CODE (declarator) != TEMPLATE_ID_EXPR) |
| /* In cases like template<> constexpr bool v = true; |
| We'll give an error in check_template_variable. */ |
| break; |
| |
| SET_DECL_TEMPLATE_SPECIALIZATION (decl); |
| if (ctype) |
| member_specialization = 1; |
| else |
| specialization = 1; |
| break; |
| |
| case tsk_template: |
| if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR) |
| { |
| /* This case handles bogus declarations like template <> |
| template <class T> void f<int>(); */ |
| |
| if (!uses_template_parms (TREE_OPERAND (declarator, 1))) |
| error_at (cp_expr_loc_or_input_loc (declarator), |
| "template-id %qE 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_at (cp_expr_loc_or_input_loc (declarator), |
| "non-type partial specialization %qE " |
| "is not allowed", declarator); |
| else |
| error_at (cp_expr_loc_or_input_loc (declarator), |
| "non-class, non-variable partial specialization %qE " |
| "is not allowed", declarator); |
| return decl; |
| ok:; |
| } |
| |
| if (ctype && CLASSTYPE_TEMPLATE_INSTANTIATION (ctype)) |
| /* This is a specialization of a member template, without |
| specialization the containing class. Something like: |
| |
| template <class T> struct S { |
| template <class U> void f (U); |
| }; |
| template <> template <class U> void S<int>::f(U) {} |
| |
| That's a specialization -- but of the entire template. */ |
| specialization = 1; |
| break; |
| |
| default: |
| gcc_unreachable (); |
| } |
| |
| if ((specialization || member_specialization) |
| /* This doesn't apply to variable templates. */ |
| && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (decl))) |
| { |
| tree t = TYPE_ARG_TYPES (TREE_TYPE (decl)); |
| for (; t; t = TREE_CHAIN (t)) |
| if (TREE_PURPOSE (t)) |
| { |
| permerror (input_location, |
| "default argument specified in explicit specialization"); |
| break; |
| } |
| } |
| |
| if (specialization || member_specialization || explicit_instantiation) |
| { |
| tree tmpl = NULL_TREE; |
| tree targs = NULL_TREE; |
| bool was_template_id = (TREE_CODE (declarator) == TEMPLATE_ID_EXPR); |
| bool found_hidden = false; |
| |
| /* Make sure that the declarator is a TEMPLATE_ID_EXPR. */ |
| if (!was_template_id) |
| { |
| tree fns; |
| |
| gcc_assert (identifier_p (declarator)); |
| if (ctype) |
| fns = dname; |
| else |
| { |
| /* If there is no class context, the explicit instantiation |
| must be at namespace scope. */ |
| gcc_assert (DECL_NAMESPACE_SCOPE_P (decl)); |
| |
| /* Find the namespace binding, using the declaration |
| context. */ |
| fns = lookup_qualified_name (CP_DECL_CONTEXT (decl), dname, |
| LOOK_want::NORMAL, true); |
| if (fns == error_mark_node) |
| { |
| /* If lookup fails, look for a friend declaration so we can |
| give a better diagnostic. */ |
| fns = (lookup_qualified_name |
| (CP_DECL_CONTEXT (decl), dname, |
| LOOK_want::NORMAL | LOOK_want::HIDDEN_FRIEND, |
| /*complain*/true)); |
| found_hidden = true; |
| } |
| |
| if (fns == error_mark_node || !is_overloaded_fn (fns)) |
| { |
| error ("%qD is not a template function", dname); |
| fns = error_mark_node; |
| } |
| } |
| |
| declarator = lookup_template_function (fns, NULL_TREE); |
| } |
| |
| if (declarator == error_mark_node) |
| return error_mark_node; |
| |
| if (ctype != NULL_TREE && TYPE_BEING_DEFINED (ctype)) |
| { |
| if (!explicit_instantiation) |
| /* A specialization in class scope. This is invalid, |
| but the error will already have been flagged by |
| check_specialization_scope. */ |
| return error_mark_node; |
| else |
| { |
| /* It's not valid to write an explicit instantiation in |
| class scope, e.g.: |
| |
| class C { template void f(); } |
| |
| This case is caught by the parser. However, on |
| something like: |
| |
| template class C { void f(); }; |
| |
| (which is invalid) we can get here. The error will be |
| issued later. */ |
| ; |
| } |
| |
| return decl; |
| } |
| else if (ctype != NULL_TREE |
| && (identifier_p (TREE_OPERAND (declarator, 0)))) |
| { |
| // We'll match variable templates in start_decl. |
| if (VAR_P (decl)) |
| return decl; |
| |
| /* Find the list of functions in ctype that have the same |
| name as the declared function. */ |
| tree name = TREE_OPERAND (declarator, 0); |
| |
| if (constructor_name_p (name, ctype)) |
| { |
| if (DECL_CONSTRUCTOR_P (decl) |
| ? !TYPE_HAS_USER_CONSTRUCTOR (ctype) |
| : !CLASSTYPE_DESTRUCTOR (ctype)) |
| { |
| /* From [temp.expl.spec]: |
| |
| If such an explicit specialization for the member |
| of a class template names an implicitly-declared |
| special member function (clause _special_), the |
| program is ill-formed. |
| |
| Similar language is found in [temp.explicit]. */ |
| error ("specialization of implicitly-declared special member function"); |
| return error_mark_node; |
| } |
| |
| name = DECL_NAME (decl); |
| } |
| |
| /* For a type-conversion operator, We might be looking for |
| `operator int' which will be a specialization of |
| `operator T'. Grab all the conversion operators, and |
| then select from them. */ |
| tree fns = get_class_binding (ctype, IDENTIFIER_CONV_OP_P (name) |
| ? conv_op_identifier : name); |
| |
| if (fns == NULL_TREE) |
| { |
| error ("no member function %qD declared in %qT", name, ctype); |
| return error_mark_node; |
| } |
| else |
| TREE_OPERAND (declarator, 0) = fns; |
| } |
| |
| /* Figure out what exactly is being specialized at this point. |
| Note that for an explicit instantiation, even one for a |
| member function, we cannot tell a priori whether the |
| instantiation is for a member template, or just a member |
| function of a template class. Even if a member template is |
| being instantiated, the member template arguments may be |
| elided if they can be deduced from the rest of the |
| declaration. */ |
| tmpl = determine_specialization (declarator, decl, |
| &targs, |
| member_specialization, |
| template_count, |
| tsk); |
| |
| if (!tmpl || tmpl == error_mark_node) |
| /* We couldn't figure out what this declaration was |
| specializing. */ |
| return error_mark_node; |
| else |
| { |
| if (found_hidden && TREE_CODE (decl) == FUNCTION_DECL) |
| { |
| auto_diagnostic_group d; |
| if (pedwarn (DECL_SOURCE_LOCATION (decl), 0, |
| "friend declaration %qD is not visible to " |
| "explicit specialization", tmpl)) |
| inform (DECL_SOURCE_LOCATION (tmpl), |
| "friend declaration here"); |
| } |
| |
| if (!ctype && !is_friend |
| && CP_DECL_CONTEXT (decl) == current_namespace) |
| check_unqualified_spec_or_inst (tmpl, DECL_SOURCE_LOCATION (decl)); |
| |
| tree gen_tmpl = most_general_template (tmpl); |
| |
| if (explicit_instantiation) |
| { |
| /* We don't set DECL_EXPLICIT_INSTANTIATION here; that |
| is done by do_decl_instantiation later. */ |
| |
| int arg_depth = TMPL_ARGS_DEPTH (targs); |
| int parm_depth = TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)); |
| |
| if (arg_depth > parm_depth) |
| { |
| /* If TMPL is not the most general template (for |
| example, if TMPL is a friend template that is |
| injected into namespace scope), then there will |
| be too many levels of TARGS. Remove some of them |
| here. */ |
| int i; |
| tree new_targs; |
| |
| new_targs = make_tree_vec (parm_depth); |
| for (i = arg_depth - parm_depth; i < arg_depth; ++i) |
| TREE_VEC_ELT (new_targs, i - (arg_depth - parm_depth)) |
| = TREE_VEC_ELT (targs, i); |
| targs = new_targs; |
| } |
| |
| return instantiate_template (tmpl, targs, tf_error); |
| } |
| |
| /* If we thought that the DECL was a member function, but it |
| turns out to be specializing a static member function, |
| make DECL a static member function as well. */ |
| if (DECL_FUNCTION_TEMPLATE_P (tmpl) |
| && DECL_STATIC_FUNCTION_P (tmpl) |
| && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) |
| revert_static_member_fn (decl); |
| |
| /* 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 && !was_template_id) |
| { |
| tree result = DECL_TEMPLATE_RESULT (tmpl); |
| SET_DECL_TEMPLATE_SPECIALIZATION (tmpl); |
| DECL_INITIAL (result) = NULL_TREE; |
| if (have_def) |
| { |
| tree parm; |
| DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl); |
| DECL_SOURCE_LOCATION (result) |
| = DECL_SOURCE_LOCATION (decl); |
| /* We want to use the argument list specified in the |
| definition, not in the original declaration. */ |
| DECL_ARGUMENTS (result) = DECL_ARGUMENTS (decl); |
| for (parm = DECL_ARGUMENTS (result); parm; |
| parm = DECL_CHAIN (parm)) |
| DECL_CONTEXT (parm) = result; |
| } |
| return register_specialization (tmpl, gen_tmpl, targs, |
| is_friend, 0); |
| } |
| |
| /* 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)) |
| copy_default_args_to_explicit_spec (decl); |
| |
| /* This specialization has the same protection as the |
| template it specializes. */ |
| TREE_PRIVATE (decl) = TREE_PRIVATE (gen_tmpl); |
| TREE_PROTECTED (decl) = TREE_PROTECTED (gen_tmpl); |
| |
| /* 7.1.1-1 [dcl.stc] |
| |
| A storage-class-specifier shall not be specified in an |
| explicit specialization... |
| |
| The parser rejects these, so unless action is taken here, |
| explicit function specializations will always appear with |
| global linkage. |
| |
| The action recommended by the C++ CWG in response to C++ |
| defect report 605 is to make the storage class and linkage |
| of the explicit specialization match the templated function: |
| |
| http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#605 |
| */ |
| if (tsk == tsk_expl_spec && DECL_FUNCTION_TEMPLATE_P (gen_tmpl)) |
| { |
| tree tmpl_func = DECL_TEMPLATE_RESULT (gen_tmpl); |
| gcc_assert (TREE_CODE (tmpl_func) == FUNCTION_DECL); |
| |
| /* A concept cannot be specialized. */ |
| if (DECL_DECLARED_CONCEPT_P (tmpl_func)) |
| { |
| error ("explicit specialization of function concept %qD", |
| gen_tmpl); |
| return error_mark_node; |
| } |
| |
| /* This specialization has the same linkage and visibility as |
| the function template it specializes. */ |
| TREE_PUBLIC (decl) = TREE_PUBLIC (tmpl_func); |
| if (! TREE_PUBLIC (decl)) |
| { |
| DECL_INTERFACE_KNOWN (decl) = 1; |
| DECL_NOT_REALLY_EXTERN (decl) = 1; |
| } |
| DECL_THIS_STATIC (decl) = DECL_THIS_STATIC (tmpl_func); |
| if (DECL_VISIBILITY_SPECIFIED (tmpl_func)) |
| { |
| DECL_VISIBILITY_SPECIFIED (decl) = 1; |
| DECL_VISIBILITY (decl) = DECL_VISIBILITY (tmpl_func); |
| } |
| } |
| |
| /* If DECL is a friend declaration, declared using an |
| unqualified name, the namespace associated with DECL may |
| have been set incorrectly. For example, in: |
| |
| template <typename T> void f(T); |
| namespace N { |
| struct S { friend void f<int>(int); } |
| } |
| |
| we will have set the DECL_CONTEXT for the friend |
| declaration to N, rather than to the global namespace. */ |
| if (DECL_NAMESPACE_SCOPE_P (decl)) |
| DECL_CONTEXT (decl) = DECL_CONTEXT (tmpl); |
| |
| if (is_friend && !have_def) |
| /* This is not really a declaration of a specialization. |
| It's just the name of an instantiation. But, it's not |
| a request for an instantiation, either. */ |
| SET_DECL_IMPLICIT_INSTANTIATION (decl); |
| else if (TREE_CODE (decl) == FUNCTION_DECL) |
| /* A specialization is not necessarily COMDAT. */ |
| DECL_COMDAT (decl) = (TREE_PUBLIC (decl) |
| && DECL_DECLARED_INLINE_P (decl)); |
| else if (VAR_P (decl)) |
| DECL_COMDAT (decl) = false; |
| |
| /* If this is a full specialization, register it so that we can find |
| it again. Partial specializations will be registered in |
| process_partial_specialization. */ |
| if (!processing_template_decl) |
| { |
| warn_spec_missing_attributes (gen_tmpl, decl, attrlist); |
| |
| decl = register_specialization (decl, gen_tmpl, targs, |
| is_friend, 0); |
| } |
| |
| |
| /* A 'structor should already have clones. */ |
| gcc_assert (decl == error_mark_node |
| || variable_template_p (tmpl) |
| || !(DECL_CONSTRUCTOR_P (decl) |
| || DECL_DESTRUCTOR_P (decl)) |
| || DECL_CLONED_FUNCTION_P (DECL_CHAIN (decl))); |
| } |
| } |
| |
| return decl; |
| } |
| |
| /* Returns 1 iff PARMS1 and PARMS2 are identical sets of template |
| parameters. These are represented in the same format used for |
| DECL_TEMPLATE_PARMS. */ |
| |
| int |
| comp_template_parms (const_tree parms1, const_tree parms2) |
| { |
| const_tree p1; |
| const_tree p2; |
| |
| if (parms1 == parms2) |
| return 1; |
| |
| for (p1 = parms1, p2 = parms2; |
| p1 != NULL_TREE && p2 != NULL_TREE; |
| p1 = TREE_CHAIN (p1), p2 = TREE_CHAIN (p2)) |
| { |
| tree t1 = TREE_VALUE (p1); |
| tree t2 = TREE_VALUE (p2); |
| int i; |
| |
| gcc_assert (TREE_CODE (t1) == TREE_VEC); |
| gcc_assert (TREE_CODE (t2) == TREE_VEC); |
| |
| if (TREE_VEC_LENGTH (t1) != TREE_VEC_LENGTH (t2)) |
| return 0; |
| |
| for (i = 0; i < TREE_VEC_LENGTH (t2); ++i) |
|