📄 cp-pt.c
字号:
overload_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;#ifdef DEBUG_CP_BINDING_LEVELS indent_to (stderr, debug_bindings_indentation); fprintf (stderr, "overload_template_name(%d)", classlevel); debug_bindings_indentation += 4;#endif template = TREE_PURPOSE (template); tinfo = DECL_TEMPLATE_INFO (template); template = DECL_NAME (template); my_friendly_assert (template != NULL_TREE, 285); if (!classlevel) { pushlevel (1); declare_pseudo_global_level (); } t = xref_tag (tinfo->aggr, id, NULL_TREE); my_friendly_assert (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == UNINSTANTIATED_P_TYPE, 286); decl = build_decl (TYPE_DECL, template, t);#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#if 0 /* not yet, should get fixed properly later */ pushdecl (decl); pushlevel (1);#else { pushdecl (decl); /* @@ Is this necessary now? */ IDENTIFIER_LOCAL_VALUE (template) = decl; }#endif#ifdef DEBUG_CP_BINDING_LEVELS debug_bindings_indentation -= 4;#endif}/* T1 is PRE_PARSED_CLASS_DECL; T3 is result of XREF_TAG lookup. */voidend_template_instantiation (t1, t3) tree t1, t3;{ extern struct pending_input *to_be_restored; tree t, decl;#ifdef DEBUG_CP_BINDING_LEVELS indent_to (stderr, debug_bindings_indentation); fprintf (stderr, "end_template_instantiation"); debug_bindings_indentation += 4;#endif processing_template_defn--; /* 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 (TREE_VALUE (t1)); my_friendly_assert (t != NULL_TREE && TREE_CODE_CLASS (TREE_CODE (t)) == 't', 287); CLASSTYPE_USE_TEMPLATE (t) = 2; /* Always make methods of template classes static, until we've got a decent scheme for handling them. The pragmas as they are now are inadequate. */ CLASSTYPE_INTERFACE_UNKNOWN (t) = 1; decl = IDENTIFIER_GLOBAL_VALUE (TREE_VALUE (t1)); my_friendly_assert (TREE_CODE (decl) == TYPE_DECL, 288); undo_template_name_overload (TREE_VALUE (t1), 0); t = IDENTIFIER_TEMPLATE (TREE_VALUE (t1)); pop_template_decls (DECL_TEMPLATE_PARMS (TREE_PURPOSE (t)), TREE_VALUE (t), 0); pop_from_top_level (); /* This will fix up the type-value field. */ pushdecl_top_level (decl); /* Restore interface/implementation settings. */ extract_interface_info ();#ifdef DEBUG_CP_BINDING_LEVELS debug_bindings_indentation -= 4;#endif}/* Store away the text of an inline template function. No rtl is generated for this function until it is actually needed. */voidreinit_parse_for_template (yychar, d1, d2) int yychar; tree d1, d2;{ struct template_info *template_info; if (d2 == NULL_TREE || d2 == error_mark_node) { lose: /* @@ Should use temp obstack, and discard results. */ reinit_parse_for_block (yychar, &permanent_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 (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, &permanent_obstack, 1); template_info->text = obstack_base (&permanent_obstack); template_info->length = obstack_object_size (&permanent_obstack); obstack_finish (&permanent_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. */inttype_unification (tparms, targs, parms, args, nsubsts) tree tparms, *targs, parms, args; int *nsubsts;{ 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); my_friendly_assert (TREE_CODE (args) == TREE_LIST, 291); my_friendly_assert (ntparms > 0, 292); bzero (targs, sizeof (tree) * ntparms); while (parms && parms != void_list_node && args) { 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 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 my_friendly_assert (TREE_TYPE (arg) != NULL_TREE, 293); arg = TREE_TYPE (arg);#endif 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 && 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; 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;{ 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); /* 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_VEC_ELT (tparms, idx)) != IDENTIFIER_NODE) 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]) { 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: 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 (parm) == INTEGER_TYPE && TREE_CODE (arg) == 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); if (TREE_CODE (t1) != TEMPLATE_CONST_PARM) return 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, TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i), nsubsts)) return 1; return 0; } case UNINSTANTIATED_P_TYPE: { tree a; /* Unification of something that is not a template fails. (mrs) */ if (TYPE_NAME (arg) == 0) return 1; a = IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (arg)); /* Unification of something that is not a template fails. (mrs) */ if (a == 0) return 1; if (UPT_TEMPLATE (parm) != TREE_PURPOSE (a)) /* different templates */ return 1; return unify (tparms, targs, ntparms, UPT_PARMS (parm), TREE_VALUE (a), nsubsts); } case RECORD_TYPE: /* Unification of something that is not a template fails. (mrs) */ return 1; default: sorry ("use of `%s' in template type unification", tree_code_name [(int) TREE_CODE (parm)]); return 1; }}#undef DEBUGintdo_pending_expansions (){ struct pending_inline *i, *new_list = 0; if (!pending_template_expansions) return 0;#ifdef DEBUG fprintf (stderr, "\n\n\t\t IN DO_PENDING_EXPANSIONS\n\n");#endif i = pending_template_expansions; while (i) { tree context; struct pending_inline *next = i->next; tree t = i->fndecl; int decision = 0;#define DECIDE(N) if(1){decision=(N); goto decided;}else my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL || TREE_CODE (t) == VAR_DECL, 294); if (TREE_ASM_WRITTEN (t)) DECIDE (0); /* If it's a method, let the class type decide it. @@ What if the method template is in a separate file? Maybe both file contexts should be taken into account? */ context = DECL_CONTEXT (t); if (context != NULL_TREE && TREE_CODE_CLASS (TREE_CODE (context)) == 't') { /* If `unknown', we might want a static copy. If `implementation', we want a global one. If `interface', ext ref. */ if (!CLASSTYPE_INTERFACE_UNKNOWN (context)) DECIDE (!CLASSTYPE_INTERFACE_ONLY (context));#if 0 /* This doesn't get us stuff needed only by the file initializer. */ DECIDE (TREE_USED (t));#else /* This compiles too much stuff, but that's probably better in most cases than never compiling the stuff we need. */ DECIDE (1);#endif } /* else maybe call extract_interface_info? */ if (TREE_USED (t)) /* is this right? */ DECIDE (1); decided:#ifdef DEBUG print_node_brief (stderr, decision ? "yes: " : "no: ", t, 0); fprintf (stderr, "\t%s\n", (DECL_ASSEMBLER_NAME (t) ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t)) : ""));#endif if (decision == 1) { i->next = pending_inlines; pending_inlines = i; } else { i->next = new_list; new_list = i; } i = next; } pending_template_expansions = new_list; if (!pending_inlines) return 0; do_pending_inlines (); return 1;}struct pending_template { struct pending_template *next; tree id;};static struct pending_template* pending_templates;voiddo_pending_templates (){ struct pending_template* t; for ( t = pending_templates; t; t = t->next) { instantiate_class_template (t->id, 1); } for ( t = pending_templates; t; t = pending_templates) { pending_templates = t->next; free(t); }}static voidadd_pending_template (pt) tree pt;{ struct pending_template *p; p = (struct pending_template *) malloc (sizeof (struct pending_template)); p->next = pending_templates; pending_templates = p; p->id = pt;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -