📄 tree.c
字号:
int hashcode; tree list;{ register struct list_hash *h; h = (struct list_hash *) obstack_alloc (&class_obstack, sizeof (struct list_hash)); h->hashcode = hashcode; h->list = list; h->next = list_hash_table[hashcode % TYPE_HASH_SIZE]; list_hash_table[hashcode % TYPE_HASH_SIZE] = h;}/* Given list components PURPOSE, VALUE, AND CHAIN, return the canonical object for an identical list if one already exists. Otherwise, build a new one, and record it as the canonical object. *//* Set to 1 to debug without canonicalization. Never set by program. */static int debug_no_list_hash = 0;treehash_tree_cons (purpose, value, chain) tree purpose, value, chain;{ struct obstack *ambient_obstack = current_obstack; tree t; int hashcode = 0; if (! debug_no_list_hash) { hashcode = list_hash (purpose, value, chain); t = list_hash_lookup (hashcode, purpose, value, chain); if (t) return t; } current_obstack = &class_obstack; t = tree_cons (purpose, value, chain); /* If this is a new list, record it for later reuse. */ if (! debug_no_list_hash) list_hash_add (hashcode, t); current_obstack = ambient_obstack; return t;}/* Constructor for hashed lists. */treehash_tree_chain (value, chain) tree value, chain;{ return hash_tree_cons (NULL_TREE, value, chain);}/* Similar, but used for concatenating two lists. */treehash_chainon (list1, list2) tree list1, list2;{ if (list2 == 0) return list1; if (list1 == 0) return list2; if (TREE_CHAIN (list1) == NULL_TREE) return hash_tree_chain (TREE_VALUE (list1), list2); return hash_tree_chain (TREE_VALUE (list1), hash_chainon (TREE_CHAIN (list1), list2));}/* Build an association between TYPE and some parameters: OFFSET is the offset added to `this' to convert it to a pointer of type `TYPE *' BINFO is the base binfo to use, if we are deriving from one. This is necessary, as we want specialized parent binfos from base classes, so that the VTABLE_NAMEs of bases are for the most derived type, instead of the simple type. VTABLE is the virtual function table with which to initialize sub-objects of type TYPE. VIRTUALS are the virtual functions sitting in VTABLE. */treemake_binfo (offset, binfo, vtable, virtuals) tree offset, binfo; tree vtable, virtuals;{ tree new_binfo = make_tree_vec (7); tree type; if (TREE_CODE (binfo) == TREE_VEC) type = BINFO_TYPE (binfo); else { type = binfo; binfo = CLASS_TYPE_P (type) ? TYPE_BINFO (binfo) : NULL_TREE; } TREE_TYPE (new_binfo) = TYPE_MAIN_VARIANT (type); BINFO_OFFSET (new_binfo) = offset; BINFO_VTABLE (new_binfo) = vtable; BINFO_VIRTUALS (new_binfo) = virtuals; BINFO_VPTR_FIELD (new_binfo) = NULL_TREE; if (binfo && BINFO_BASETYPES (binfo) != NULL_TREE) BINFO_BASETYPES (new_binfo) = copy_node (BINFO_BASETYPES (binfo)); return new_binfo;}/* Return the binfo value for ELEM in TYPE. */treebinfo_value (elem, type) tree elem; tree type;{ if (get_base_distance (elem, type, 0, (tree *)0) == -2) compiler_error ("base class `%s' ambiguous in binfo_value", TYPE_NAME_STRING (elem)); if (elem == type) return TYPE_BINFO (type); if (TREE_CODE (elem) == RECORD_TYPE && TYPE_BINFO (elem) == type) return type; return get_binfo (elem, type, 0);}/* Return a reversed copy of the BINFO-chain given by PATH. (If the BINFO_INHERITANCE_CHAIN points from base classes to derived classes, it will instead point from derived classes to base classes.) Returns the first node in the reversed chain. */treereverse_path (path) tree path;{ register tree prev = NULL_TREE, cur; push_expression_obstack (); for (cur = path; cur; cur = BINFO_INHERITANCE_CHAIN (cur)) { tree r = copy_node (cur); BINFO_INHERITANCE_CHAIN (r) = prev; prev = r; } pop_obstacks (); return prev;}voiddebug_binfo (elem) tree elem;{ unsigned HOST_WIDE_INT n; tree virtuals; fprintf (stderr, "type \"%s\"; offset = %ld\n", TYPE_NAME_STRING (BINFO_TYPE (elem)), (long) TREE_INT_CST_LOW (BINFO_OFFSET (elem))); fprintf (stderr, "vtable type:\n"); debug_tree (BINFO_TYPE (elem)); if (BINFO_VTABLE (elem)) fprintf (stderr, "vtable decl \"%s\"\n", IDENTIFIER_POINTER (DECL_NAME (BINFO_VTABLE (elem)))); else fprintf (stderr, "no vtable decl yet\n"); fprintf (stderr, "virtuals:\n"); virtuals = BINFO_VIRTUALS (elem); n = skip_rtti_stuff (&virtuals, BINFO_TYPE (elem)); while (virtuals) { tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0); fprintf (stderr, "%s [%ld =? %ld]\n", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)), (long) n, (long) TREE_INT_CST_LOW (DECL_VINDEX (fndecl))); ++n; virtuals = TREE_CHAIN (virtuals); }}/* Initialize an CPLUS_BINDING node that does not live on an obstack. */treebinding_init (node) struct tree_binding* node;{ static struct tree_binding* source; if (!source) { extern struct obstack permanent_obstack; push_obstacks (&permanent_obstack, &permanent_obstack); source = (struct tree_binding*)make_node (CPLUS_BINDING); pop_obstacks (); } *node = *source; TREE_PERMANENT ((tree)node) = 0; return (tree)node;}intcount_functions (t) tree t;{ int i; if (TREE_CODE (t) == FUNCTION_DECL) return 1; else if (TREE_CODE (t) == OVERLOAD) { for (i=0; t; t = OVL_CHAIN (t)) i++; return i; } my_friendly_abort (359); return 0;}intis_overloaded_fn (x) tree x;{ /* A baselink is also considered an overloaded function. */ if (TREE_CODE (x) == OFFSET_REF) x = TREE_OPERAND (x, 1); if (BASELINK_P (x)) x = TREE_VALUE (x); return (TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == TEMPLATE_ID_EXPR || DECL_FUNCTION_TEMPLATE_P (x) || TREE_CODE (x) == OVERLOAD);}intreally_overloaded_fn (x) tree x;{ /* A baselink is also considered an overloaded function. */ if (TREE_CODE (x) == OFFSET_REF) x = TREE_OPERAND (x, 1); if (BASELINK_P (x)) x = TREE_VALUE (x); return (TREE_CODE (x) == OVERLOAD && (TREE_CHAIN (x) != NULL_TREE || DECL_FUNCTION_TEMPLATE_P (OVL_FUNCTION (x))));}treeget_first_fn (from) tree from;{ my_friendly_assert (is_overloaded_fn (from), 9); /* A baselink is also considered an overloaded function. */ if (BASELINK_P (from)) from = TREE_VALUE (from); return OVL_CURRENT (from);}/* Returns nonzero if T is a ->* or .* expression that refers to a member function. */intbound_pmf_p (t) tree t;{ return (TREE_CODE (t) == OFFSET_REF && TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (t, 1))));}/* Return a new OVL node, concatenating it with the old one. */treeovl_cons (decl, chain) tree decl; tree chain;{ tree result = make_node (OVERLOAD); TREE_TYPE (result) = unknown_type_node; OVL_FUNCTION (result) = decl; TREE_CHAIN (result) = chain; return result;}/* Same as ovl_cons, but on the scratch_obstack. */treescratch_ovl_cons (value, chain) tree value, chain;{ register tree node; register struct obstack *ambient_obstack = current_obstack; extern struct obstack *expression_obstack; current_obstack = expression_obstack; node = ovl_cons (value, chain); current_obstack = ambient_obstack; return node;}/* Build a new overloaded function. If this is the first one, just return it; otherwise, ovl_cons the _DECLs */treebuild_overload (decl, chain) tree decl; tree chain;{ if (! chain && TREE_CODE (decl) != TEMPLATE_DECL) return decl; if (chain && TREE_CODE (chain) != OVERLOAD) chain = ovl_cons (chain, NULL_TREE); return ovl_cons (decl, chain);}/* Returns true iff functions are equivalent. Equivalent functions are not identical only if one is a function-local extern function. This assumes that function-locals don't have TREE_PERMANENT. */static intequal_functions (fn1, fn2) tree fn1; tree fn2;{ if (!TREE_PERMANENT (fn1) || !TREE_PERMANENT (fn2)) return decls_match (fn1, fn2); return fn1 == fn2;}/* True if fn is in ovl. */intovl_member (fn, ovl) tree fn; tree ovl;{ if (ovl == NULL_TREE) return 0; if (TREE_CODE (ovl) != OVERLOAD) return equal_functions (ovl, fn); for (; ovl; ovl = OVL_CHAIN (ovl)) if (equal_functions (OVL_FUNCTION (ovl), fn)) return 1; return 0;}intis_aggr_type_2 (t1, t2) tree t1, t2;{ if (TREE_CODE (t1) != TREE_CODE (t2)) return 0; return IS_AGGR_TYPE (t1) && IS_AGGR_TYPE (t2);}#define PRINT_RING_SIZE 4char *lang_printable_name (decl, v) tree decl; int v;{ static tree decl_ring[PRINT_RING_SIZE]; static char *print_ring[PRINT_RING_SIZE]; static int ring_counter; int i; /* Only cache functions. */ if (v < 2 || TREE_CODE (decl) != FUNCTION_DECL || DECL_LANG_SPECIFIC (decl) == 0) return lang_decl_name (decl, v); /* See if this print name is lying around. */ for (i = 0; i < PRINT_RING_SIZE; i++) if (decl_ring[i] == decl) /* yes, so return it. */ return print_ring[i]; if (++ring_counter == PRINT_RING_SIZE) ring_counter = 0; if (current_function_decl != NULL_TREE) { if (decl_ring[ring_counter] == current_function_decl) ring_counter += 1; if (ring_counter == PRINT_RING_SIZE) ring_counter = 0; if (decl_ring[ring_counter] == current_function_decl) my_friendly_abort (106); } if (print_ring[ring_counter]) free (print_ring[ring_counter]); print_ring[ring_counter] = xstrdup (lang_decl_name (decl, v)); decl_ring[ring_counter] = decl; return print_ring[ring_counter];}/* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions listed in RAISES. */treebuild_exception_variant (type, raises) tree type; tree raises;{ tree v = TYPE_MAIN_VARIANT (type); int type_quals = TYPE_QUALS (type); for (; v; v = TYPE_NEXT_VARIANT (v)) { tree t; tree u; if (TYPE_QUALS (v) != type_quals) continue; for (t = TYPE_RAISES_EXCEPTIONS (v), u = raises; t != NULL_TREE && u != NULL_TREE; t = TREE_CHAIN (t), u = TREE_CHAIN (u)) if (((TREE_VALUE (t) != NULL_TREE) != (TREE_VALUE (u) != NULL_TREE)) || !same_type_p (TREE_VALUE (t), TREE_VALUE (u))) break; if (!t && !u) /* There's a memory leak here; RAISES is not freed. */ return v; } /* Need to build a new variant. */ v = build_type_copy (type); if (raises && ! TREE_PERMANENT (raises)) raises = copy_to_permanent (raises); TYPE_RAISES_EXCEPTIONS (v) = raises; return v;}/* Given a TEMPLATE_TEMPLATE_PARM node T, create a new one together with its lang_specific field and its corresponding TEMPLATE_DECL node */treecopy_template_template_parm (t) tree t;{ tree template = TYPE_NAME (t); tree t2; /* Make sure these end up on the permanent_obstack. */ push_obstacks_nochange (); end_temporary_allocation (); t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM); template = copy_node (template); copy_lang_decl (template); pop_obstacks (); TREE_TYPE (template) = t2; TYPE_NAME (t2) = template; TYPE_STUB_DECL (t2) = template; /* No need to copy these */ TYPE_FIELDS (t2) = TYPE_FIELDS (t); TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2) = TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t); return t2;}/* Walk through the tree structure T, applying func. If func ever returns non-null, return that value. */treesearch_tree (t, func) tree t; tree (*func) PROTO((tree));{#define TRY(ARG) if (tmp=search_tree (ARG, func), tmp != NULL_TREE) return tmp tree tmp; if (t == NULL_TREE) return t; if (tmp = func (t), tmp != NULL_TREE) return tmp; switch (TREE_CODE (t)) { case ERROR_MARK: break; case IDENTIFIER_NODE:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -