📄 cp-search.c
字号:
if (tp+((i+1)*increment) < search_tail) my_friendly_assert (base_binfo == tp[(i+1)*increment], 295); if (rval = recursive_bounded_basetype_p (binfo, base_binfo, rval, 1)) break; } if (rval > 0) BINFO_INHERITANCE_CHAIN (base_binfo) = *tp; } /* Because I don't trust recursive_bounded_basetype_p to find all ambiguities, I will just make sure here. When it is sure that all ambiguities are found, the two routines and this call can be removed. Not toally sure this should be here, but I think it should. (mrs) */ if (get_binfo2 (parent, type) == error_mark_node && rval != -2) {#if 1 /* This warning is here because the code over in prepare_fresh_vtable relies on partial completion offered by recursive_bounded_basetype_p I think, but that behavior is not documented. It needs to be. I don't think prepare_fresh_vtable is the only routine that relies upon path_ptr being set to something in a particular way when this routine returns -2. (mrs) */ warning ("internal consistency check failed, please report, recovering."); rval = -2;#endif } /* Visibilities don't count if we found an ambiguous basetype. */ if (rval == -2) rval_private = 0; } } search_stack = pop_search_level (search_stack); if (rval && protect && rval_private) return -3; if (path_ptr) *path_ptr = 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 has a visible path to 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;}/* Compute the visibility of FIELD. This is done by computing the visibility 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 visibility defines the visibility for the field. Otherwise, the visibility 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. */#define PUBLIC_RETURN return (DECL_PUBLIC (field) = 1), visibility_public#define PROTECTED_RETURN return (DECL_PROTECTED (field) = 1), visibility_protected#define PRIVATE_RETURN return (DECL_PRIVATE (field) = 1), visibility_privateenum visibility_typecompute_visibility (basetype_path, field) tree basetype_path, field;{ enum visibility_type visibility = visibility_public; tree types; tree context = DECL_CLASS_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) return visibility_public; /* Make these special cases fast. */ if (BINFO_TYPE (basetype_path) == current_class_type) { if (DECL_PUBLIC (field)) return visibility_public; if (DECL_PROTECTED (field)) return visibility_protected; if (DECL_PRIVATE (field)) return visibility_private; } /* Member function manipulating its own members. */ if (current_class_type == context) PUBLIC_RETURN; /* Member found immediately within object. */ if (BINFO_INHERITANCE_CHAIN (basetype_path) == NULL_TREE) { /* At object's top level, public members are public. */ if (TREE_PROTECTED (field) == 0 && TREE_PRIVATE (field) == 0) PUBLIC_RETURN; /* Friend function manipulating members it gets (for being a friend). */ if (is_friend (context, current_function_decl)) PUBLIC_RETURN; /* Inner than that, without special visibility, protected members are ok if type of object is current_class_type is derived therefrom. This means that if the type of the object is a base type for our current class type, we cannot access protected members. private members are not ok. */ if (current_class_type && DECL_VISIBILITY (field) == NULL_TREE) { if (TREE_PRIVATE (field)) PRIVATE_RETURN; if (TREE_PROTECTED (field)) { if (context == current_class_type || UNIQUELY_DERIVED_FROM_P (context, current_class_type)) PUBLIC_RETURN; else PROTECTED_RETURN; } else my_friendly_abort (94); } } /* Friend function manipulating members it gets (for being a friend). */ if (is_friend (context, current_function_decl)) PUBLIC_RETURN; /* must reverse more than one element */ basetype_path = reverse_path (basetype_path); types = basetype_path; while (types) { tree member; tree binfo = types; tree type = BINFO_TYPE (binfo); member = purpose_member (type, DECL_VISIBILITY (field)); if (member) { visibility = (enum visibility_type)TREE_VALUE (member); if (visibility == visibility_public || is_friend (type, current_function_decl) || (visibility == visibility_protected && current_class_type && UNIQUELY_DERIVED_FROM_P (context, current_class_type))) visibility = visibility_public; goto ret; } /* Friends inherit the visibility of the class they inherit from. */ if (is_friend (type, current_function_decl)) { if (type == context) { visibility = visibility_public; goto ret; } if (TREE_PROTECTED (field)) { visibility = visibility_public; goto ret; }#if 0 /* This short-cut is too short. */ if (visibility == visibility_public) goto ret;#endif /* else, may be a friend of a deeper base class */ } if (type == context) break; types = BINFO_INHERITANCE_CHAIN (types); /* If the next type was not VIA_PUBLIC, then fields of all remaining class past that one are private. */ if (types) { if (TREE_VIA_PROTECTED (types)) visibility = visibility_protected; else if (! TREE_VIA_PUBLIC (types)) visibility = visibility_private; } } /* No special visibilities apply. Use normal rules. No assignment needed for BASETYPEs here from the nreverse. This is because we use it only for information about the path to the base. The code earlier dealt with what happens when we are at the base level. */ if (visibility == visibility_public) { basetype_path = reverse_path (basetype_path); if (TREE_PRIVATE (field)) PRIVATE_RETURN; if (TREE_PROTECTED (field)) { /* Used to check if the current class type was derived from the type that contains the field. This is wrong for multiple inheritance because is gives one class reference to protected members via another classes protected path. I.e., if A; B1 : A; B2 : A; Then B1 and B2 can access their own members which are protected in A, but not those same members in one another. */ if (current_class_type && UNIQUELY_DERIVED_FROM_P (context, current_class_type)) PUBLIC_RETURN; PROTECTED_RETURN; } PUBLIC_RETURN; } if (visibility == visibility_protected) { /* reverse_path? */ if (TREE_PRIVATE (field)) PRIVATE_RETURN; /* We want to make sure that all non-private members in the current class (as derived) are accessible. */ if (current_class_type && UNIQUELY_DERIVED_FROM_P (context, current_class_type)) PUBLIC_RETURN; PROTECTED_RETURN; } if (visibility == visibility_private && current_class_type != NULL_TREE) { if (TREE_PRIVATE (field)) { reverse_path (basetype_path); PRIVATE_RETURN; } /* See if the field isn't protected. */ if (TREE_PROTECTED (field)) { tree test = basetype_path; while (test) { if (BINFO_TYPE (test) == current_class_type) break; test = BINFO_INHERITANCE_CHAIN (test); } reverse_path (basetype_path); if (test) PUBLIC_RETURN; PROTECTED_RETURN; } /* See if the field isn't a public member of a private base class. */ visibility = visibility_public; types = BINFO_INHERITANCE_CHAIN (basetype_path); while (types) { if (! TREE_VIA_PUBLIC (types)) { if (visibility == visibility_private) { visibility = visibility_private; goto ret; } visibility = visibility_private; } if (BINFO_TYPE (types) == context) { visibility = visibility_public; goto ret; } types = BINFO_INHERITANCE_CHAIN (types); } my_friendly_abort (95); } ret: reverse_path (basetype_path); if (visibility == visibility_public) DECL_PUBLIC (field) = 1; else if (visibility == visibility_protected) DECL_PROTECTED (field) = 1; else if (visibility == visibility_private) DECL_PRIVATE (field) = 1; else my_friendly_abort (96); return visibility;}/* Look for a field named NAME in an inheritance lattice dominated by XBASETYPE. PROTECT is zero if we can avoid computing visibility information, otherwise it is 1. WANT_TYPE is 1 when we should only return TYPE_DECLs, if no TYPE_DECL can be found return NULL. */treelookup_field (xbasetype, name, protect, want_type) register tree xbasetype, name; int protect, want_type;{ int head = 0, tail = 0; tree rval; tree type, basetype_chain, basetype_path; enum visibility_type this_v = visibility_default; tree entry, binfo; enum visibility_type own_visibility = visibility_default; int vbase_name_p = VBASE_NAME_P (name); /* Things for memoization. */ char *errstr = 0; /* Set this to nonzero if we don't know how to compute accurate error messages for visibility. */ int index = MEMOIZED_HASH_FN (name); if (TREE_CODE (xbasetype) == TREE_VEC) basetype_path = xbasetype, type = BINFO_TYPE (xbasetype); else if (IS_AGGR_TYPE_CODE (TREE_CODE (xbasetype))) basetype_path = TYPE_BINFO (xbasetype), type = xbasetype; else my_friendly_abort (97); if (CLASSTYPE_MTABLE_ENTRY (type)) { tree tem = MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), index); while (tem && TREE_PURPOSE (tem) != name) { memoized_fields_searched[0]++; tem = TREE_CHAIN (tem); } if (tem) { if (protect && TREE_TYPE (tem)) { error (TREE_STRING_POINTER (TREE_TYPE (tem)), IDENTIFIER_POINTER (name), TYPE_NAME_STRING (DECL_FIELD_CONTEXT (TREE_VALUE (tem)))); return error_mark_node; } if (TREE_VALUE (tem) == NULL_TREE) memoized_fast_rejects[0] += 1; else memoized_fast_finds[0] += 1; return TREE_VALUE (tem); } }#ifdef GATHER_STATISTICS n_calls_lookup_field++;#endif if (protect && flag_memoize_lookups && ! global_bindings_p ()) entry = make_memoized_table_entry (type, name, 0); else entry = 0; rval = lookup_field_1 (type, name); if (rval && TREE_CODE (rval) != TYPE_DECL && want_type) rval = NULL_TREE; if (rval) { if (protect) { if (TREE_PRIVATE (rval) | TREE_PROTECTED (rval)) this_v = compute_visibility (basetype_path, rval); if (TREE_CODE (rval) == CONST_DECL) { if (this_v == visibility_private) errstr = "enum `%s' is a private value of class `%s'"; else if (this_v == visibility_protected) errstr = "enum `%s' is a protected value of class `%s'"; } else { if (this_v == visibility_private) errstr = "member `%s' is a private member of class `%s'"; else if (this_v == visibility_protected) errstr = "member `%s' is a protected member of class `%s'"; } } if (entry) { if (errstr) { /* This depends on behavior of lookup_field_1! */ tree error_string = my_build_string (errstr); TREE_TYPE (entry) = error_string; } else { /* Let entry know there is no problem with this access. */ TREE_TYPE (entry) = NULL_TREE; } TREE_VALUE (entry) = rval; } if (errstr && protect) { error (errstr, IDENTIFIER_POINTER (name), TYPE_NAME_STRING (type)); return error_mark_node; } return rval; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -