📄 pt.c
字号:
type); tree t = build_template_parm_index (TEMPLATE_PARM_IDX (index), TEMPLATE_PARM_LEVEL (index) - levels, TEMPLATE_PARM_ORIG_LEVEL (index), decl, type); TEMPLATE_PARM_DESCENDANTS (index) = t; /* Template template parameters need this. */ DECL_TEMPLATE_PARMS (decl) = DECL_TEMPLATE_PARMS (TEMPLATE_PARM_DECL (index)); } return TEMPLATE_PARM_DESCENDANTS (index);}/* Process information from new template parameter NEXT and append it to the LIST being built. */treeprocess_template_parm (list, next) tree list, next;{ tree parm; tree decl = 0; tree defval; int is_type, idx; parm = next; my_friendly_assert (TREE_CODE (parm) == TREE_LIST, 259); defval = TREE_PURPOSE (parm); parm = TREE_VALUE (parm); is_type = TREE_PURPOSE (parm) == class_type_node; if (list) { tree p = TREE_VALUE (tree_last (list)); if (TREE_CODE (p) == TYPE_DECL) idx = TEMPLATE_TYPE_IDX (TREE_TYPE (p)); else if (TREE_CODE (p) == TEMPLATE_DECL) idx = TEMPLATE_TYPE_IDX (TREE_TYPE (DECL_TEMPLATE_RESULT (p))); else idx = TEMPLATE_PARM_IDX (DECL_INITIAL (p)); ++idx; } else idx = 0; if (!is_type) { my_friendly_assert (TREE_CODE (TREE_PURPOSE (parm)) == TREE_LIST, 260); /* is a const-param */ parm = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm), PARM, 0, NULL_TREE); /* [temp.param] The top-level cv-qualifiers on the template-parameter are ignored when determining its type. */ TREE_TYPE (parm) = TYPE_MAIN_VARIANT (TREE_TYPE (parm)); /* A template parameter is not modifiable. */ TREE_READONLY (parm) = 1; if (IS_AGGR_TYPE (TREE_TYPE (parm)) && TREE_CODE (TREE_TYPE (parm)) != TEMPLATE_TYPE_PARM && TREE_CODE (TREE_TYPE (parm)) != TYPENAME_TYPE) { cp_error ("`%#T' is not a valid type for a template constant parameter", TREE_TYPE (parm)); if (DECL_NAME (parm) == NULL_TREE) error (" a template type parameter must begin with `class' or `typename'"); TREE_TYPE (parm) = void_type_node; } else if (pedantic && (TREE_CODE (TREE_TYPE (parm)) == REAL_TYPE || TREE_CODE (TREE_TYPE (parm)) == COMPLEX_TYPE)) cp_pedwarn ("`%T' is not a valid type for a template constant parameter", TREE_TYPE (parm)); if (TREE_PERMANENT (parm) == 0) { parm = copy_node (parm); TREE_PERMANENT (parm) = 1; } decl = build_decl (CONST_DECL, DECL_NAME (parm), TREE_TYPE (parm)); DECL_INITIAL (parm) = DECL_INITIAL (decl) = build_template_parm_index (idx, processing_template_decl, processing_template_decl, decl, TREE_TYPE (parm)); } else { tree t; parm = TREE_VALUE (parm); if (parm && TREE_CODE (parm) == TEMPLATE_DECL) { t = make_lang_type (TEMPLATE_TEMPLATE_PARM); /* This is for distinguishing between real templates and template template parameters */ TREE_TYPE (parm) = t; TREE_TYPE (DECL_TEMPLATE_RESULT (parm)) = t; decl = parm; } else { t = make_lang_type (TEMPLATE_TYPE_PARM); /* parm is either IDENTIFIER_NODE or NULL_TREE */ decl = build_decl (TYPE_DECL, parm, t); } TYPE_NAME (t) = decl; TYPE_STUB_DECL (t) = decl; parm = decl; TEMPLATE_TYPE_PARM_INDEX (t) = build_template_parm_index (idx, processing_template_decl, processing_template_decl, decl, TREE_TYPE (parm)); } SET_DECL_ARTIFICIAL (decl); DECL_TEMPLATE_PARM_P (decl) = 1; pushdecl (decl); parm = build_tree_list (defval, parm); return chainon (list, parm);}/* The end of a template parameter list has been reached. Process the tree list into a parameter vector, converting each parameter into a more useful form. Type parameters are saved as IDENTIFIER_NODEs, and others as PARM_DECLs. */treeend_template_parm_list (parms) tree parms;{ int nparms; tree parm; tree saved_parmlist = make_tree_vec (list_length (parms)); current_template_parms = tree_cons (build_int_2 (0, processing_template_decl), saved_parmlist, current_template_parms); for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++) TREE_VEC_ELT (saved_parmlist, nparms) = parm; --processing_template_parmlist; return saved_parmlist;}/* end_template_decl is called after a template declaration is seen. */voidend_template_decl (){ reset_specialization (); if (! processing_template_decl) return; /* This matches the pushlevel in begin_template_parm_list. */ poplevel (0, 0, 0); --processing_template_decl; current_template_parms = TREE_CHAIN (current_template_parms); (void) get_pending_sizes (); /* Why? */}/* Given a template argument vector containing the template PARMS. The innermost PARMS are given first. */treecurrent_template_args (){ tree header; tree args = NULL_TREE; int length = TMPL_PARMS_DEPTH (current_template_parms); int l = length; /* If there is only one level of template parameters, we do not create a TREE_VEC of TREE_VECs. Instead, we return a single TREE_VEC containing the arguments. */ if (length > 1) args = make_tree_vec (length); for (header = current_template_parms; header; header = TREE_CHAIN (header)) { tree a = copy_node (TREE_VALUE (header)); int i; TREE_TYPE (a) = NULL_TREE; for (i = TREE_VEC_LENGTH (a) - 1; i >= 0; --i) { tree t = TREE_VEC_ELT (a, i); /* T will be a list if we are called from within a begin/end_template_parm_list pair, but a vector directly if within a begin/end_member_template_processing pair. */ if (TREE_CODE (t) == TREE_LIST) { t = TREE_VALUE (t); if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (t) == TEMPLATE_DECL) t = TREE_TYPE (t); else t = DECL_INITIAL (t); TREE_VEC_ELT (a, i) = t; } } if (length > 1) TREE_VEC_ELT (args, --l) = a; else args = a; } return args;}/* Return a TEMPLATE_DECL corresponding to DECL, using the indicated template PARMS. Used by push_template_decl below. */static treebuild_template_decl (decl, parms) tree decl; tree parms;{ tree tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE); DECL_TEMPLATE_PARMS (tmpl) = parms; DECL_CONTEXT (tmpl) = DECL_CONTEXT (decl); if (DECL_LANG_SPECIFIC (decl)) { DECL_CLASS_CONTEXT (tmpl) = DECL_CLASS_CONTEXT (decl); DECL_STATIC_FUNCTION_P (tmpl) = DECL_STATIC_FUNCTION_P (decl); DECL_CONSTRUCTOR_P (tmpl) = DECL_CONSTRUCTOR_P (decl); } return tmpl;}struct template_parm_data{ /* The level of the template parameters we are currently processing. */ int level; /* The index of the specialization argument we are currently processing. */ int current_arg; /* An array whose size is the number of template parameters. The elements are non-zero if the parameter has been used in any one of the arguments processed so far. */ int* parms; /* An array whose size is the number of template arguments. The elements are non-zero if the argument makes use of template parameters of this level. */ int* arg_uses_template_parms;};/* Subroutine of push_template_decl used to see if each template parameter in a partial specialization is used in the explicit argument list. If T is of the LEVEL given in DATA (which is treated as a template_parm_data*), then DATA->PARMS is marked appropriately. */static intmark_template_parm (t, data) tree t; void* data;{ int level; int idx; struct template_parm_data* tpd = (struct template_parm_data*) data; if (TREE_CODE (t) == TEMPLATE_PARM_INDEX) { level = TEMPLATE_PARM_LEVEL (t); idx = TEMPLATE_PARM_IDX (t); } else { level = TEMPLATE_TYPE_LEVEL (t); idx = TEMPLATE_TYPE_IDX (t); } if (level == tpd->level) { tpd->parms[idx] = 1; tpd->arg_uses_template_parms[tpd->current_arg] = 1; } /* Return zero so that for_each_template_parm will continue the traversal of the tree; we want to mark *every* template parm. */ return 0;}/* Process the partial specialization DECL. */static treeprocess_partial_specialization (decl) tree decl;{ tree type = TREE_TYPE (decl); tree maintmpl = CLASSTYPE_TI_TEMPLATE (type); tree specargs = CLASSTYPE_TI_ARGS (type); tree inner_args = innermost_args (specargs); tree inner_parms = INNERMOST_TEMPLATE_PARMS (current_template_parms); tree main_inner_parms = DECL_INNERMOST_TEMPLATE_PARMS (maintmpl); int nargs = TREE_VEC_LENGTH (inner_args); int ntparms = TREE_VEC_LENGTH (inner_parms); int i; int did_error_intro = 0; struct template_parm_data tpd; struct template_parm_data tpd2; /* We check that each of the template parameters given in the partial specialization is used in the argument list to the specialization. For example: template <class T> struct S; template <class T> struct S<T*>; The second declaration is OK because `T*' uses the template parameter T, whereas template <class T> struct S<int>; is no good. Even trickier is: template <class T> struct S1 { template <class U> struct S2; template <class U> struct S2<T>; }; The S2<T> declaration is actually illegal; it is a full-specialization. Of course, template <class U> struct S2<T (*)(U)>; or some such would have been OK. */ tpd.level = TMPL_PARMS_DEPTH (current_template_parms); tpd.parms = alloca (sizeof (int) * ntparms); bzero ((PTR) tpd.parms, sizeof (int) * ntparms); tpd.arg_uses_template_parms = alloca (sizeof (int) * nargs); bzero ((PTR) tpd.arg_uses_template_parms, sizeof (int) * nargs); for (i = 0; i < nargs; ++i) { tpd.current_arg = i; for_each_template_parm (TREE_VEC_ELT (inner_args, i), &mark_template_parm, &tpd); } for (i = 0; i < ntparms; ++i) if (tpd.parms[i] == 0) { /* One of the template parms was not used in the specialization. */ if (!did_error_intro) { cp_error ("template parameters not used in partial specialization:"); did_error_intro = 1; } cp_error (" `%D'", TREE_VALUE (TREE_VEC_ELT (inner_parms, i))); } /* [temp.class.spec] The argument list of the specialization shall not be identical to the implicit argument list of the primary template. */ if (comp_template_args (inner_args, innermost_args (CLASSTYPE_TI_ARGS (TREE_TYPE (maintmpl))))) cp_error ("partial specialization `%T' does not specialize any template arguments", type); /* [temp.class.spec] A partially specialized non-type argument expression shall not involve template parameters of the partial specialization except when the argument expression is a simple identifier. The type of a template parameter corresponding to a specialized non-type argument shall not be dependent on a parameter of the specialization. */ my_friendly_assert (nargs == DECL_NTPARMS (maintmpl), 0); tpd2.parms = 0; for (i = 0; i < nargs; ++i) { tree arg = TREE_VEC_ELT (inner_args, i); if (/* These first two lines are the `non-type' bit. */ TREE_CODE_CLASS (TREE_CODE (arg)) != 't' && TREE_CODE (arg) != TEMPLATE_DECL /* This next line is the `argument expression is not just a simple identifier' condition and also the `specialized non-type argument' bit. */ && TREE_CODE (arg) != TEMPLATE_PARM_INDEX) { if (tpd.arg_uses_template_parms[i]) cp_error ("template argument `%E' involves template parameter(s)", arg); else { /* Look at the corresponding template parameter, marking which template parameters its type depends upon. */ tree type = TREE_TYPE (TREE_VALUE (TREE_VEC_ELT (main_inner_parms, i))); if (!tpd2.parms) { /* We haven't yet initialized TPD2. Do so now. */ tpd2.arg_uses_template_parms = (int*) alloca (sizeof (int) * nargs); /* The number of parameters here is the number in the m
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -