📄 search.c
字号:
{ tree binfos = BINFO_BASETYPES (TYPE_BINFO (type)); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; for (i = 0; i < n_baselinks; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); if (parent == BINFO_TYPE (base_binfo)) return 1; } } return 0;}#endif/* 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, basetype_path, rval, rval_private_ptr, new_binfo_ptr, parent, path_ptr, protect, via_virtual_ptr, via_virtual) tree binfo, basetype_path, *new_binfo_ptr, parent, *path_ptr; int *rval_private_ptr, depth, is_private, rval, protect, *via_virtual_ptr, via_virtual;{ tree binfos; int i, n_baselinks; 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) && !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, binfo, rval, rval_private_ptr, new_binfo_ptr, parent, path_ptr, protect, via_virtual_ptr, this_virtual); /* 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; if (TREE_CODE (parent) != TREE_VEC) parent = TYPE_MAIN_VARIANT (parent); if (TREE_CODE (binfo) == TREE_VEC) type = BINFO_TYPE (binfo); else if (IS_AGGR_TYPE_CODE (TREE_CODE (binfo))) { 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, NULL_TREE, -1, &rval_private, &new_binfo, parent, path_ptr, watch_access, &via_virtual, 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 while (field) {#ifdef GATHER_STATISTICS n_fields_searched++;#endif 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_decl 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 means that the field can be accessed by the current lexical scope. access_protected means that the field cannot be accessed by the current lexical scope because it is protected. access_private 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#define PROTECTED_RETURN return (DECL_PROTECTED (field) = 1), access_protected#define PRIVATE_RETURN return (DECL_PRIVATE (field) = 1), access_private#else#define PUBLIC_RETURN return access_public#define PROTECTED_RETURN return access_protected#define PRIVATE_RETURN return access_private#endif#if 0/* Disabled with DECL_PUBLIC &c. */static tree previous_scope = NULL_TREE;#endifenum access_typecompute_access (basetype_path, field) tree basetype_path, field;{ enum access_type access; tree types; tree context; int protected_ok, via_protected; extern int flag_access_control;#if 1 /* Replaces static decl above. */ tree previous_scope;#endif int static_mem = ((TREE_CODE (field) == FUNCTION_DECL && DECL_STATIC_FUNCTION_P (field)) || (TREE_CODE (field) != FUNCTION_DECL && TREE_STATIC (field))); if (! flag_access_control) return access_public; /* The field lives in the current class. */ if (BINFO_TYPE (basetype_path) == current_class_type) return access_public;#if 0 /* Disabled until pushing function scope clears these out. If ever. */ /* Make these special cases fast. */ if (current_scope () == previous_scope) { if (DECL_PUBLIC (field)) return access_public; if (DECL_PROTECTED (field)) return access_protected; if (DECL_PRIVATE (field)) return access_private; }#endif /* We don't currently support access control on nested types. */ if (TREE_CODE (field) == TYPE_DECL) return access_public; previous_scope = current_scope (); context = DECL_CLASS_CONTEXT (field); if (context == NULL_TREE) context = DECL_CONTEXT (field); /* Fields coming from nested anonymous unions have their DECL_CLASS_CONTEXT slot set to the union type rather than the record type containing the anonymous union. In this case, DECL_FIELD_CONTEXT is correct. */ if (context && TREE_CODE (context) == UNION_TYPE && ANON_AGGRNAME_P (TYPE_IDENTIFIER (context))) context = DECL_FIELD_CONTEXT (field); /* Virtual function tables are never private. But we should know that we are looking for this, and not even try to hide it. */ if (DECL_NAME (field) && VFIELD_NAME_P (DECL_NAME (field)) == 1) PUBLIC_RETURN; /* Member found immediately within object. */ if (BINFO_INHERITANCE_CHAIN (basetype_path) == NULL_TREE) { /* Are we (or an enclosing scope) friends with the class that has FIELD? */ if (is_friend (context, previous_scope)) PUBLIC_RETURN; /* If it's private, it's private, you letch. */ if (TREE_PRIVATE (field)) PRIVATE_RETURN; /* ARM $11.5. Member functions of a derived class can access the non-static protected members of a base class only through a pointer to the derived class, a reference to it, or an object of it. Also any subsequently derived classes also have access. */ else if (TREE_PROTECTED (field)) { if (current_class_type && static_mem && ACCESSIBLY_DERIVED_FROM_P (context, current_class_type)) PUBLIC_RETURN; else PROTECTED_RETURN; } else PUBLIC_RETURN;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -