📄 pt.c
字号:
/* Handle parameterized types (templates) for GNU C++. Copyright (C) 1992, 93-97, 1998, 1999 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 GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA. *//* Known bugs or deficiencies include: all methods must be provided in header files; can't use a source file that contains only the method templates and "just win". */#include "config.h"#include "system.h"#include "obstack.h"#include "tree.h"#include "flags.h"#include "cp-tree.h"#include "decl.h"#include "parse.h"#include "lex.h"#include "output.h"#include "defaults.h"#include "except.h"#include "toplev.h"#include "rtl.h"#include "varray.h"/* The type of functions taking a tree, and some additional data, and returning an int. */typedef int (*tree_fn_t) PROTO((tree, void*));extern struct obstack permanent_obstack;extern int lineno;extern char *input_filename;tree current_template_parms;HOST_WIDE_INT processing_template_decl;/* The PENDING_TEMPLATES is a TREE_LIST of templates whose instantiations have been deferred, either because their definitions were not yet available, or because we were putting off doing the work. The TREE_PURPOSE of each entry is a SRCLOC indicating where the instantiate request occurred; the TREE_VALUE is a either a DECL (for a function or static data member), or a TYPE (for a class) indicating what we are hoping to instantiate. */static tree pending_templates;static tree *template_tail = &pending_templates;static tree maybe_templates;static tree *maybe_template_tail = &maybe_templates;int minimal_parse_mode;int processing_specialization;int processing_explicit_instantiation;int processing_template_parmlist;static int template_header_count;static tree saved_trees;static varray_type inline_parm_levels;static size_t inline_parm_levels_used;#define obstack_chunk_alloc xmalloc#define obstack_chunk_free free#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 GTB_VIA_VIRTUAL 1 /* The base class we are examining is virtual, or a base class of a virtual base. */#define GTB_IGNORE_TYPE 2 /* We don't need to try to unify the current type with the desired type. */static int resolve_overloaded_unification PROTO((tree, tree, tree, tree, unification_kind_t, int));static int try_one_overload PROTO((tree, tree, tree, tree, tree, unification_kind_t, int));static int unify PROTO((tree, tree, tree, tree, int));static void add_pending_template PROTO((tree));static int push_tinst_level PROTO((tree));static tree classtype_mangled_name PROTO((tree));static char *mangle_class_name_for_template PROTO((char *, tree, tree));static tree tsubst_expr_values PROTO((tree, tree));static int list_eq PROTO((tree, tree));static tree get_class_bindings PROTO((tree, tree, tree));static tree coerce_template_parms PROTO((tree, tree, tree, int, int));static void tsubst_enum PROTO((tree, tree, tree));static tree add_to_template_args PROTO((tree, tree));static tree add_outermost_template_args PROTO((tree, tree));static void maybe_adjust_types_for_deduction PROTO((unification_kind_t, tree*, tree*)); static int type_unification_real PROTO((tree, tree, tree, tree, int, unification_kind_t, int));static void note_template_header PROTO((int));static tree maybe_fold_nontype_arg PROTO((tree));static tree convert_nontype_argument PROTO((tree, tree));static tree convert_template_argument PROTO ((tree, tree, tree, int, int , tree));static tree get_bindings_overload PROTO((tree, tree, tree));static int for_each_template_parm PROTO((tree, tree_fn_t, void*));static tree build_template_parm_index PROTO((int, int, int, tree, tree));static int inline_needs_template_parms PROTO((tree));static void push_inline_template_parms_recursive PROTO((tree, int));static tree retrieve_specialization PROTO((tree, tree));static tree register_specialization PROTO((tree, tree, tree));static int unregister_specialization PROTO((tree, tree));static tree reduce_template_parm_level PROTO((tree, tree, int));static tree build_template_decl PROTO((tree, tree));static int mark_template_parm PROTO((tree, void *));static tree tsubst_friend_function PROTO((tree, tree));static tree tsubst_friend_class PROTO((tree, tree));static tree get_bindings_real PROTO((tree, tree, tree, int));static int template_decl_level PROTO((tree));static tree maybe_get_template_decl_from_type_decl PROTO((tree));static int check_cv_quals_for_unify PROTO((int, tree, tree));static tree tsubst_template_arg_vector PROTO((tree, tree, int));static tree tsubst_template_parms PROTO((tree, tree, int));static void regenerate_decl_from_template PROTO((tree, tree));static tree most_specialized PROTO((tree, tree, tree));static tree most_specialized_class PROTO((tree, tree));static tree most_general_template PROTO((tree));static void set_mangled_name_for_template_decl PROTO((tree));static int template_class_depth_real PROTO((tree, int));static tree tsubst_aggr_type PROTO((tree, tree, int, tree, int));static tree tsubst_decl PROTO((tree, tree, tree, tree));static tree tsubst_arg_types PROTO((tree, tree, int, tree));static tree tsubst_function_type PROTO((tree, tree, int, tree));static void check_specialization_scope PROTO((void));static tree process_partial_specialization PROTO((tree));static void set_current_access_from_decl PROTO((tree));static void check_default_tmpl_args PROTO((tree, tree, int, int));static tree tsubst_call_declarator_parms PROTO((tree, tree, int, tree));static tree get_template_base_recursive PROTO((tree, tree, tree, tree, tree, int)); static tree get_template_base PROTO((tree, tree, tree, tree));static tree try_class_unification PROTO((tree, tree, tree, tree));static int coerce_template_template_parms PROTO((tree, tree, int, tree, tree));static tree determine_specialization PROTO((tree, tree, tree *, int));static int template_args_equal PROTO((tree, tree));static void print_template_context PROTO((int));static int has_pvbases_p PROTO((tree, tree));/* We use TREE_VECs to hold template arguments. If there is only one level of template arguments, then the TREE_VEC contains the arguments directly. If there is more than one level of template arguments, then each entry in the TREE_VEC is itself a TREE_VEC, containing the template arguments for a single level. The first entry in the outer TREE_VEC is the outermost level of template parameters; the last is the innermost. It is incorrect to ever form a template argument vector containing only one level of arguments, but which is a TREE_VEC containing as its only entry the TREE_VEC for that level. *//* Non-zero if the template arguments is actually a vector of vectors, rather than just a vector. */#define TMPL_ARGS_HAVE_MULTIPLE_LEVELS(NODE) \ (NODE != NULL_TREE \ && TREE_CODE (NODE) == TREE_VEC \ && TREE_VEC_LENGTH (NODE) > 0 \ && TREE_VEC_ELT (NODE, 0) != NULL_TREE \ && TREE_CODE (TREE_VEC_ELT (NODE, 0)) == TREE_VEC)/* The depth of a template argument vector. When called directly by the parser, we use a TREE_LIST rather than a TREE_VEC to represent template arguments. In fact, we may even see NULL_TREE if there are no template arguments. In both of those cases, there is only one level of template arguments. */#define TMPL_ARGS_DEPTH(NODE) \ (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (NODE) ? TREE_VEC_LENGTH (NODE) : 1)/* The LEVELth level of the template ARGS. Note that template parameter levels are indexed from 1, not from 0. */#define TMPL_ARGS_LEVEL(ARGS, LEVEL) \ (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (ARGS) \ ? TREE_VEC_ELT ((ARGS), (LEVEL) - 1) : ARGS)/* Set the LEVELth level of the template ARGS to VAL. This macro does not work with single-level argument vectors. */#define SET_TMPL_ARGS_LEVEL(ARGS, LEVEL, VAL) \ (TREE_VEC_ELT ((ARGS), (LEVEL) - 1) = (VAL))/* Accesses the IDXth parameter in the LEVELth level of the ARGS. */#define TMPL_ARG(ARGS, LEVEL, IDX) \ (TREE_VEC_ELT (TMPL_ARGS_LEVEL (ARGS, LEVEL), IDX))/* Set the IDXth element in the LEVELth level of ARGS to VAL. This macro does not work with single-level argument vectors. */#define SET_TMPL_ARG(ARGS, LEVEL, IDX, VAL) \ (TREE_VEC_ELT (TREE_VEC_ELT ((ARGS), (LEVEL) - 1), (IDX)) = (VAL))/* Given a single level of template arguments in NODE, return the number of arguments. */#define NUM_TMPL_ARGS(NODE) \ ((NODE) == NULL_TREE ? 0 \ : (TREE_CODE (NODE) == TREE_VEC \ ? TREE_VEC_LENGTH (NODE) : list_length (NODE)))/* The number of levels of template parameters given by NODE. */#define TMPL_PARMS_DEPTH(NODE) \ (TREE_INT_CST_HIGH (TREE_PURPOSE (NODE)))/* Do any processing required when DECL (a member template declaration using TEMPLATE_PARAMETERS as its innermost parameter list) is finished. Returns the TEMPLATE_DECL corresponding to DECL, unless it is a specialization, in which case the DECL itself is returned. */treefinish_member_template_decl (decl) tree decl;{ if (decl == NULL_TREE || decl == void_type_node) return NULL_TREE; else if (decl == error_mark_node) /* By returning NULL_TREE, the parser will just ignore this declaration. We have already issued the error. */ return NULL_TREE; else if (TREE_CODE (decl) == TREE_LIST) { /* Assume that the class is the only declspec. */ decl = TREE_VALUE (decl); if (IS_AGGR_TYPE (decl) && CLASSTYPE_TEMPLATE_INFO (decl) && ! CLASSTYPE_TEMPLATE_SPECIALIZATION (decl)) { tree tmpl = CLASSTYPE_TI_TEMPLATE (decl); check_member_template (tmpl); return tmpl; } return NULL_TREE; } 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 cp_error ("invalid member template declaration `%D'", decl); return error_mark_node;}/* 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 COUNT_SPECIALIZATIONS is 0 or if they are instantiations, not specializations. This function is guaranteed to return 0 if passed NULL_TREE so that, for example, `template_class_depth (current_class_type)' is always safe. */static int template_class_depth_real (type, count_specializations) tree type; int count_specializations;{ int depth; for (depth = 0; type && TREE_CODE (type) != NAMESPACE_DECL; type = (TREE_CODE (type) == FUNCTION_DECL) ? DECL_REAL_CONTEXT (type) : TYPE_CONTEXT (type)) { if (TREE_CODE (type) != FUNCTION_DECL) { if (CLASSTYPE_TEMPLATE_INFO (type) && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (type)) && ((count_specializations && CLASSTYPE_TEMPLATE_SPECIALIZATION (type)) || uses_template_parms (CLASSTYPE_TI_ARGS (type)))) ++depth; } else { if (DECL_TEMPLATE_INFO (type) && PRIMARY_TEMPLATE_P (DECL_TI_TEMPLATE (type)) && ((count_specializations && DECL_TEMPLATE_SPECIALIZATION (type)) || uses_template_parms (DECL_TI_ARGS (type)))) ++depth; } } return depth;}/* Returns the template nesting level of the indicated class TYPE. Like template_class_depth_real, but instantiations do not count in the depth. */int template_class_depth (type) tree type;{ return template_class_depth_real (type, /*count_specializations=*/0);}/* Returns 1 if processing DECL as part of do_pending_inlines needs us to push template parms. */static intinline_needs_template_parms (decl) tree decl;{ if (! DECL_TEMPLATE_INFO (decl)) return 0; return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (most_general_template (decl))) > (processing_template_decl + DECL_TEMPLATE_SPECIALIZATION (decl)));}/* Subroutine of maybe_begin_member_template_processing. Push the template parms in PARMS, starting from LEVELS steps into the chain, and ending at the beginning, since template parms are listed innermost first. */static voidpush_inline_template_parms_recursive (parmlist, levels) 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 (build_int_2 (0, processing_template_decl), parms, current_template_parms); TEMPLATE_PARMS_FOR_INLINE (current_template_parms) = 1; pushlevel (0); for (i = 0; i < TREE_VEC_LENGTH (parms); ++i) { tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i)); my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (parm)) == 'd', 0); switch (TREE_CODE (parm)) { case TYPE_DECL: case TEMPLATE_DECL: pushdecl (parm); break; case PARM_DECL: { /* Make a CONST_DECL as is done in process_template_parm. It is ugly that we recreate this here; the original version built in process_template_parm is no longer available. */ tree decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm)); SET_DECL_ARTIFICIAL (decl); DECL_INITIAL (decl) = DECL_INITIAL (parm); DECL_TEMPLATE_PARM_P (decl) = 1; pushdecl (decl); } break; default: my_friendly_abort (0); } }}/* Restore the template parameter context for a member template or a friend template defined in a class definition. */voidmaybe_begin_member_template_processing (decl) tree decl;{ tree parms; int levels = 0; if (inline_needs_template_parms (decl)) { parms = DECL_TEMPLATE_PARMS (most_general_template (decl)); levels = TMPL_PARMS_DEPTH (parms) - processing_template_decl; if (DECL_TEMPLATE_SPECIALIZATION (decl)) { --levels; parms = TREE_CHAIN (parms); } push_inline_template_parms_recursive (parms, levels); } /* Remember how many levels of template parameters we pushed so that
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -