📄 pt.c
字号:
#if 0 /* not yet, should get fixed properly later */ poplevel (0, 0, 0);#endif#if 1 /* XXX */ /* This was a botch... See `overload_template_name' just below. */ if (!classlevel) poplevel (0, 0, 0);#endif}/* classlevel should now never be true. jason 4/12/94 */voidoverload_template_name (id, classlevel) tree id; int classlevel;{ tree template, t, decl; struct template_info *tinfo; my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 284); template = IDENTIFIER_TEMPLATE (id); if (!template) return; template = TREE_PURPOSE (template); tinfo = DECL_TEMPLATE_INFO (template); template = DECL_NAME (template); my_friendly_assert (template != NULL_TREE, 285);#if 1 /* XXX */ /* This was a botch... names of templates do not get their own private scopes. Rather, they should go into the binding level already created by push_template_decls. Except that there isn't one of those for specializations. */ if (!classlevel) { pushlevel (1); declare_pseudo_global_level (); }#endif t = xref_tag (tinfo->aggr, id, NULL_TREE, 1); my_friendly_assert (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNION_TYPE || TREE_CODE (t) == UNINSTANTIATED_P_TYPE, 286); decl = build_decl (TYPE_DECL, template, t); SET_DECL_ARTIFICIAL (decl);#if 0 /* fix this later */ /* We don't want to call here if the work has already been done. */ t = (classlevel ? IDENTIFIER_CLASS_VALUE (template) : IDENTIFIER_LOCAL_VALUE (template)); if (t && TREE_CODE (t) == TYPE_DECL && TREE_TYPE (t) == t) my_friendly_abort (85);#endif if (classlevel) pushdecl_class_level (decl); else pushdecl (decl);#if 0 /* This seems bogus to me; if it isn't, explain why. (jason) */ /* Fake this for now, just to make dwarfout.c happy. It will have to be done in a proper way later on. */ DECL_CONTEXT (decl) = t;#endif}extern struct pending_input *to_be_restored;/* NAME is the IDENTIFIER value of a PRE_PARSED_CLASS_DECL. */voidend_template_instantiation (name) tree name;{ tree t, decl; processing_template_defn--; if (!flag_external_templates) interface_unknown--; /* Restore the old parser input state. */ if (yychar == YYEMPTY) yychar = yylex (); if (yychar != END_OF_SAVED_INPUT) error ("parse error at end of class template"); else { restore_pending_input (to_be_restored); to_be_restored = 0; } /* Our declarations didn't get stored in the global slot, since there was a (supposedly tags-transparent) scope in between. */ t = IDENTIFIER_TYPE_VALUE (name); my_friendly_assert (t != NULL_TREE && TREE_CODE_CLASS (TREE_CODE (t)) == 't', 287); SET_CLASSTYPE_IMPLICIT_INSTANTIATION (t); /* Make methods of template classes static, unless -fexternal-templates is given. */ if (!flag_external_templates) SET_CLASSTYPE_INTERFACE_UNKNOWN (t); decl = IDENTIFIER_GLOBAL_VALUE (name); my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 288); undo_template_name_overload (name, 0); t = IDENTIFIER_TEMPLATE (name); pop_template_decls (DECL_TEMPLATE_PARMS (TREE_PURPOSE (t)), TREE_VALUE (t), 0); /* This will fix up the type-value field. */ pushdecl (decl); pop_from_top_level ();#ifdef DWARF_DEBUGGING_INFO if (write_symbols == DWARF_DEBUG && TREE_CODE (decl) == TYPE_DECL) { /* We just completed the definition of a new file-scope type, so we can go ahead and output debug-info for it now. */ TYPE_STUB_DECL (TREE_TYPE (decl)) = decl; rest_of_type_compilation (TREE_TYPE (decl), 1); }#endif /* DWARF_DEBUGGING_INFO */ /* Restore interface/implementation settings. */ extract_interface_info ();}/* Store away the text of an template. */voidreinit_parse_for_template (yychar, d1, d2) int yychar; tree d1, d2;{ struct template_info *template_info; extern struct obstack inline_text_obstack; /* see comment in lex.c */ if (d2 == NULL_TREE || d2 == error_mark_node) { lose: /* @@ Should use temp obstack, and discard results. */ reinit_parse_for_block (yychar, &inline_text_obstack, 1); return; } if (TREE_CODE (d2) == IDENTIFIER_NODE) d2 = IDENTIFIER_GLOBAL_VALUE (d2); if (!d2) goto lose; template_info = DECL_TEMPLATE_INFO (d2); if (!template_info) { template_info = (struct template_info *) permalloc (sizeof (struct template_info)); bzero ((char *) template_info, sizeof (struct template_info)); DECL_TEMPLATE_INFO (d2) = template_info; } template_info->filename = input_filename; template_info->lineno = lineno; reinit_parse_for_block (yychar, &inline_text_obstack, 1); template_info->text = obstack_base (&inline_text_obstack); template_info->length = obstack_object_size (&inline_text_obstack); obstack_finish (&inline_text_obstack); template_info->parm_vec = d1;}/* Type unification. We have a function template signature with one or more references to template parameters, and a parameter list we wish to fit to this template. If possible, produce a list of parameters for the template which will cause it to fit the supplied parameter list. Return zero for success, 2 for an incomplete match that doesn't resolve all the types, and 1 for complete failure. An error message will be printed only for an incomplete match. TPARMS[NTPARMS] is an array of template parameter types; TARGS[NTPARMS] is the array of template parameter values. PARMS is the function template's signature (using TEMPLATE_PARM_IDX nodes), and ARGS is the argument list we're trying to match against it. If SUBR is 1, we're being called recursively (to unify the arguments of a function or method parameter of a function template), so don't zero out targs and don't fail on an incomplete match. */inttype_unification (tparms, targs, parms, args, nsubsts, subr) tree tparms, *targs, parms, args; int *nsubsts, subr;{ tree parm, arg; int i; int ntparms = TREE_VEC_LENGTH (tparms); my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289); my_friendly_assert (TREE_CODE (parms) == TREE_LIST, 290); /* ARGS could be NULL (via a call from parse.y to build_x_function_call). */ if (args) my_friendly_assert (TREE_CODE (args) == TREE_LIST, 291); my_friendly_assert (ntparms > 0, 292); if (!subr) bzero ((char *) targs, sizeof (tree) * ntparms); while (parms && parms != void_list_node && args && args != void_list_node) { parm = TREE_VALUE (parms); parms = TREE_CHAIN (parms); arg = TREE_VALUE (args); args = TREE_CHAIN (args); if (arg == error_mark_node) return 1; if (arg == unknown_type_node) return 1; if (! uses_template_parms (parm) && TREE_CODE_CLASS (TREE_CODE (arg)) != 't') { if (can_convert_arg (parm, TREE_TYPE (arg), arg)) continue; return 1; } #if 0 if (TREE_CODE (arg) == VAR_DECL) arg = TREE_TYPE (arg); else if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'e') arg = TREE_TYPE (arg);#else if (TREE_CODE_CLASS (TREE_CODE (arg)) != 't') { my_friendly_assert (TREE_TYPE (arg) != NULL_TREE, 293); if (TREE_CODE (arg) == TREE_LIST && TREE_TYPE (arg) == unknown_type_node && TREE_CODE (TREE_VALUE (arg)) == TEMPLATE_DECL) { int nsubsts, ntparms; tree *targs; /* Have to back unify here */ arg = TREE_VALUE (arg); nsubsts = 0; ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (arg)); targs = (tree *) alloca (sizeof (tree) * ntparms); parm = tree_cons (NULL_TREE, parm, NULL_TREE); return type_unification (DECL_TEMPLATE_PARMS (arg), targs, TYPE_ARG_TYPES (TREE_TYPE (arg)), parm, &nsubsts, 0); } arg = TREE_TYPE (arg); }#endif if (TREE_CODE (arg) == REFERENCE_TYPE) arg = TREE_TYPE (arg); if (TREE_CODE (parm) != REFERENCE_TYPE) { if (TREE_CODE (arg) == FUNCTION_TYPE || TREE_CODE (arg) == METHOD_TYPE) arg = build_pointer_type (arg); else if (TREE_CODE (arg) == ARRAY_TYPE) arg = build_pointer_type (TREE_TYPE (arg)); else arg = TYPE_MAIN_VARIANT (arg); } switch (unify (tparms, targs, ntparms, parm, arg, nsubsts)) { case 0: break; case 1: return 1; } } /* Fail if we've reached the end of the parm list, and more args are present, and the parm list isn't variadic. */ if (args && args != void_list_node && parms == void_list_node) return 1; /* Fail if parms are left and they don't have default values. */ if (parms && parms != void_list_node && TREE_PURPOSE (parms) == NULL_TREE) return 1; if (!subr) for (i = 0; i < ntparms; i++) if (!targs[i]) { error ("incomplete type unification"); return 2; } return 0;}/* Tail recursion is your friend. */static intunify (tparms, targs, ntparms, parm, arg, nsubsts) tree tparms, *targs, parm, arg; int *nsubsts, ntparms;{ int idx; /* I don't think this will do the right thing with respect to types. But the only case I've seen it in so far has been array bounds, where signedness is the only information lost, and I think that will be okay. */ while (TREE_CODE (parm) == NOP_EXPR) parm = TREE_OPERAND (parm, 0); if (arg == error_mark_node) return 1; if (arg == unknown_type_node) return 1; if (arg == parm) return 0; switch (TREE_CODE (parm)) { case TEMPLATE_TYPE_PARM: (*nsubsts)++; if (TEMPLATE_TYPE_TPARMLIST (parm) != tparms) { error ("mixed template headers?!"); my_friendly_abort (86); return 1; } idx = TEMPLATE_TYPE_IDX (parm);#if 0 /* Template type parameters cannot contain cv-quals; i.e. template <class T> void f (T& a, T& b) will not generate void f (const int& a, const int& b). */ if (TYPE_READONLY (arg) > TYPE_READONLY (parm) || TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm)) return 1; arg = TYPE_MAIN_VARIANT (arg);#else { int constp = TYPE_READONLY (arg) > TYPE_READONLY (parm); int volatilep = TYPE_VOLATILE (arg) > TYPE_VOLATILE (parm); arg = cp_build_type_variant (arg, constp, volatilep); }#endif /* Simple cases: Value already set, does match or doesn't. */ if (targs[idx] == arg) return 0; else if (targs[idx]) return 1; /* Check for mixed types and values. */ if (TREE_CODE (TREE_VALUE (TREE_VEC_ELT (tparms, idx))) != TYPE_DECL) return 1; targs[idx] = arg; return 0; case TEMPLATE_CONST_PARM: (*nsubsts)++; idx = TEMPLATE_CONST_IDX (parm); if (targs[idx] == arg) return 0; else if (targs[idx]) { tree t = targs[idx]; if (TREE_CODE (t) == TREE_CODE (arg)) switch (TREE_CODE (arg)) { case INTEGER_CST: if (tree_int_cst_equal (t, arg)) return 0; break; case REAL_CST: if (REAL_VALUES_EQUAL (TREE_REAL_CST (t), TREE_REAL_CST (arg))) return 0; break; /* STRING_CST values are not valid template const parms. */ default: ; } my_friendly_abort (87); return 1; }/* else if (typeof arg != tparms[idx]) return 1;*/ targs[idx] = copy_to_permanent (arg); return 0; case POINTER_TYPE: if (TREE_CODE (arg) != POINTER_TYPE) return 1; return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg), nsubsts); case REFERENCE_TYPE: if (TREE_CODE (arg) == REFERENCE_TYPE) arg = TREE_TYPE (arg); return unify (tparms, targs, ntparms, TREE_TYPE (parm), arg, nsubsts); case ARRAY_TYPE: if (TREE_CODE (arg) != ARRAY_TYPE) return 1; if (unify (tparms, targs, ntparms, TYPE_DOMAIN (parm), TYPE_DOMAIN (arg), nsubsts) != 0) return 1; return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg), nsubsts); case REAL_TYPE: case INTEGER_TYPE: if (TREE_CODE (arg) != TREE_CODE (parm)) return 1; if (TREE_CODE (parm) == INTEGER_TYPE) { if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg) && unify (tparms, targs, ntparms, TYPE_MIN_VALUE (parm), TYPE_MIN_VALUE (arg), nsubsts)) return 1; if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg) && unify (tparms, targs, ntparms, TYPE_MAX_VALUE (parm), TYPE_MAX_VALUE (arg), nsubsts)) return 1; } /* As far as unification is concerned, this wins. Later checks will invalidate it if necessary. */ return 0; /* Types INTEGER_CST and MINUS_EXPR can come from array bounds. */ case INTEGER_CST: if (TREE_CODE (arg) != INTEGER_CST) return 1; return !tree_int_cst_equal (parm, arg); case MINUS_EXPR: { tree t1, t2; t1 = TREE_OPERAND (parm, 0); t2 = TREE_OPERAND (parm, 1); return unify (tparms, targs, ntparms, t1, fold (build (PLUS_EXPR, integer_type_node, arg, t2)), nsubsts); } case TREE_VEC: { int i; if (TREE_CODE (arg) != TREE_VEC) return 1; if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg)) return 1; for (i = TREE_VEC_LENGTH (parm) - 1; i >= 0; i--) if (unify (tparms, targs, ntparms, TR
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -