📄 cp-pt.c
字号:
significant? */ && type != integer_type_node && type != void_type_node && type != char_type_node) type = build_type_variant (tsubst (type, args, nargs), TYPE_READONLY (type), TYPE_VOLATILE (type)); switch (TREE_CODE (t)) { case ERROR_MARK: case IDENTIFIER_NODE: case OP_IDENTIFIER: case VOID_TYPE: case REAL_TYPE: case ENUMERAL_TYPE: case INTEGER_CST: case REAL_CST: case STRING_CST: case RECORD_TYPE: case UNION_TYPE: return t; case INTEGER_TYPE: if (t == integer_type_node) return t; if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST) return t; return build_index_2_type (tsubst (TYPE_MIN_VALUE (t), args, nargs), tsubst (TYPE_MAX_VALUE (t), args, nargs)); case TEMPLATE_TYPE_PARM: return build_type_variant (args[TEMPLATE_TYPE_IDX (t)], TYPE_READONLY (t), TYPE_VOLATILE (t)); case TEMPLATE_CONST_PARM: return args[TEMPLATE_CONST_IDX (t)]; case FUNCTION_DECL: { tree r; tree fnargs, result; if (type == TREE_TYPE (t) && (DECL_CONTEXT (t) == NULL_TREE || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't')) return t; fnargs = tsubst (DECL_ARGUMENTS (t), args, nargs); result = tsubst (DECL_RESULT (t), args, nargs); if (DECL_CONTEXT (t) != NULL_TREE && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't') { /* Look it up in that class, and return the decl node there, instead of creating a new one. */ tree ctx, methods, name, method; int n_methods; int i, found = 0; name = DECL_NAME (t); ctx = tsubst (DECL_CONTEXT (t), args, nargs); methods = CLASSTYPE_METHOD_VEC (ctx); if (methods == NULL_TREE) /* No methods at all -- no way this one can match. */ goto no_match; n_methods = TREE_VEC_LENGTH (methods); r = NULL_TREE; if (!strncmp (OPERATOR_TYPENAME_FORMAT, IDENTIFIER_POINTER (name), sizeof (OPERATOR_TYPENAME_FORMAT) - 1)) { /* Type-conversion operator. Reconstruct the name, in case it's the name of one of the template's parameters. */ name = build_typename_overload (TREE_TYPE (type)); } if (DECL_CONTEXT (t) != NULL_TREE && TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) == 't' && constructor_name (DECL_CONTEXT (t)) == DECL_NAME (t)) name = constructor_name (ctx);#if 0 fprintf (stderr, "\nfor function %s in class %s:\n", IDENTIFIER_POINTER (name), IDENTIFIER_POINTER (TYPE_IDENTIFIER (ctx)));#endif for (i = 0; i < n_methods; i++) { method = TREE_VEC_ELT (methods, i); if (method == NULL_TREE || DECL_NAME (method) != name) continue; for (; method; method = TREE_CHAIN (method)) { my_friendly_assert (TREE_CODE (method) == FUNCTION_DECL, 282); if (TREE_TYPE (method) != type) { tree mtype = TREE_TYPE (method); tree t1, t2; t1 = TYPE_ARG_TYPES (mtype); t2 = TYPE_ARG_TYPES (type); if (TREE_CODE (mtype) == FUNCTION_TYPE) t2 = TREE_CHAIN (t2); if (list_eq (t1, t2)) { if (TREE_CODE (mtype) == FUNCTION_TYPE) { tree newtype; newtype = build_function_type (TREE_TYPE (type), TYPE_ARG_TYPES (type)); newtype = build_type_variant (newtype, TYPE_READONLY (type), TYPE_VOLATILE (type)); type = newtype; if (TREE_TYPE (type) != TREE_TYPE (mtype)) goto maybe_bad_return_type; } else if (TYPE_METHOD_BASETYPE (mtype) == TYPE_METHOD_BASETYPE (type)) { /* Types didn't match, but arg types and `this' do match, so the return type is all that should be messing it up. */ maybe_bad_return_type: if (TREE_TYPE (type) != TREE_TYPE (mtype)) error ("inconsistent return types for method `%s' in class `%s'", IDENTIFIER_POINTER (name), IDENTIFIER_POINTER (TYPE_IDENTIFIER (ctx))); } r = method; break; } found = 1; continue; }#if 0 fprintf (stderr, "\tfound %s\n\n", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (method)));#endif if (! TREE_PERMANENT (DECL_ARGUMENTS (method))) /* @@ Is this early enough? Might we want to do this instead while processing the expansion? */ DECL_ARGUMENTS (method) = tsubst (DECL_ARGUMENTS (t), args, nargs); r = method; break; } } if (r == NULL_TREE) { no_match: error (found ? "template for method `%s' doesn't match any in class `%s'" : "method `%s' not found in class `%s'", IDENTIFIER_POINTER (name), IDENTIFIER_POINTER (TYPE_IDENTIFIER (ctx))); return error_mark_node; } } else { r = DECL_NAME (t); { tree decls, val; int got_it = 0; decls = IDENTIFIER_GLOBAL_VALUE (r); if (decls == NULL_TREE) /* no match */; else if (TREE_CODE (decls) == TREE_LIST) while (decls) { val = TREE_VALUE (decls); decls = TREE_CHAIN (decls); try_one: if (TREE_CODE (val) == FUNCTION_DECL && TREE_TYPE (val) == type) { got_it = 1; r = val; break; } } else { val = decls; decls = NULL_TREE; goto try_one; } if (!got_it) r = build_lang_decl (FUNCTION_DECL, r, type); } } TREE_PUBLIC (r) = TREE_PUBLIC (t); DECL_EXTERNAL (r) = DECL_EXTERNAL (t); TREE_STATIC (r) = TREE_STATIC (t); DECL_INLINE (r) = DECL_INLINE (t); 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); make_decl_rtl (r, 0, 1); DECL_ARGUMENTS (r) = fnargs; DECL_RESULT (r) = result; if (DECL_CONTEXT (t) == NULL_TREE || TREE_CODE_CLASS (TREE_CODE (DECL_CONTEXT (t))) != 't') push_overloaded_decl_top_level (r, 0); return r; } case PARM_DECL: { tree r; r = build_decl (PARM_DECL, DECL_NAME (t), type); DECL_INITIAL (r) = TREE_TYPE (r); if (TREE_CHAIN (t)) TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, nargs); 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); value = TREE_VALUE (t); if (value) value = tsubst (value, args, nargs); chain = TREE_CHAIN (t); if (chain && chain != void_type_node) chain = tsubst (chain, args, nargs); 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 (elts, len * sizeof (tree)); for (i = 0; i < len; i++) { elts[i] = tsubst (TREE_VEC_ELT (t, i), args, nargs); 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 = 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 FUNCTION_TYPE: case METHOD_TYPE: { tree values = TYPE_VALUES (t); /* same as TYPE_ARG_TYPES */ tree context = TYPE_CONTEXT (t); tree new_value; /* Don't bother recursing if we know it won't change anything. */ if (! (values == void_type_node || values == integer_type_node)) values = tsubst (values, args, nargs); if (context) context = tsubst (context, args, nargs); /* 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); 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); /* 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); 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; for (i = 0; i < nparms; i++) TREE_VEC_ELT (argvec, i) = tsubst (TREE_VEC_ELT (parmvec, i), args, nargs); id = lookup_template_class (DECL_NAME (UPT_TEMPLATE (t)), argvec); 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); } return build_type_variant (IDENTIFIER_TYPE_VALUE (id), 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), tsubst (TREE_OPERAND (t, 1), args, nargs))); case NEGATE_EXPR: case NOP_EXPR: return fold (build1 (TREE_CODE (t), TREE_TYPE (t), tsubst (TREE_OPERAND (t, 0), args, nargs))); 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)); 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 (t1[i] != targ_ptr[i]) goto no_match; /* Here, we have a match. */ fndecl = TREE_VALUE (fndecl); function_maybepermanent_obstack = old_fmp_obstack; pop_obstacks (); return fndecl; 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)); t = DECL_TEMPLATE_INFO (tmpl); if (t->text) { 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->lineno = t->lineno; p->filename = t->filename; p->buf = t->text; p->len = t->length; p->fndecl = fndecl; p->interface = 1; /* unknown */ } else p = 0; DECL_TEMPLATE_INSTANTIATIONS (tmpl) = tree_cons (targs, fndecl, DECL_TEMPLATE_INSTANTIATIONS (tmpl)); function_maybepermanent_obstack = old_fmp_obstack; pop_obstacks (); if (fndecl == error_mark_node || p == 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; } return fndecl;}voidundo_template_name_overload (id, classlevel) tree id; int classlevel;{ tree template; template = IDENTIFIER_TEMPLATE (id); if (!template) return;#ifdef DEBUG_CP_BINDING_LEVELS indent_to (stderr, debug_bindings_indentation); fprintf (stderr, "undo_template_name_overload"); debug_bindings_indentation += 4;#endif#if 0 /* not yet, should get fixed properly later */ poplevel (0, 0, 0);#endif if (!classlevel) poplevel (0, 0, 0);#ifdef DEBUG_CP_BINDING_LEVELS debug_bindings_indentation -= 4;#endif}void
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -