📄 pt.c
字号:
we can pop them later. */ if (!inline_parm_levels) VARRAY_INT_INIT (inline_parm_levels, 4, "inline_parm_levels"); if (inline_parm_levels_used == inline_parm_levels->num_elements) VARRAY_GROW (inline_parm_levels, 2 * inline_parm_levels_used); VARRAY_INT (inline_parm_levels, inline_parm_levels_used) = levels; ++inline_parm_levels_used;}/* Undo the effects of begin_member_template_processing. */void maybe_end_member_template_processing (){ int i; if (!inline_parm_levels_used) return; --inline_parm_levels_used; for (i = 0; i < VARRAY_INT (inline_parm_levels, inline_parm_levels_used); ++i) { --processing_template_decl; current_template_parms = TREE_CHAIN (current_template_parms); poplevel (0, 0, 0); }}/* Returns non-zero iff T is a member template function. We must be careful as in template <class T> class C { void f(); } Here, f is a template function, and a member, but not a member template. This function does not concern itself with the origin of T, only its present state. So if we have template <class T> class C { template <class U> void f(U); } then neither C<int>::f<char> nor C<T>::f<double> is considered to be a member template. But, `template <class U> void C<int>::f(U)' is considered a member template. */intis_member_template (t) tree t;{ if (!DECL_FUNCTION_TEMPLATE_P (t)) /* Anything that isn't a function or a template function is certainly not a member template. */ return 0; /* A local class can't have member templates. */ if (hack_decl_function_context (t)) return 0; return (DECL_FUNCTION_MEMBER_P (DECL_TEMPLATE_RESULT (t)) /* If there are more levels of template parameters than there are template classes surrounding the declaration, then we have a member template. */ && (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) > template_class_depth (DECL_CLASS_CONTEXT (t))));}#if 0 /* UNUSED *//* Returns non-zero iff T is a member template class. See is_member_template for a description of what precisely constitutes a member template. */intis_member_template_class (t) tree t;{ if (!DECL_CLASS_TEMPLATE_P (t)) /* Anything that isn't a class template, is certainly not a member template. */ return 0; if (!DECL_CLASS_SCOPE_P (t)) /* Anything whose context isn't a class type is surely not a member template. */ return 0; /* If there are more levels of template parameters than there are template classes surrounding the declaration, then we have a member template. */ return (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (t)) > template_class_depth (DECL_CONTEXT (t)));}#endif/* Return a new template argument vector which contains all of ARGS, but has as its innermost set of arguments the EXTRA_ARGS. The resulting vector will be built on a temporary obstack, and so must be explicitly copied to the permanent obstack, if required. */static treeadd_to_template_args (args, extra_args) tree args; tree extra_args;{ tree new_args; int extra_depth; int i; int j; extra_depth = TMPL_ARGS_DEPTH (extra_args); new_args = make_temp_vec (TMPL_ARGS_DEPTH (args) + extra_depth); for (i = 1; i <= TMPL_ARGS_DEPTH (args); ++i) SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (args, i)); for (j = 1; j <= extra_depth; ++j, ++i) SET_TMPL_ARGS_LEVEL (new_args, i, TMPL_ARGS_LEVEL (extra_args, j)); return new_args;}/* Like add_to_template_args, but only the outermost ARGS are added to the EXTRA_ARGS. In particular, all but TMPL_ARGS_DEPTH (EXTRA_ARGS) levels are added. This function is used to combine the template arguments from a partial instantiation with the template arguments used to attain the full instantiation from the partial instantiation. */static treeadd_outermost_template_args (args, extra_args) tree args; tree extra_args;{ tree new_args; /* If there are more levels of EXTRA_ARGS than there are ARGS, something very fishy is going on. */ my_friendly_assert (TMPL_ARGS_DEPTH (args) >= TMPL_ARGS_DEPTH (extra_args), 0); /* 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;}/* We've got a template header coming up; push to a new level for storing the parms. */voidbegin_template_parm_list (){ /* 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 call pushdecl_with_scope on the TEMPLATE_DECL for S2. */ pushlevel (0); declare_pseudo_global_level (); ++processing_template_decl; ++processing_template_parmlist; note_template_header (0);}/* This routine is called when a specialization is declared. If it is illegal to declare a specialization here, an error is reported. */static voidcheck_specialization_scope (){ 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) cp_error ("explicit specialization in non-namespace scope `%D'", scope); /* [temp.expl.spec] In an explicit specialization declaration for a member of a class template or a member template that appears in namespace scope, the member template and some of its enclosing class templates may remain unspecialized, except that the declaration shall not explicitly specialize a class member template if its enclosing class templates are not explicitly specialized as well. */ if (current_template_parms) cp_error ("enclosing class templates are not explicitly specialized");}/* We've just seen template <>. */voidbegin_specialization (){ note_template_header (1); check_specialization_scope ();}/* Called at then end of processing a declaration preceeded by template<>. */void end_specialization (){ reset_specialization ();}/* Any template <>'s that we have seen thus far are not referring to a function specialization. */voidreset_specialization (){ processing_specialization = 0; template_header_count = 0;}/* We've just seen a template header. If SPECIALIZATION is non-zero, it was of the form template <>. */static void note_template_header (specialization) int specialization;{ processing_specialization = specialization; template_header_count++;}/* We're beginning an explicit instantiation. */voidbegin_explicit_instantiation (){ ++processing_explicit_instantiation;}voidend_explicit_instantiation (){ my_friendly_assert(processing_explicit_instantiation > 0, 0); --processing_explicit_instantiation;}/* The TYPE is being declared. If it is a template type, that means it is a partial specialization. Do appropriate error-checking. */void maybe_process_partial_specialization (type) tree type;{ if (IS_AGGR_TYPE (type) && CLASSTYPE_USE_TEMPLATE (type)) { if (CLASSTYPE_IMPLICIT_INSTANTIATION (type) && TYPE_SIZE (type) == NULL_TREE) { if (current_namespace != decl_namespace_context (CLASSTYPE_TI_TEMPLATE (type))) { cp_pedwarn ("specializing `%#T' in different namespace", type); cp_pedwarn_at (" from definition of `%#D'", CLASSTYPE_TI_TEMPLATE (type)); } SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (type); if (processing_template_decl) push_template_decl (TYPE_MAIN_DECL (type)); } else if (CLASSTYPE_TEMPLATE_INSTANTIATION (type)) cp_error ("specialization of `%T' after instantiation", type); } else if (processing_specialization) cp_error ("explicit specialization of non-template `%T'", type);}/* 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. */ static treeretrieve_specialization (tmpl, args) tree tmpl; tree args;{ tree s; my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0); /* There should be as many levels of arguments as there are levels of parameters. */ my_friendly_assert (TMPL_ARGS_DEPTH (args) == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)), 0); for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); s != NULL_TREE; s = TREE_CHAIN (s)) if (comp_template_args (TREE_PURPOSE (s), args)) return TREE_VALUE (s); return NULL_TREE;}/* Returns non-zero iff DECL is a specialization of TMPL. */intis_specialization_of (decl, tmpl) 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 { my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 0); for (t = TREE_TYPE (decl); t != NULL_TREE; t = CLASSTYPE_USE_TEMPLATE (t) ? TREE_TYPE (CLASSTYPE_TI_TEMPLATE (t)) : NULL_TREE) if (same_type_p (TYPE_MAIN_VARIANT (t), TYPE_MAIN_VARIANT (TREE_TYPE (tmpl)))) return 1; } return 0;}/* Register the specialization SPEC as a specialization of TMPL with the indicated ARGS. Returns SPEC, or an equivalent prior declaration, if available. */static treeregister_specialization (spec, tmpl, args) tree spec; tree tmpl; tree args;{ tree s; my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0); 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; /* There should be as many levels of arguments as there are levels of parameters. */ my_friendly_assert (TMPL_ARGS_DEPTH (args) == TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (tmpl)), 0); for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl); s != NULL_TREE; s = TREE_CHAIN (s)) if (comp_template_args (TREE_PURPOSE (s), args)) { tree fn = TREE_VALUE (s); if (DECL_TEMPLATE_SPECIALIZATION (spec)) { if (DECL_TEMPLATE_INSTANTIATION (fn)) { if (TREE_USED (fn) || DECL_EXPLICIT_INSTANTIATION (fn)) { cp_error ("specialization of %D after instantiation", fn); return spec; } else { /* This situation should occur only if the first specialization is an implicit instantiation, the second is an explicit specialization, and the implicit instantiation has not yet been used. That situation can occur if we have implicitly instantiated a member function and then specialized it later. We can also wind up here if a friend declaration that looked like an instantiation
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -