📄 cp-tree.c
字号:
TREE_VIA_VIRTUAL (t) = via_virtual; hashcode = list_hash (t); t = list_hash_canon (hashcode, t); current_obstack = ambient_obstack; return t;}/* Constructor for hashed lists. */treehash_tree_chain (value, chain) tree value, chain;{ struct obstack *ambient_obstack = current_obstack; tree t; int hashcode; current_obstack = &class_obstack; t = tree_cons (NULL_TREE, value, chain); hashcode = list_hash (t); t = list_hash_canon (hashcode, t); current_obstack = ambient_obstack; return t;}/* 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));}treeget_decl_list (value) tree value;{ tree list = NULL_TREE; if (TREE_CODE (value) == IDENTIFIER_NODE) { list = IDENTIFIER_AS_LIST (value); if (list != NULL_TREE && (TREE_CODE (list) != TREE_LIST || TREE_VALUE (list) != value)) list = NULL_TREE; else if (IDENTIFIER_HAS_TYPE_VALUE (value) && TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE) { tree type = IDENTIFIER_TYPE_VALUE (value); if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE) CLASSTYPE_ID_AS_LIST (type) = perm_tree_cons (NULL_TREE, value, NULL_TREE); list = CLASSTYPE_ID_AS_LIST (type); } } else if (TREE_CODE (value) == RECORD_TYPE && TYPE_LANG_SPECIFIC (value)) list = CLASSTYPE_AS_LIST (value); if (list != NULL_TREE) { my_friendly_assert (TREE_CHAIN (list) == NULL_TREE, 301); return list; } return build_decl_list (NULL_TREE, value);}/* Look in the type hash table for a type isomorphic to `build_tree_list (NULL_TREE, VALUE)'. If one is found, return it. Otherwise return 0. */treelist_hash_lookup_or_cons (value) tree value;{ register int hashcode = TYPE_HASH (value); register struct list_hash *h; struct obstack *ambient_obstack; tree list = NULL_TREE; if (TREE_CODE (value) == IDENTIFIER_NODE) { list = IDENTIFIER_AS_LIST (value); if (list != NULL_TREE && (TREE_CODE (list) != TREE_LIST || TREE_VALUE (list) != value)) list = NULL_TREE; else if (IDENTIFIER_HAS_TYPE_VALUE (value) && TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE) { /* If the type name and constructor name are different, don't write constructor name into type. */ extern tree constructor_name (); if (IDENTIFIER_TYPEDECL_VALUE (value) && IDENTIFIER_TYPEDECL_VALUE (value) != constructor_name (value)) list = tree_cons (NULL_TREE, value, NULL_TREE); else { tree type = IDENTIFIER_TYPE_VALUE (value); if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE) CLASSTYPE_ID_AS_LIST (type) = perm_tree_cons (NULL_TREE, value, NULL_TREE); list = CLASSTYPE_ID_AS_LIST (type); } } } else if (TREE_CODE (value) == TYPE_DECL && TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE && TYPE_LANG_SPECIFIC (TREE_TYPE (value))) list = CLASSTYPE_ID_AS_LIST (TREE_TYPE (value)); else if (TREE_CODE (value) == RECORD_TYPE && TYPE_LANG_SPECIFIC (value)) list = CLASSTYPE_AS_LIST (value); if (list != NULL_TREE) { my_friendly_assert (TREE_CHAIN (list) == NULL_TREE, 302); return list; } if (debug_no_list_hash) return hash_tree_chain (value, NULL_TREE); for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next) if (h->hashcode == hashcode && TREE_VIA_VIRTUAL (h->list) == 0 && TREE_VIA_PUBLIC (h->list) == 0 && TREE_VIA_PROTECTED (h->list) == 0 && TREE_PURPOSE (h->list) == 0 && TREE_VALUE (h->list) == value) { my_friendly_assert (TREE_TYPE (h->list) == 0, 303); my_friendly_assert (TREE_CHAIN (h->list) == 0, 304); return h->list; } ambient_obstack = current_obstack; current_obstack = &class_obstack; list = build_tree_list (NULL_TREE, value); list_hash_add (hashcode, list); current_obstack = ambient_obstack; return list;}/* Build an association between TYPE and some parameters: OFFSET is the offset added to `this' to convert it to a pointer of type `TYPE *' VTABLE is the virtual function table with which to initialize sub-objects of type TYPE. VIRTUALS are the virtual functions sitting in VTABLE. CHAIN are more associations we must retain. */treemake_binfo (offset, type, vtable, virtuals, chain) tree offset, type; tree vtable, virtuals; tree chain;{ tree binfo = make_tree_vec (6); tree old_binfo = TYPE_BINFO (type); tree last; TREE_CHAIN (binfo) = chain; if (chain) TREE_USED (binfo) = TREE_USED (chain); TREE_TYPE (binfo) = TYPE_MAIN_VARIANT (type); BINFO_OFFSET (binfo) = offset; BINFO_VTABLE (binfo) = vtable; BINFO_VIRTUALS (binfo) = virtuals; BINFO_VPTR_FIELD (binfo) = NULL_TREE; last = binfo; if (old_binfo != NULL_TREE && BINFO_BASETYPES (old_binfo) != NULL_TREE) { int i, n_baseclasses = CLASSTYPE_N_BASECLASSES (type); tree binfos = TYPE_BINFO_BASETYPES (type); BINFO_BASETYPES (binfo) = make_tree_vec (n_baseclasses); for (i = 0; i < n_baseclasses; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); tree old_base_binfo = old_binfo ? BINFO_BASETYPE (old_binfo, i) : 0; BINFO_BASETYPE (binfo, i) = base_binfo; if (old_binfo) { TREE_VIA_PUBLIC (base_binfo) = TREE_VIA_PUBLIC (old_base_binfo); TREE_VIA_PROTECTED (base_binfo) = TREE_VIA_PROTECTED (old_base_binfo); TREE_VIA_VIRTUAL (base_binfo) = TREE_VIA_VIRTUAL (old_base_binfo); } } } return binfo;}treecopy_binfo (list) tree list;{ tree binfo = copy_list (list); tree rval = binfo; while (binfo) { TREE_USED (binfo) = 0; if (BINFO_BASETYPES (binfo)) BINFO_BASETYPES (binfo) = copy_node (BINFO_BASETYPES (binfo)); binfo = TREE_CHAIN (binfo); } return rval;}/* Return the binfo value for ELEM in TYPE. Due to structure sharing, we may find ELEM only in the association list belonging to a basetype of TYPE. COPYING is 0 if we just want an binfo value without needing to modify it. COPYING is 1 if we want the binfo value in order to modify it. In this case, if we don't find ELEM immediately in the binfo values of TYPE, we return a copy. COPYING is -1 if we are called recursively and need a copy. In this case we return a copy of ELEM at the point we find it. */treebinfo_value (elem, type, copying) tree elem; tree type; int copying;{ tree binfo = TYPE_BINFO (type); tree last; tree rval = NULL_TREE; /* Dispose quickly of degenerate case. */ if (elem == type) return copying < 0 ? copy_binfo (binfo) : binfo; /* Look for ELEM in two passes. First pass checks the entire binfo list. Second pass recursively searches the binfo lists of binfos. */ while (binfo) { if (elem == BINFO_TYPE (binfo)) /* If we find it on the main spine, then there can be no ambiguity. */ return copying < 0 ? copy_binfo (binfo) : binfo; last = binfo; binfo = TREE_CHAIN (binfo); } for (binfo = TYPE_BINFO (type); binfo != TREE_CHAIN (last); binfo = TREE_CHAIN (binfo)) { /* ??? Should this condition instead test BINFO_TYPE (binfo) != TYPE_MAIN_VARIANT (type) ??? */ if (BINFO_TYPE (binfo) != TYPE_MAIN_VARIANT (type)) { tree nval = binfo_value (elem, BINFO_TYPE (binfo), copying ? -1 : 0); if (nval) { if (copying && rval == NULL_TREE) chainon (TYPE_BINFO (type), nval); if (rval && BINFO_TYPE (rval) != BINFO_TYPE (nval)) /* If we find it underneath, we must make sure that there are no two ways to do it. */ compiler_error ("base class `%s' ambiguous in binfo_value", TYPE_NAME_STRING (elem)); else rval = nval; } } } return rval;}treereverse_path (path) tree path;{ register tree prev = 0, tmp, next; for (tmp = path; tmp; tmp = next) { next = BINFO_INHERITANCE_CHAIN (tmp); BINFO_INHERITANCE_CHAIN (tmp) = prev; prev = tmp; } return prev;}treevirtual_member (elem, list) tree elem; tree list;{ tree t; tree rval, nval; for (t = list; t; t = TREE_CHAIN (t)) if (elem == BINFO_TYPE (t)) return t; rval = 0; for (t = list; t; t = TREE_CHAIN (t)) { tree binfos = BINFO_BASETYPES (t); int i; if (binfos != NULL_TREE) for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--) { nval = binfo_value (elem, BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0); if (nval) { if (rval && BINFO_OFFSET (nval) != BINFO_OFFSET (rval)) my_friendly_abort (104); rval = nval; } } } return rval;}/* Return the offset (as an INTEGER_CST) for ELEM in LIST. INITIAL_OFFSET is the value to add to the offset that ELEM's binfo entry in LIST provides. Returns NULL if ELEM does not have an binfo value in LIST. */treevirtual_offset (elem, list, initial_offset) tree elem; tree list; tree initial_offset;{ tree vb, offset; tree rval, nval; for (vb = list; vb; vb = TREE_CHAIN (vb)) if (elem == BINFO_TYPE (vb)) return size_binop (PLUS_EXPR, initial_offset, BINFO_OFFSET (vb)); rval = 0; for (vb = list; vb; vb = TREE_CHAIN (vb)) { tree binfos = BINFO_BASETYPES (vb); int i; if (binfos == NULL_TREE) continue; for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--) { nval = binfo_value (elem, BINFO_TYPE (TREE_VEC_ELT (binfos, i)), 0); if (nval) { if (rval && BINFO_OFFSET (nval) != BINFO_OFFSET (rval)) my_friendly_abort (105); offset = BINFO_OFFSET (vb); rval = nval; } } } if (rval == NULL_TREE) return rval; return size_binop (PLUS_EXPR, offset, BINFO_OFFSET (rval));}voiddebug_binfo (elem) tree elem;{ int i; tree virtuals; fprintf (stderr, "type \"%s\"; offset = %d\n", TYPE_NAME_STRING (BINFO_TYPE (elem)), 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); if (virtuals != 0) { virtuals = TREE_CHAIN (virtuals); if (flag_dossier) virtuals = TREE_CHAIN (virtuals); } i = 1; while (virtuals) { tree fndecl = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)), 0); fprintf (stderr, "%s [%d =? %d]\n", IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)), i, TREE_INT_CST_LOW (DECL_VINDEX (fndecl))); virtuals = TREE_CHAIN (virtuals); i += 1; }}/* Return the length of a chain of nodes chained through DECL_CHAIN. We expect a null pointer to mark the end of the chain. This is the Lisp primitive `length'. */intdecl_list_length (t) tree t;{ register tree tail; register int len = 0; my_friendly_assert (TREE_CODE (t) == FUNCTION_DECL, 300); for (tail = t; tail; tail = DECL_CHAIN (tail)) len++; return len;}treefnaddr_from_vtable_entry (entry) tree entry;{ return TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry))));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -