📄 search.c
字号:
if (flag_memoize_lookups) { len = type_stack->len; while (len--) CLASSTYPE_MTABLE_ENTRY (tem[len*2]) = (char *)MEMOIZED_CHAIN (CLASSTYPE_MTABLE_ENTRY (tem[len*2])); } if (! use_old) type_stack = pop_type_level (type_stack); else type_stack = (struct type_level *)type_stack->base.prev;}/* Get a virtual binfo that is found inside BINFO's hierarchy that is the same type as the type given in PARENT. To be optimal, we want the first one that is found by going through the least number of virtual bases. */static treeget_vbase_1 (parent, binfo, depth) tree parent, binfo; unsigned int *depth;{ tree binfos; int i, n_baselinks; tree rval = NULL_TREE; if (BINFO_TYPE (binfo) == parent && TREE_VIA_VIRTUAL (binfo)) { *depth = 0; return binfo; } *depth = *depth - 1; binfos = BINFO_BASETYPES (binfo); n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; /* Process base types. */ for (i = 0; i < n_baselinks; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); tree nrval; if (*depth == 0) break; nrval = get_vbase_1 (parent, base_binfo, depth); if (nrval) rval = nrval; } *depth = *depth+1; return rval;}treeget_vbase (parent, binfo) tree parent; tree binfo;{ unsigned int d = (unsigned int)-1; return get_vbase_1 (parent, binfo, &d);}/* Convert EXPR to a virtual base class of type TYPE. We know that EXPR is a non-null POINTER_TYPE to RECORD_TYPE. We also know that the type of what expr points to has a virtual base of type TYPE. */static treeconvert_pointer_to_vbase (type, expr) tree type; tree expr;{ tree vb = get_vbase (type, TYPE_BINFO (TREE_TYPE (TREE_TYPE (expr)))); return convert_pointer_to_real (vb, expr);}/* Check whether the type given in BINFO is derived from PARENT. If it isn't, return 0. If it is, but the derivation is MI-ambiguous AND protect != 0, emit an error message and return error_mark_node. Otherwise, if TYPE is derived from PARENT, return the actual base information, unless a one of the protection violations below occurs, in which case emit an error message and return error_mark_node. If PROTECT is 1, then check if access to a public field of PARENT would be private. Also check for ambiguity. */treeget_binfo (parent, binfo, protect) register tree parent, binfo; int protect;{ tree type; int dist; tree rval = NULL_TREE; if (TREE_CODE (parent) == TREE_VEC) parent = BINFO_TYPE (parent); else if (! IS_AGGR_TYPE_CODE (TREE_CODE (parent))) my_friendly_abort (89); if (TREE_CODE (binfo) == TREE_VEC) type = BINFO_TYPE (binfo); else if (IS_AGGR_TYPE_CODE (TREE_CODE (binfo))) type = binfo; else my_friendly_abort (90); dist = get_base_distance (parent, binfo, protect, &rval); if (dist == -3) { cp_error ("fields of `%T' are inaccessible in `%T' due to private inheritance", parent, type); return error_mark_node; } else if (dist == -2 && protect) { cp_error ("type `%T' is ambiguous base class for type `%T'", parent, type); return error_mark_node; } return rval;}/* This is the newer depth first get_base_distance routine. */static intget_base_distance_recursive (binfo, depth, is_private, rval, rval_private_ptr, new_binfo_ptr, parent, path_ptr, protect, via_virtual_ptr, via_virtual, current_scope_in_chain) tree binfo; int depth, is_private, rval; int *rval_private_ptr; tree *new_binfo_ptr, parent, *path_ptr; int protect, *via_virtual_ptr, via_virtual; int current_scope_in_chain;{ tree binfos; int i, n_baselinks; if (protect && !current_scope_in_chain && is_friend (BINFO_TYPE (binfo), current_scope ())) current_scope_in_chain = 1; if (BINFO_TYPE (binfo) == parent || binfo == parent) { if (rval == -1) { rval = depth; *rval_private_ptr = is_private; *new_binfo_ptr = binfo; *via_virtual_ptr = via_virtual; } else { int same_object = (tree_int_cst_equal (BINFO_OFFSET (*new_binfo_ptr), BINFO_OFFSET (binfo)) && *via_virtual_ptr && via_virtual); if (*via_virtual_ptr && via_virtual==0) { *rval_private_ptr = is_private; *new_binfo_ptr = binfo; *via_virtual_ptr = via_virtual; } else if (same_object) { if (*rval_private_ptr && ! is_private) { *rval_private_ptr = is_private; *new_binfo_ptr = binfo; *via_virtual_ptr = via_virtual; } return rval; } rval = -2; } return rval; } binfos = BINFO_BASETYPES (binfo); n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; depth += 1; /* Process base types. */ for (i = 0; i < n_baselinks; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); /* Find any specific instance of a virtual base, when searching with a binfo... */ if (BINFO_MARKED (base_binfo) == 0 || TREE_CODE (parent) == TREE_VEC) { int via_private = (protect && (is_private || (!TREE_VIA_PUBLIC (base_binfo) && !(TREE_VIA_PROTECTED (base_binfo) && current_scope_in_chain) && !is_friend (BINFO_TYPE (binfo), current_scope ())))); int this_virtual = via_virtual || TREE_VIA_VIRTUAL (base_binfo); int was; /* When searching for a non-virtual, we cannot mark virtually found binfos. */ if (! this_virtual) SET_BINFO_MARKED (base_binfo);#define WATCH_VALUES(rval, via_private) (rval == -1 ? 3 : via_private) was = WATCH_VALUES (rval, *via_virtual_ptr); rval = get_base_distance_recursive (base_binfo, depth, via_private, rval, rval_private_ptr, new_binfo_ptr, parent, path_ptr, protect, via_virtual_ptr, this_virtual, current_scope_in_chain); /* watch for updates; only update if path is good. */ if (path_ptr && WATCH_VALUES (rval, *via_virtual_ptr) != was) BINFO_INHERITANCE_CHAIN (base_binfo) = binfo; if (rval == -2 && *via_virtual_ptr == 0) return rval;#undef WATCH_VALUES } } return rval;}/* Return the number of levels between type PARENT and the type given in BINFO, following the leftmost path to PARENT not found along a virtual path, if there are no real PARENTs (all come from virtual base classes), then follow the leftmost path to PARENT. Return -1 if TYPE is not derived from PARENT. Return -2 if PARENT is an ambiguous base class of TYPE, and PROTECT is non-negative. Return -3 if PARENT is private to TYPE, and PROTECT is non-zero. If PATH_PTR is non-NULL, then also build the list of types from PARENT to TYPE, with TREE_VIA_VIRTUAL and TREE_VIA_PUBLIC set. PARENT can also be a binfo, in which case that exact parent is found and no other. convert_pointer_to_real uses this functionality. If BINFO is a binfo, its BINFO_INHERITANCE_CHAIN will be left alone. */intget_base_distance (parent, binfo, protect, path_ptr) register tree parent, binfo; int protect; tree *path_ptr;{ int rval; int rval_private = 0; tree type; tree new_binfo = NULL_TREE; int via_virtual; int watch_access = protect; /* Should we be completing types here? */ if (TREE_CODE (parent) != TREE_VEC) parent = complete_type (TYPE_MAIN_VARIANT (parent)); else complete_type (TREE_TYPE (parent)); if (TREE_CODE (binfo) == TREE_VEC) type = BINFO_TYPE (binfo); else if (IS_AGGR_TYPE_CODE (TREE_CODE (binfo))) { type = complete_type (binfo); binfo = TYPE_BINFO (type); if (path_ptr) BINFO_INHERITANCE_CHAIN (binfo) = NULL_TREE; } else my_friendly_abort (92); if (parent == type || parent == binfo) { /* If the distance is 0, then we don't really need a path pointer, but we shouldn't let garbage go back. */ if (path_ptr) *path_ptr = binfo; return 0; } if (path_ptr) watch_access = 1; rval = get_base_distance_recursive (binfo, 0, 0, -1, &rval_private, &new_binfo, parent, path_ptr, watch_access, &via_virtual, 0, 0); dfs_walk (binfo, dfs_unmark, markedp); /* Access restrictions don't count if we found an ambiguous basetype. */ if (rval == -2 && protect >= 0) rval_private = 0; if (rval && protect && rval_private) return -3; /* find real virtual base classes. */ if (rval == -1 && TREE_CODE (parent) == TREE_VEC && parent == binfo_member (BINFO_TYPE (parent), CLASSTYPE_VBASECLASSES (type))) { BINFO_INHERITANCE_CHAIN (parent) = binfo; new_binfo = parent; rval = 1; } if (path_ptr) *path_ptr = new_binfo; return rval;}/* Search for a member with name NAME in a multiple inheritance lattice specified by TYPE. If it does not exist, return NULL_TREE. If the member is ambiguously referenced, return `error_mark_node'. Otherwise, return the FIELD_DECL. *//* Do a 1-level search for NAME as a member of TYPE. The caller must figure out whether it can access this field. (Since it is only one level, this is reasonable.) */static treelookup_field_1 (type, name) tree type, name;{ register tree field = TYPE_FIELDS (type);#ifdef GATHER_STATISTICS n_calls_lookup_field_1++;#endif /* GATHER_STATISTICS */ while (field) {#ifdef GATHER_STATISTICS n_fields_searched++;#endif /* GATHER_STATISTICS */ if (DECL_NAME (field) == NULL_TREE && TREE_CODE (TREE_TYPE (field)) == UNION_TYPE) { tree temp = lookup_field_1 (TREE_TYPE (field), name); if (temp) return temp; } if (DECL_NAME (field) == name) { if ((TREE_CODE(field) == VAR_DECL || TREE_CODE(field) == CONST_DECL) && DECL_ASSEMBLER_NAME (field) != NULL) GNU_xref_ref(current_function_decl, IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (field))); return field; } field = TREE_CHAIN (field); } /* Not found. */ if (name == _vptr_name) { /* Give the user what s/he thinks s/he wants. */ if (TYPE_VIRTUAL_P (type)) return CLASSTYPE_VFIELD (type); } return NULL_TREE;}/* There are a number of cases we need to be aware of here: current_class_type current_function_decl global NULL NULL fn-local NULL SET class-local SET NULL class->fn SET SET fn->class SET SET Those last two make life interesting. If we're in a function which is itself inside a class, we need decls to go into the fn's decls (our second case below). But if we're in a class and the class itself is inside a function, we need decls to go into the decls for the class. To achieve this last goal, we must see if, when both current_class_ptr and current_function_decl are set, the class was declared inside that function. If so, we know to put the decls into the class's scope. */treecurrent_scope (){ if (current_function_decl == NULL_TREE) return current_class_type; if (current_class_type == NULL_TREE) return current_function_decl; if (DECL_CLASS_CONTEXT (current_function_decl) == current_class_type) return current_function_decl; return current_class_type;}/* Compute the access of FIELD. This is done by computing the access available to each type in BASETYPES (which comes as a list of [via_public/basetype] in reverse order, namely base class before derived class). The first one which defines a access defines the access for the field. Otherwise, the access of the field is that which occurs normally. Uses global variables CURRENT_CLASS_TYPE and CURRENT_FUNCTION_DECL to use friend relationships if necessary. This will be static when lookup_fnfield comes into this file. access_public_node means that the field can be accessed by the current lexical scope. access_protected_node means that the field cannot be accessed by the current lexical scope because it is protected. access_private_node means that the field cannot be accessed by the current lexical scope because it is private. */#if 0#define PUBLIC_RETURN return (DECL_PUBLIC (field) = 1), access_public_node#define PROTECTED_RETURN return (DECL_PROTECTED (field) = 1), access_protected_node#define PRIVATE_RETURN return (DECL_PRIVATE (field) = 1), access_private_node#else#define PUBLIC_RETURN return access_public_node#define PROTECTED_RETURN return access_protected_node#define PRIVATE_RETURN return access_private_node#endif#if 0/* Disabled with DECL_PUBLIC &c. */static tree previous_scope = NULL_TREE;#endiftreecompute_access (basetype_path, field) tree basetype_path, field;{ tree access; tree types; tree context;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -