📄 pt.c
字号:
} } if (specialization || member_specialization) { tree t = TYPE_ARG_TYPES (TREE_TYPE (decl)); for (; t; t = TREE_CHAIN (t)) if (TREE_PURPOSE (t)) { cp_pedwarn ("default argument specified in explicit specialization"); break; } if (current_lang_name == lang_name_c) cp_error ("template specialization with C linkage"); } if (specialization || member_specialization || explicit_instantiation) { tree tmpl = NULL_TREE; tree targs = NULL_TREE; /* Make sure that the declarator is a TEMPLATE_ID_EXPR. */ if (TREE_CODE (declarator) != TEMPLATE_ID_EXPR) { tree fns; my_friendly_assert (TREE_CODE (declarator) == IDENTIFIER_NODE, 0); if (!ctype) fns = IDENTIFIER_NAMESPACE_VALUE (dname); else fns = dname; 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 illegal, but the error will already have been flagged by check_specialization_scope. */ return error_mark_node; else { /* It's not legal 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 illegal) we can get here. The error will be issued later. */ ; } return decl; } else if (TREE_CODE (TREE_OPERAND (declarator, 0)) == LOOKUP_EXPR) { /* A friend declaration. We can't do much, because we don't know what this resolves to, yet. */ my_friendly_assert (is_friend != 0, 0); my_friendly_assert (!explicit_instantiation, 0); SET_DECL_IMPLICIT_INSTANTIATION (decl); return decl; } else if (ctype != NULL_TREE && (TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE)) { /* Find the list of functions in ctype that have the same name as the declared function. */ tree name = TREE_OPERAND (declarator, 0); tree fns = NULL_TREE; int idx; if (name == constructor_name (ctype) || name == constructor_name_full (ctype)) { int is_constructor = DECL_CONSTRUCTOR_P (decl); if (is_constructor ? !TYPE_HAS_CONSTRUCTOR (ctype) : !TYPE_HAS_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]. */ cp_error ("specialization of implicitly-declared special member function"); return error_mark_node; } name = is_constructor ? ctor_identifier : dtor_identifier; } if (!IDENTIFIER_TYPENAME_P (name)) { idx = lookup_fnfields_1 (ctype, name); if (idx >= 0) fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (ctype), idx); } else { tree methods; /* For a type-conversion operator, we cannot do a name-based lookup. We might be looking for `operator int' which will be a specialization of `operator T'. So, we find *all* the conversion operators, and then select from them. */ fns = NULL_TREE; methods = CLASSTYPE_METHOD_VEC (ctype); if (methods) for (idx = 2; idx < TREE_VEC_LENGTH (methods); ++idx) { tree ovl = TREE_VEC_ELT (methods, idx); if (!ovl || !DECL_CONV_FN_P (OVL_CURRENT (ovl))) /* There are no more conversion functions. */ break; /* Glue all these conversion functions together with those we already have. */ for (; ovl; ovl = OVL_NEXT (ovl)) fns = ovl_cons (OVL_CURRENT (ovl), fns); } } if (fns == NULL_TREE) { cp_error ("no member function `%D' declared in `%T'", 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 apriori 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); if (!tmpl || tmpl == error_mark_node) /* We couldn't figure out what this declaration was specializing. */ return error_mark_node; else { 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 fo TARGS. Remove some of them here. */ int i; tree new_targs; new_targs = make_temp_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; } decl = instantiate_template (tmpl, targs); return decl; } /* If we though 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_STATIC_FUNCTION_P (tmpl) && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)) { revert_static_member_fn (&decl, 0, 0); last_function_parms = TREE_CHAIN (last_function_parms); } /* Set up the DECL_TEMPLATE_INFO for DECL. */ DECL_TEMPLATE_INFO (decl) = perm_tree_cons (tmpl, targs, NULL_TREE); /* Mangle the function name appropriately. Note that we do not mangle specializations of non-template member functions of template classes, e.g. with template <class T> struct S { void f(); } and given the specialization template <> void S<int>::f() {} we do not mangle S<int>::f() here. That's because it's just an ordinary member function and doesn't need special treatment. We do this here so that the ordinary, non-template, name-mangling algorith will not be used later. */ if ((is_member_template (tmpl) || ctype == NULL_TREE) && name_mangling_version >= 1) set_mangled_name_for_template_decl (decl); 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); /* Register this specialization so that we can find it again. */ decl = register_specialization (decl, gen_tmpl, targs); } } return decl;}/* TYPE is being declared. Verify that the use of template headers and such is reasonable. Issue error messages if not. */voidmaybe_check_template_type (type) tree type;{ if (template_header_count) { /* We are in the scope of some `template <...>' header. */ int context_depth = template_class_depth_real (TYPE_CONTEXT (type), /*count_specializations=*/1); if (template_header_count <= context_depth) /* This is OK; the template headers are for the context. We are actually too lenient here; like check_explicit_specialization we should consider the number of template types included in the actual declaration. For example, template <class T> struct S { template <class U> template <class V> struct I {}; }; is illegal, but: template <class T> struct S { template <class U> struct I; }; template <class T> template <class U. struct S<T>::I {}; is not. */ ; else if (template_header_count > context_depth + 1) /* There are two many template parameter lists. */ cp_error ("too many template parameter lists in declaration of `%T'", type); }}/* 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 (parms1, parms2) tree parms1; tree parms2;{ tree p1; 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; my_friendly_assert (TREE_CODE (t1) == TREE_VEC, 0); my_friendly_assert (TREE_CODE (t2) == TREE_VEC, 0); if (TREE_VEC_LENGTH (t1) != TREE_VEC_LENGTH (t2)) return 0; for (i = 0; i < TREE_VEC_LENGTH (t2); ++i) { tree parm1 = TREE_VALUE (TREE_VEC_ELT (t1, i)); tree parm2 = TREE_VALUE (TREE_VEC_ELT (t2, i)); if (TREE_CODE (parm1) != TREE_CODE (parm2)) return 0; if (TREE_CODE (parm1) == TEMPLATE_TYPE_PARM) continue; else if (!same_type_p (TREE_TYPE (parm1), TREE_TYPE (parm2))) return 0; } } if ((p1 != NULL_TREE) != (p2 != NULL_TREE)) /* One set of parameters has more parameters lists than the other. */ return 0; return 1;}/* Complain if DECL shadows a template parameter. [temp.local]: A template-parameter shall not be redeclared within its scope (including nested scopes). */voidcheck_template_shadow (decl) tree decl;{ tree olddecl; /* If we're not in a template, we can't possibly shadow a template parameter. */ if (!current_template_parms) return; /* Figure out what we're shadowing. */ if (TREE_CODE (decl) == OVERLOAD) decl = OVL_CURRENT (decl); olddecl = IDENTIFIER_VALUE (DECL_NAME (decl)); /* If there's no previous binding for this name, we're not shadowing anything, let alone a template parameter. */ if (!olddecl) return; /* If we're not shadowing a template parameter, we're done. Note that OLDDECL might be an OVERLOAD (or perhaps even an ERROR_MARK), so we can't just blithely assume it to be a _DECL node. */ if (TREE_CODE_CLASS (TREE_CODE (olddecl)) != 'd' || !DECL_TEMPLATE_PARM_P (olddecl)) return; /* We check for decl != olddecl to avoid bogus errors for using a name inside a class. We check TPFI to avoid duplicate errors for inline member templates. */ if (decl == olddecl || TEMPLATE_PARMS_FOR_INLINE (current_template_parms)) return; cp_error_at ("declaration of `%#D'", decl); cp_error_at (" shadows template parm `%#D'", olddecl);}/* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL, ORIG_LEVEL, DECL, and TYPE. */static treebuild_template_parm_index (index, level, orig_level, decl, type) int index; int level; int orig_level; tree decl; tree type;{ tree t = make_node (TEMPLATE_PARM_INDEX); TEMPLATE_PARM_IDX (t) = index; TEMPLATE_PARM_LEVEL (t) = level; TEMPLATE_PARM_ORIG_LEVEL (t) = orig_level; TEMPLATE_PARM_DECL (t) = decl; TREE_TYPE (t) = type; return t;}/* Return a TEMPLATE_PARM_INDEX, similar to INDEX, but whose TEMPLATE_PARM_LEVEL has been decreased by LEVELS. If such a TEMPLATE_PARM_INDEX already exists, it is returned; otherwise, a new one is created. */static tree reduce_template_parm_level (index, type, levels) tree index; tree type; int levels;{ if (TEMPLATE_PARM_DESCENDANTS (index) == NULL_TREE || (TEMPLATE_PARM_LEVEL (TEMPLATE_PARM_DESCENDANTS (index)) != TEMPLATE_PARM_LEVEL (index) - levels)) { tree decl = build_decl (TREE_CODE (TEMPLATE_PARM_DECL (index)), DECL_NAME (TEMPLATE_PARM_DECL (index)),
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -