📄 pt.c
字号:
goto maybe_error; } } if (r == NULL_TREE) { no_match: cp_error (found ? "template for method `%D' doesn't match any in class `%T'" : "method `%D' not found in class `%T'", name, ctx); if (in_decl) cp_error_at ("in attempt to instantiate `%D' declared at this point in file", in_decl); return error_mark_node; } } else { r = DECL_NAME (t); { tree decls; int got_it = 0; decls = lookup_name_nonclass (r); if (decls == NULL_TREE) /* no match */; else if (TREE_CODE (decls) == TREE_LIST) for (decls = TREE_VALUE (decls); decls ; decls = DECL_CHAIN (decls)) { if (TREE_CODE (decls) == FUNCTION_DECL && TREE_TYPE (decls) == type) { got_it = 1; r = decls; break; } } else { tree val = decls; decls = NULL_TREE; if (TREE_CODE (val) == FUNCTION_DECL && TREE_TYPE (val) == type) { got_it = 1; r = val; } } if (!got_it) { tree a = build_decl_overload (r, TYPE_VALUES (type), DECL_CONTEXT (t) != NULL_TREE); r = build_lang_decl (FUNCTION_DECL, r, type); DECL_ASSEMBLER_NAME (r) = a; } else if (TREE_STATIC (r)) { /* This overrides the template version, use it. */ return r; } } } TREE_PUBLIC (r) = 1; DECL_EXTERNAL (r) = 1; TREE_STATIC (r) = 0; DECL_INTERFACE_KNOWN (r) = 0; DECL_INLINE (r) = DECL_INLINE (t); DECL_THIS_INLINE (r) = DECL_THIS_INLINE (t); TREE_READONLY (r) = TREE_READONLY (t); TREE_THIS_VOLATILE (r) = TREE_THIS_VOLATILE (t); {#if 0 /* Maybe later. -jason */ struct tinst_level *til = tinst_for_decl(); /* should always be true under new approach */ if (til) { DECL_SOURCE_FILE (r) = til->file; DECL_SOURCE_LINE (r) = til->line; } else#endif { DECL_SOURCE_FILE (r) = DECL_SOURCE_FILE (t); DECL_SOURCE_LINE (r) = DECL_SOURCE_LINE (t); } } DECL_CLASS_CONTEXT (r) = tsubst (DECL_CLASS_CONTEXT (t), args, nargs, t); make_decl_rtl (r, NULL_PTR, 1); DECL_ARGUMENTS (r) = fnargs; DECL_RESULT (r) = result;#if 0 if (DECL_CONTEXT (t) == NULL_TREE || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't') push_overloaded_decl_top_level (r, 0);#endif return r; } case PARM_DECL: { tree r; r = build_decl (PARM_DECL, DECL_NAME (t), type); DECL_INITIAL (r) = TREE_TYPE (r); DECL_ARTIFICIAL (r) = DECL_ARTIFICIAL (t);#ifdef PROMOTE_PROTOTYPES if ((TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == ENUMERAL_TYPE) && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) DECL_ARG_TYPE (r) = integer_type_node;#endif if (TREE_CHAIN (t)) TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, nargs, TREE_CHAIN (t)); return r; } case TREE_LIST: { tree purpose, value, chain, result; int via_public, via_virtual, via_protected; if (t == void_list_node) return t; via_public = TREE_VIA_PUBLIC (t); via_protected = TREE_VIA_PROTECTED (t); via_virtual = TREE_VIA_VIRTUAL (t); purpose = TREE_PURPOSE (t); if (purpose) purpose = tsubst (purpose, args, nargs, in_decl); value = TREE_VALUE (t); if (value) value = tsubst (value, args, nargs, in_decl); chain = TREE_CHAIN (t); if (chain && chain != void_type_node) chain = tsubst (chain, args, nargs, in_decl); if (purpose == TREE_PURPOSE (t) && value == TREE_VALUE (t) && chain == TREE_CHAIN (t)) return t; result = hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain); TREE_PARMLIST (result) = TREE_PARMLIST (t); return result; } case TREE_VEC: { int len = TREE_VEC_LENGTH (t), need_new = 0, i; tree *elts = (tree *) alloca (len * sizeof (tree)); bzero ((char *) elts, len * sizeof (tree)); for (i = 0; i < len; i++) { elts[i] = tsubst (TREE_VEC_ELT (t, i), args, nargs, in_decl); if (elts[i] != TREE_VEC_ELT (t, i)) need_new = 1; } if (!need_new) return t; t = make_tree_vec (len); for (i = 0; i < len; i++) TREE_VEC_ELT (t, i) = elts[i]; return t; } case POINTER_TYPE: case REFERENCE_TYPE: { tree r; enum tree_code code; if (type == TREE_TYPE (t)) return t; code = TREE_CODE (t); if (code == POINTER_TYPE) r = build_pointer_type (type); else r = build_reference_type (type); r = cp_build_type_variant (r, TYPE_READONLY (t), TYPE_VOLATILE (t)); /* Will this ever be needed for TYPE_..._TO values? */ layout_type (r); return r; } case OFFSET_TYPE: return build_offset_type (tsubst (TYPE_OFFSET_BASETYPE (t), args, nargs, in_decl), type); case FUNCTION_TYPE: case METHOD_TYPE: { tree values = TYPE_ARG_TYPES (t); tree context = TYPE_CONTEXT (t); tree new_value; /* Don't bother recursing if we know it won't change anything. */ if (values != void_list_node) values = tsubst (values, args, nargs, in_decl); if (context) context = tsubst (context, args, nargs, in_decl); /* Could also optimize cases where return value and values have common elements (e.g., T min(const &T, const T&). */ /* If the above parameters haven't changed, just return the type. */ if (type == TREE_TYPE (t) && values == TYPE_VALUES (t) && context == TYPE_CONTEXT (t)) return t; /* Construct a new type node and return it. */ if (TREE_CODE (t) == FUNCTION_TYPE && context == NULL_TREE) { new_value = build_function_type (type, values); } else if (context == NULL_TREE) { tree base = tsubst (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), args, nargs, in_decl); new_value = build_cplus_method_type (base, type, TREE_CHAIN (values)); } else { new_value = make_node (TREE_CODE (t)); TREE_TYPE (new_value) = type; TYPE_CONTEXT (new_value) = context; TYPE_VALUES (new_value) = values; TYPE_SIZE (new_value) = TYPE_SIZE (t); TYPE_ALIGN (new_value) = TYPE_ALIGN (t); TYPE_MODE (new_value) = TYPE_MODE (t); if (TYPE_METHOD_BASETYPE (t)) TYPE_METHOD_BASETYPE (new_value) = tsubst (TYPE_METHOD_BASETYPE (t), args, nargs, in_decl); /* Need to generate hash value. */ my_friendly_abort (84); } new_value = build_type_variant (new_value, TYPE_READONLY (t), TYPE_VOLATILE (t)); return new_value; } case ARRAY_TYPE: { tree domain = tsubst (TYPE_DOMAIN (t), args, nargs, in_decl); tree r; if (type == TREE_TYPE (t) && domain == TYPE_DOMAIN (t)) return t; r = build_cplus_array_type (type, domain); return r; } case UNINSTANTIATED_P_TYPE: { int nparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (UPT_TEMPLATE (t))); tree argvec = make_tree_vec (nparms); tree parmvec = UPT_PARMS (t); int i; tree id, rt; for (i = 0; i < nparms; i++) TREE_VEC_ELT (argvec, i) = tsubst (TREE_VEC_ELT (parmvec, i), args, nargs, in_decl); id = lookup_template_class (DECL_NAME (UPT_TEMPLATE (t)), argvec, NULL_TREE); if (! IDENTIFIER_HAS_TYPE_VALUE (id)) { instantiate_class_template(id, 0); /* set up pending_classes */ add_pending_template (id); TYPE_MAIN_VARIANT (IDENTIFIER_TYPE_VALUE (id)) = IDENTIFIER_TYPE_VALUE (id); } rt = IDENTIFIER_TYPE_VALUE (id); /* kung: this part handles nested type in template definition */ if ( !ANON_AGGRNAME_P (DECL_NAME(TYPE_NAME(t)))) { rt = search_nested_type_in_tmpl (rt, t); } return build_type_variant (rt, TYPE_READONLY (t), TYPE_VOLATILE (t)); } case MINUS_EXPR: case PLUS_EXPR: return fold (build (TREE_CODE (t), TREE_TYPE (t), tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl), tsubst (TREE_OPERAND (t, 1), args, nargs, in_decl))); case NEGATE_EXPR: case NOP_EXPR: return fold (build1 (TREE_CODE (t), TREE_TYPE (t), tsubst (TREE_OPERAND (t, 0), args, nargs, in_decl))); default: sorry ("use of `%s' in function template", tree_code_name [(int) TREE_CODE (t)]); return error_mark_node; }}treeinstantiate_template (tmpl, targ_ptr) tree tmpl, *targ_ptr;{ tree targs, fndecl; int i, len; struct pending_inline *p; struct template_info *t; struct obstack *old_fmp_obstack; extern struct obstack *function_maybepermanent_obstack; push_obstacks (&permanent_obstack, &permanent_obstack); old_fmp_obstack = function_maybepermanent_obstack; function_maybepermanent_obstack = &permanent_obstack; my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 283); len = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl)); i = len; while (i--) targ_ptr[i] = copy_to_permanent (targ_ptr[i]); for (fndecl = DECL_TEMPLATE_INSTANTIATIONS (tmpl); fndecl; fndecl = TREE_CHAIN (fndecl)) { tree *t1 = &TREE_VEC_ELT (TREE_PURPOSE (fndecl), 0); for (i = len - 1; i >= 0; i--) if (simple_cst_equal (t1[i], targ_ptr[i]) <= 0) goto no_match; /* Here, we have a match. */ fndecl = TREE_VALUE (fndecl); goto exit; no_match: ; } targs = make_tree_vec (len); i = len; while (i--) TREE_VEC_ELT (targs, i) = targ_ptr[i]; /* substitute template parameters */ fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr, TREE_VEC_LENGTH (targs), tmpl); if (fndecl == error_mark_node) goto exit; assemble_external (fndecl); /* If it's a static member fn in the template, we need to change it into a FUNCTION_TYPE and chop off its this pointer. */ if (TREE_CODE (TREE_TYPE (DECL_RESULT (tmpl))) == METHOD_TYPE && DECL_STATIC_FUNCTION_P (fndecl)) { revert_static_member_fn (&DECL_RESULT (tmpl), NULL, NULL); /* Chop off the this pointer that grokclassfn so kindly added for us (it didn't know yet if the fn was static or not). */ DECL_ARGUMENTS (fndecl) = TREE_CHAIN (DECL_ARGUMENTS (fndecl)); } t = DECL_TEMPLATE_INFO (tmpl); /* If we have a preexisting version of this function, don't expand the template version, use the other instead. */ if (TREE_STATIC (fndecl) || DECL_TEMPLATE_SPECIALIZATION (fndecl)) { SET_DECL_TEMPLATE_SPECIALIZATION (fndecl); p = (struct pending_inline *)0; } else if (t->text) { SET_DECL_IMPLICIT_INSTANTIATION (fndecl); repo_template_used (fndecl); p = (struct pending_inline *) permalloc (sizeof (struct pending_inline)); p->parm_vec = t->parm_vec; p->bindings = targs; p->can_free = 0; p->deja_vu = 0; p->buf = t->text; p->len = t->length; p->fndecl = fndecl; { int l = lineno; char * f = input_filename; lineno = p->lineno = t->lineno; input_filename = p->filename = t->filename; extract_interface_info (); if (interface_unknown && flag_external_templates) { if (DECL_CLASS_CONTEXT (fndecl) && CLASSTYPE_INTERFACE_KNOWN (DECL_CLASS_CONTEXT (fndecl))) { interface_unknown = 0; interface_only = CLASSTYPE_INTERFACE_ONLY (DECL_CLASS_CONTEXT (fndecl)); } else if (! DECL_IN_SYSTEM_HEADER (tmpl)) warn_if_unknown_interface (tmpl); } if (interface_unknown || ! flag_external_templates) p->interface = 1; /* unknown */ else p->interface = interface_only ? 0 : 2; lineno = l; input_filename = f; extract_interface_info (); } } else p = (struct pending_inline *)0; DECL_TEMPLATE_INSTANTIATIONS (tmpl) = tree_cons (targs, fndecl, DECL_TEMPLATE_INSTANTIATIONS (tmpl)); if (p == (struct pending_inline *)0) { /* do nothing */ } else if (DECL_INLINE (fndecl)) { DECL_PENDING_INLINE_INFO (fndecl) = p; p->next = pending_inlines; pending_inlines = p; } else { p->next = pending_template_expansions; pending_template_expansions = p; } exit: function_maybepermanent_obstack = old_fmp_obstack; pop_obstacks (); return fndecl;}/* classlevel should now never be true. jason 4/12/94 */voidundo_template_name_overload (id, classlevel) tree id; int classlevel;{ tree template; template = IDENTIFIER_TEMPLATE (id); if (!template) return;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -