📄 search.c
字号:
} /* must reverse more than one element */ basetype_path = reverse_path (basetype_path); types = basetype_path; via_protected = 0; access = access_default; protected_ok = static_mem && current_class_type && ACCESSIBLY_DERIVED_FROM_P (BINFO_TYPE (types), current_class_type); while (1) { tree member; tree binfo = types; tree type = BINFO_TYPE (binfo); int private_ok = 0; /* Friends of a class can see protected members of its bases. Note that classes are their own friends. */ if (is_friend (type, previous_scope)) { protected_ok = 1; private_ok = 1; } member = purpose_member (type, DECL_ACCESS (field)); if (member) { access = (enum access_type) TREE_VALUE (member); break; } types = BINFO_INHERITANCE_CHAIN (types); /* If the next type was VIA_PROTECTED, then fields of all remaining classes past that one are *at least* protected. */ if (types) { if (TREE_VIA_PROTECTED (types)) via_protected = 1; else if (! TREE_VIA_PUBLIC (types) && ! private_ok) { access = access_private; break; } } else break; } reverse_path (basetype_path); /* No special visibilities apply. Use normal rules. */ if (access == access_default) { if (is_friend (context, previous_scope)) access = access_public; else if (TREE_PRIVATE (field)) access = access_private; else if (TREE_PROTECTED (field)) access = access_protected; else access = access_public; } if (access == access_public && via_protected) access = access_protected; if (access == access_protected && protected_ok) access = access_public;#if 0 if (access == access_public) DECL_PUBLIC (field) = 1; else if (access == access_protected) DECL_PROTECTED (field) = 1; else if (access == access_private) DECL_PRIVATE (field) = 1; else my_friendly_abort (96);#endif return access;}/* Routine to see if the sub-object denoted by the binfo PARENT can be found as a base class and sub-object of the object denoted by BINFO. This routine relies upon binfos not being shared, except for binfos for virtual bases. */static intis_subobject_of_p (parent, binfo) tree parent, binfo;{ tree binfos = BINFO_BASETYPES (binfo); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; if (parent == binfo) return 1; /* Process and/or queue base types. */ for (i = 0; i < n_baselinks; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); if (TREE_VIA_VIRTUAL (base_binfo)) base_binfo = TYPE_BINFO (BINFO_TYPE (base_binfo)); if (is_subobject_of_p (parent, base_binfo)) return 1; } return 0;}/* See if a one FIELD_DECL hides another. This routine is meant to correspond to ANSI working paper Sept 17, 1992 10p4. The two binfos given are the binfos corresponding to the particular places the FIELD_DECLs are found. This routine relies upon binfos not being shared, except for virtual bases. */static inthides (hider_binfo, hidee_binfo) tree hider_binfo, hidee_binfo;{ /* hider hides hidee, if hider has hidee as a base class and the instance of hidee is a sub-object of hider. The first part is always true is the second part is true. When hider and hidee are the same (two ways to get to the exact same member) we consider either one as hiding the other. */ return is_subobject_of_p (hidee_binfo, hider_binfo);}/* Very similar to lookup_fnfields_1 but it ensures that at least one function was declared inside the class given by TYPE. It really should only return functions that match the given TYPE. */static intlookup_fnfields_here (type, name) tree type, name;{ int index = lookup_fnfields_1 (type, name); tree fndecls; if (index <= 0) return index; fndecls = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index); while (fndecls) { if (TYPE_MAIN_VARIANT (DECL_CLASS_CONTEXT (fndecls)) == TYPE_MAIN_VARIANT (type)) return index; fndecls = TREE_CHAIN (fndecls); } return -1;}/* Look for a field named NAME in an inheritance lattice dominated by XBASETYPE. PROTECT is zero if we can avoid computing access 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_TREE. It was not clear what should happen if WANT_TYPE is set, and an ambiguity is found. At least one use (lookup_name) to not see the error. */treelookup_field (xbasetype, name, protect, want_type) register tree xbasetype, name; int protect, want_type;{ int head = 0, tail = 0; tree rval, rval_binfo = NULL_TREE, rval_binfo_h; tree type, basetype_chain, basetype_path; enum access_type this_v = access_default; tree entry, binfo, binfo_h; enum access_type own_access = access_default; int vbase_name_p = VBASE_NAME_P (name); /* rval_binfo is the binfo associated with the found member, note, this can be set with useful information, even when rval is not set, because it must deal with ALL members, not just non-function members. It is used for ambiguity checking and the hidden checks. Whereas rval is only set if a proper (not hidden) non-function member is found. */ /* rval_binfo_h and binfo_h are binfo values used when we perform the hiding checks, as virtual base classes may not be shared. The strategy is we always go into the the binfo hierarchy owned by TYPE_BINFO of virtual base classes, as we cross virtual base class lines. This way we know that binfo of a virtual base class will always == itself when found along any line. (mrs) */ char *errstr = 0; /* Set this to nonzero if we don't know how to compute accurate error messages for access control. */ int index = MEMOIZED_HASH_FN (name); /* If we are looking for a constructor in a templated type, use the unspecialized name, as that is how we store it. */ if (IDENTIFIER_TEMPLATE (name)) name = constructor_name (name); if (TREE_CODE (xbasetype) == TREE_VEC) { type = BINFO_TYPE (xbasetype); basetype_path = xbasetype; } else if (IS_AGGR_TYPE_CODE (TREE_CODE (xbasetype))) { type = xbasetype; basetype_path = TYPE_BINFO (xbasetype); BINFO_VIA_PUBLIC (basetype_path) = 1; BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE; } 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 || lookup_fnfields_here (type, name) >= 0) { if (rval) { if (want_type) { if (TREE_CODE (rval) != TYPE_DECL) { rval = purpose_member (name, CLASSTYPE_TAGS (type)); if (rval) rval = TYPE_MAIN_DECL (TREE_VALUE (rval)); } } else { if (TREE_CODE (rval) == TYPE_DECL && lookup_fnfields_here (type, name) >= 0) rval = NULL_TREE; } } if (protect && rval) { if (TREE_PRIVATE (rval) | TREE_PROTECTED (rval)) this_v = compute_access (basetype_path, rval); if (TREE_CODE (rval) == CONST_DECL) { if (this_v == access_private) errstr = "enum `%D' is a private value of class `%T'"; else if (this_v == access_protected) errstr = "enum `%D' is a protected value of class `%T'"; } else { if (this_v == access_private) errstr = "member `%D' is a private member of class `%T'"; else if (this_v == access_protected) errstr = "member `%D' is a protected member of class `%T'"; } } 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) { cp_error (errstr, name, type); return error_mark_node; } return rval; } basetype_chain = build_tree_list (NULL_TREE, basetype_path); TREE_VIA_PUBLIC (basetype_chain) = TREE_VIA_PUBLIC (basetype_path); TREE_VIA_PROTECTED (basetype_chain) = TREE_VIA_PROTECTED (basetype_path); TREE_VIA_VIRTUAL (basetype_chain) = TREE_VIA_VIRTUAL (basetype_path); /* The ambiguity check relies upon breadth first searching. */ search_stack = push_search_level (search_stack, &search_obstack); binfo = basetype_path; binfo_h = binfo; while (1) { tree binfos = BINFO_BASETYPES (binfo); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; tree nval; /* Process and/or queue base types. */ for (i = 0; i < n_baselinks; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); if (BINFO_FIELDS_MARKED (base_binfo) == 0) { tree btypes; SET_BINFO_FIELDS_MARKED (base_binfo); btypes = my_tree_cons (NULL_TREE, base_binfo, basetype_chain); TREE_VIA_PUBLIC (btypes) = TREE_VIA_PUBLIC (base_binfo); TREE_VIA_PROTECTED (btypes) = TREE_VIA_PROTECTED (base_binfo); TREE_VIA_VIRTUAL (btypes) = TREE_VIA_VIRTUAL (base_binfo); if (TREE_VIA_VIRTUAL (base_binfo)) btypes = tree_cons (NULL_TREE, TYPE_BINFO (BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i))), btypes); else btypes = tree_cons (NULL_TREE, TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i), btypes); obstack_ptr_grow (&search_obstack, btypes); tail += 1; if (tail >= search_stack->limit) my_friendly_abort (98); } } /* Process head of queue, if one exists. */ if (head >= tail) break; basetype_chain = search_stack->first[head++]; binfo_h = TREE_VALUE (basetype_chain); basetype_chain = TREE_CHAIN (basetype_chain); basetype_path = TREE_VALUE (basetype_chain); if (TREE_CHAIN (basetype_chain)) BINFO_INHERITANCE_CHAIN (basetype_path) = TREE_VALUE (TREE_CHAIN (basetype_chain)); else BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE; binfo = basetype_path; type = BINFO_TYPE (binfo); /* See if we can find NAME in TYPE. If RVAL is nonzero, and we do find NAME in TYPE, verify that such a second sighting is in fact valid. */ nval = lookup_field_1 (type, name); if (nval || lookup_fnfields_here (type, name)>=0) { if (nval && nval == rval && SHARED_MEMBER_P (nval)) { /* This is ok, the member found is the same [class.ambig] */ } else if (rval_binfo && hides (rval_binfo_h, binfo_h)) { /* This is ok, the member found is in rval_binfo, not here (binfo). */ } else if (rval_binfo==NULL_TREE || hides (binfo_h, rval_binfo_h)) { /* This is ok, the member found is here (binfo), not in rval_binfo. */ if (nval) { rval = nval; if (entry || protect) this_v = compute_access (basetype_path, rval); /* These may look ambiguous, but they really are not. */ if (vbase_name_p) break; } else { /* Undo finding it before, as something else hides it. */ rval = NULL_TREE; } rval_binfo = binfo; rval_binfo_h = binfo_h; } else { /* This is ambiguous. */ errstr = "request for member `%D' is ambiguous"; protect = 2; break; } } } { tree *tp = search_stack->first; tree *search_tail = tp + tail; if (entry) TREE_VALUE (entry) = rval; if (rval_binfo) { type = BINFO_TYPE (rval_binfo); if (rval) { if (want_type) { if (TREE_CODE (rval) != TYPE_DECL) { rval = purpose_member (name, CLASSTYPE_TAGS (type)); if (rval) rval = TYPE_MAIN_DECL (TREE_VALUE (rval)); } } else { if (TREE_CODE (rval) == TYPE_DECL && lookup_fnfields_here (type, name) >= 0) rval = NULL_TREE; } } } if (rval == NULL_TREE) errstr = 0; /* If this FIELD_DECL defines its own access level, deal with that. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -