📄 pt.c
字号:
TREE_CODE (TREE_TYPE (TREE_TYPE (val))) == FUNCTION_TYPE ? "a function" : "an object"); val = error_mark_node; } } } if (val == error_mark_node) lost++; TREE_VEC_ELT (vec, i) = val; } if (lost) return error_mark_node; return vec;}/* Given class template name and parameter list, produce a user-friendly name for the instantiation. */static char *mangle_class_name_for_template (name, parms, arglist) char *name; tree parms, arglist;{ static struct obstack scratch_obstack; static char *scratch_firstobj; int i, nparms; if (!scratch_firstobj) { gcc_obstack_init (&scratch_obstack); scratch_firstobj = obstack_alloc (&scratch_obstack, 1); } else obstack_free (&scratch_obstack, scratch_firstobj);#if 0#define buflen sizeof(buf)#define check if (bufp >= buf+buflen-1) goto too_long#define ccat(c) *bufp++=(c); check#define advance bufp+=strlen(bufp); check#define cat(s) strncpy(bufp, s, buf+buflen-bufp-1); advance#else#define check#define ccat(c) obstack_1grow (&scratch_obstack, (c));#define advance#define cat(s) obstack_grow (&scratch_obstack, (s), strlen (s))#endif cat (name); ccat ('<'); nparms = TREE_VEC_LENGTH (parms); my_friendly_assert (nparms == TREE_VEC_LENGTH (arglist), 268); for (i = 0; i < nparms; i++) { tree parm = TREE_VALUE (TREE_VEC_ELT (parms, i)); tree arg = TREE_VEC_ELT (arglist, i); if (i) ccat (','); if (TREE_CODE (parm) == TYPE_DECL) { cat (type_as_string (arg, 0)); continue; } else my_friendly_assert (TREE_CODE (parm) == PARM_DECL, 269); if (TREE_CODE (arg) == TREE_LIST) { /* New list cell was built because old chain link was in use. */ my_friendly_assert (TREE_PURPOSE (arg) == NULL_TREE, 270); arg = TREE_VALUE (arg); } /* No need to check arglist against parmlist here; we did that in coerce_template_parms, called from lookup_template_class. */ cat (expr_as_string (arg, 0)); } { char *bufp = obstack_next_free (&scratch_obstack); int offset = 0; while (bufp[offset - 1] == ' ') offset--; obstack_blank_fast (&scratch_obstack, offset); /* B<C<char> >, not B<C<char>> */ if (bufp[offset - 1] == '>') ccat (' '); } ccat ('>'); ccat ('\0'); return (char *) obstack_base (&scratch_obstack);#if 0 too_long:#endif fatal ("out of (preallocated) string space creating template instantiation name"); /* NOTREACHED */ return NULL;}/* Given an IDENTIFIER_NODE (type TEMPLATE_DECL) and a chain of parameters, find the desired type. D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments. Since ARGLIST is build on the decl_obstack, we must copy it here to keep it from being reclaimed when the decl storage is reclaimed. IN_DECL, if non-NULL, is the template declaration we are trying to instantiate. */treelookup_template_class (d1, arglist, in_decl) tree d1, arglist; tree in_decl;{ tree template, parmlist; char *mangled_name; tree id; my_friendly_assert (TREE_CODE (d1) == IDENTIFIER_NODE, 272); template = IDENTIFIER_GLOBAL_VALUE (d1); /* XXX */ if (! template) template = IDENTIFIER_CLASS_VALUE (d1); /* With something like `template <class T> class X class X { ... };' we could end up with D1 having nothing but an IDENTIFIER_LOCAL_VALUE. We don't want to do that, but we have to deal with the situation, so let's give them some syntax errors to chew on instead of a crash. */ if (! template) return error_mark_node; if (TREE_CODE (template) != TEMPLATE_DECL) { cp_error ("non-template type `%T' used as a template", d1); if (in_decl) cp_error_at ("for template declaration `%D'", in_decl); return error_mark_node; } parmlist = DECL_TEMPLATE_PARMS (template); arglist = coerce_template_parms (parmlist, arglist, template); if (arglist == error_mark_node) return error_mark_node; if (uses_template_parms (arglist)) { tree t = make_lang_type (UNINSTANTIATED_P_TYPE); tree d; id = make_anon_name (); d = build_decl (TYPE_DECL, id, t); TYPE_NAME (t) = d; TYPE_VALUES (t) = build_tree_list (template, arglist); pushdecl_top_level (d); } else { mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1), parmlist, arglist); id = get_identifier (mangled_name); } if (!IDENTIFIER_TEMPLATE (id)) { arglist = copy_to_permanent (arglist); IDENTIFIER_TEMPLATE (id) = perm_tree_cons (template, arglist, NULL_TREE); } return id;}voidpush_template_decls (parmlist, arglist, class_level) tree parmlist, arglist; int class_level;{ int i, nparms; /* Don't want to push values into global context. */ if (!class_level) { pushlevel (1); declare_pseudo_global_level (); } nparms = TREE_VEC_LENGTH (parmlist); for (i = 0; i < nparms; i++) { int requires_type, is_type; tree parm = TREE_VALUE (TREE_VEC_ELT (parmlist, i)); tree arg = TREE_VEC_ELT (arglist, i); tree decl = 0; requires_type = TREE_CODE (parm) == TYPE_DECL; is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't'; if (is_type) { /* add typename to namespace */ if (!requires_type) { error ("template use error: type provided where value needed"); continue; } decl = arg; my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 't', 273); decl = build_decl (TYPE_DECL, DECL_NAME (parm), decl); } else { /* add const decl to namespace */ tree val; tree parmtype; if (requires_type) { error ("template use error: value provided where type needed"); continue; } parmtype = tsubst (TREE_TYPE (parm), &TREE_VEC_ELT (arglist, 0), TREE_VEC_LENGTH (arglist), NULL_TREE); val = digest_init (parmtype, arg, (tree *) 0); if (val != error_mark_node) { decl = build_decl (CONST_DECL, DECL_NAME (parm), parmtype); DECL_INITIAL (decl) = val; TREE_READONLY (decl) = 1; } } if (decl != 0) { SET_DECL_ARTIFICIAL (decl); layout_decl (decl, 0); if (class_level) pushdecl_class_level (decl); else pushdecl (decl); } }}voidpop_template_decls (parmlist, arglist, class_level) tree parmlist, arglist; int class_level;{ if (!class_level) poplevel (0, 0, 0);}/* Should be defined in parse.h. */extern int yychar;intuses_template_parms (t) tree t;{ if (!t) return 0; switch (TREE_CODE (t)) { case INDIRECT_REF: case COMPONENT_REF: /* We assume that the object must be instantiated in order to build the COMPONENT_REF, so we test only whether the type of the COMPONENT_REF uses template parms. */ return uses_template_parms (TREE_TYPE (t)); case IDENTIFIER_NODE: if (!IDENTIFIER_TEMPLATE (t)) return 0; return uses_template_parms (TREE_VALUE (IDENTIFIER_TEMPLATE (t))); /* aggregates of tree nodes */ case TREE_VEC: { int i = TREE_VEC_LENGTH (t); while (i--) if (uses_template_parms (TREE_VEC_ELT (t, i))) return 1; return 0; } case TREE_LIST: if (uses_template_parms (TREE_PURPOSE (t)) || uses_template_parms (TREE_VALUE (t))) return 1; return uses_template_parms (TREE_CHAIN (t)); /* constructed type nodes */ case POINTER_TYPE: case REFERENCE_TYPE: return uses_template_parms (TREE_TYPE (t)); case RECORD_TYPE: if (TYPE_PTRMEMFUNC_FLAG (t)) return uses_template_parms (TYPE_PTRMEMFUNC_FN_TYPE (t)); case UNION_TYPE: if (!TYPE_NAME (t)) return 0; if (!TYPE_IDENTIFIER (t)) return 0; return uses_template_parms (TYPE_IDENTIFIER (t)); case FUNCTION_TYPE: if (uses_template_parms (TYPE_ARG_TYPES (t))) return 1; return uses_template_parms (TREE_TYPE (t)); case ARRAY_TYPE: if (uses_template_parms (TYPE_DOMAIN (t))) return 1; return uses_template_parms (TREE_TYPE (t)); case OFFSET_TYPE: if (uses_template_parms (TYPE_OFFSET_BASETYPE (t))) return 1; return uses_template_parms (TREE_TYPE (t)); case METHOD_TYPE: if (uses_template_parms (TYPE_METHOD_BASETYPE (t))) return 1; if (uses_template_parms (TYPE_ARG_TYPES (t))) return 1; return uses_template_parms (TREE_TYPE (t)); /* decl nodes */ case TYPE_DECL: return uses_template_parms (DECL_NAME (t)); case FUNCTION_DECL: if (uses_template_parms (TREE_TYPE (t))) return 1; /* fall through */ case VAR_DECL: case PARM_DECL: /* ??? What about FIELD_DECLs? */ /* The type of a decl can't use template parms if the name of the variable doesn't, because it's impossible to resolve them. So ignore the type field for now. */ if (DECL_CONTEXT (t) && uses_template_parms (DECL_CONTEXT (t))) return 1; if (uses_template_parms (TREE_TYPE (t))) { error ("template parms used where they can't be resolved"); } return 0; case CALL_EXPR: return uses_template_parms (TREE_TYPE (t)); case ADDR_EXPR: return uses_template_parms (TREE_OPERAND (t, 0)); /* template parm nodes */ case TEMPLATE_TYPE_PARM: case TEMPLATE_CONST_PARM: return 1; /* simple type nodes */ case INTEGER_TYPE: if (uses_template_parms (TYPE_MIN_VALUE (t))) return 1; return uses_template_parms (TYPE_MAX_VALUE (t)); case REAL_TYPE: case VOID_TYPE: case ENUMERAL_TYPE: case BOOLEAN_TYPE: return 0; /* constants */ case INTEGER_CST: case REAL_CST: case STRING_CST: return 0; case ERROR_MARK: /* Non-error_mark_node ERROR_MARKs are bad things. */ my_friendly_assert (t == error_mark_node, 274); /* NOTREACHED */ return 0; case UNINSTANTIATED_P_TYPE: return 1; case CONSTRUCTOR: if (TREE_TYPE (t) && TYPE_PTRMEMFUNC_P (TREE_TYPE (t))) return uses_template_parms (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (t))); /* else fall through */ default: switch (TREE_CODE_CLASS (TREE_CODE (t))) { case '1': case '2': case '3': case '<': { int i; for (i = tree_code_length[(int) TREE_CODE (t)]; --i >= 0;) if (uses_template_parms (TREE_OPERAND (t, i))) return 1; return 0; } default: break; } sorry ("testing %s for template parms", tree_code_name [(int) TREE_CODE (t)]); my_friendly_abort (82); /* NOTREACHED */ return 0; }}voidinstantiate_member_templates (classname) tree classname;{ tree t; tree id = classname; tree members = DECL_TEMPLATE_MEMBERS (TREE_PURPOSE (IDENTIFIER_TEMPLATE (id))); for (t = members; t; t = TREE_CHAIN (t)) { tree parmvec, type, classparms, tdecl, t2; int nparms, xxx = 0, i; my_friendly_assert (TREE_VALUE (t) != NULL_TREE, 275); my_friendly_assert (TREE_CODE (TREE_VALUE (t)) == TEMPLATE_DECL, 276); /* @@ Should verify that class parm list is a list of distinct template parameters, and covers all the template parameters. */ tdecl = TREE_VALUE (t); type = DECL_CONTEXT (DECL_TEMPLATE_RESULT (tdecl)); classparms = UPT_PARMS (type); nparms = TREE_VEC_LENGTH (classparms); parmvec = make_tree_vec (nparms); for (i = 0; i < nparms; i++) TREE_VEC_ELT (parmvec, i) = NULL_TREE; switch (unify (DECL_TEMPLATE_PARMS (tdecl), &TREE_VEC_ELT (parmvec, 0), nparms, type, IDENTIFIER_TYPE_VALUE (classname), &xxx)) { case 0: /* Success -- well, no inconsistency, at least. */ for (i = 0; i < nparms; i++) if (TREE_VEC_ELT (parmvec, i) == NULL_TREE) goto failure; t2 = instantiate_template (tdecl, &TREE_VEC_ELT (parmvec, 0)); type = IDENTIFIER_TYPE_VALUE (id); my_friendly_assert (type != 0, 277); break; case 1: /* Failure. */ failure: cp_error_at ("type unification error instantiating `%D'", tdecl); cp_error ("while instantiating members of `%T'", classname); continue /* loop of members */; default: /* Eek, a bug. */ my_friendly_abort (83); } }}static struct tinst_level *current_tinst_level = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -