📄 search.c
字号:
if (rval && errstr == 0 && ((protect&1) || entry) && DECL_LANG_SPECIFIC (rval) && DECL_ACCESS (rval)) { while (tp < search_tail) { /* If is possible for one of the derived types on the path to have defined special access for this field. Look for such declarations and report an error if a conflict is found. */ enum access_type new_v; if (this_v != access_default) new_v = compute_access (TREE_VALUE (TREE_CHAIN (*tp)), rval); if (this_v != access_default && new_v != this_v) { errstr = "conflicting access to member `%D'"; this_v = access_default; } own_access = new_v; CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp))); tp += 1; } } else { while (tp < search_tail) { CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp))); tp += 1; } } } search_stack = pop_search_level (search_stack); if (errstr == 0) { if (own_access == access_private) errstr = "member `%D' declared private"; else if (own_access == access_protected) errstr = "member `%D' declared protected"; else if (this_v == access_private) errstr = TREE_PRIVATE (rval) ? "member `%D' is private" : "member `%D' is from private base class"; else if (this_v == access_protected) errstr = TREE_PROTECTED (rval) ? "member `%D' is protected" : "member `%D' is from protected base class"; } if (entry) { if (errstr) { tree error_string = my_build_string (errstr); /* Save error message with entry. */ TREE_TYPE (entry) = error_string; } else { /* Mark entry as having no error string. */ TREE_TYPE (entry) = NULL_TREE; } } if (errstr && protect) { cp_error (errstr, name, type); rval = error_mark_node; } return rval;}/* Try to find NAME inside a nested class. */treelookup_nested_field (name, complain) tree name; int complain;{ register tree t; tree id = NULL_TREE; if (TREE_CHAIN (current_class_type)) { /* Climb our way up the nested ladder, seeing if we're trying to modify a field in an enclosing class. If so, we should only be able to modify if it's static. */ for (t = TREE_CHAIN (current_class_type); t && DECL_CONTEXT (t); t = TREE_CHAIN (DECL_CONTEXT (t))) { if (TREE_CODE (DECL_CONTEXT (t)) != RECORD_TYPE) break; /* N.B.: lookup_field will do the access checking for us */ id = lookup_field (DECL_CONTEXT (t), name, complain, 0); if (id == error_mark_node) { id = NULL_TREE; continue; } if (id != NULL_TREE) { if (TREE_CODE (id) == FIELD_DECL && ! TREE_STATIC (id) && TREE_TYPE (id) != error_mark_node) { if (complain) { /* At parse time, we don't want to give this error, since we won't have enough state to make this kind of decision properly. But there are times (e.g., with enums in nested classes) when we do need to call this fn at parse time. So, in those cases, we pass complain as a 0 and just return a NULL_TREE. */ error ("assignment to non-static member `%s' of enclosing class `%s'", lang_printable_name (id), IDENTIFIER_POINTER (TYPE_IDENTIFIER (DECL_CONTEXT (t)))); /* Mark this for do_identifier(). It would otherwise claim that the variable was undeclared. */ TREE_TYPE (id) = error_mark_node; } else { id = NULL_TREE; continue; } } break; } } } return id;}/* TYPE is a class type. Return the index of the fields within the method vector with name NAME, or -1 is no such field exists. */static intlookup_fnfields_1 (type, name) tree type, name;{ register tree method_vec = CLASSTYPE_METHOD_VEC (type); if (method_vec != 0) { register tree *methods = &TREE_VEC_ELT (method_vec, 0); register tree *end = TREE_VEC_END (method_vec);#ifdef GATHER_STATISTICS n_calls_lookup_fnfields_1++;#endif if (*methods && name == constructor_name (type)) return 0; while (++methods != end) {#ifdef GATHER_STATISTICS n_outer_fields_searched++;#endif if (DECL_NAME (*methods) == name) break; } if (methods != end) return methods - &TREE_VEC_ELT (method_vec, 0); } return -1;}/* Starting from BASETYPE, return a TREE_BASELINK-like object which gives the following information (in a list): TREE_TYPE: list of basetypes needed to get to... TREE_VALUE: list of all functions in of given type which have name NAME. No access information is computed by this function, other then to adorn the list of basetypes with TREE_VIA_PUBLIC. If there are two ways to find a name (two members), if COMPLAIN is non-zero, then error_mark_node is returned, and an error message is printed, otherwise, just an error_mark_node is returned. As a special case, is COMPLAIN is -1, we don't complain, and we don't return error_mark_node, but rather the complete list of virtuals. This is used by get_virtuals_named_this. */treelookup_fnfields (basetype_path, name, complain) tree basetype_path, name; int complain;{ int head = 0, tail = 0; tree type, rval, rval_binfo = NULL_TREE, rvals = NULL_TREE, rval_binfo_h; tree entry, binfo, basetype_chain, binfo_h; int find_all = 0; /* 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 function members. It is used for ambiguity checking and the hidden checks. Whereas rval is only set if a proper (not hidden) 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) */ /* For now, don't try this. */ int protect = complain; 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 (complain == -1) { find_all = 1; protect = complain = 0; } /* 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); binfo = basetype_path; binfo_h = binfo; type = BINFO_TYPE (basetype_path); /* The memoization code is in need of maintenance. */ if (!find_all && CLASSTYPE_MTABLE_ENTRY (type)) { tree tem = MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), index); while (tem && TREE_PURPOSE (tem) != name) { memoized_fields_searched[1]++; 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_CLASS_CONTEXT (TREE_VALUE (TREE_VALUE (tem))))); return error_mark_node; } if (TREE_VALUE (tem) == NULL_TREE) { memoized_fast_rejects[1] += 1; return NULL_TREE; } else { /* Want to return this, but we must make sure that access information is consistent. */ tree baselink = TREE_VALUE (tem); tree memoized_basetypes = TREE_PURPOSE (baselink); tree these_basetypes = basetype_path; while (memoized_basetypes && these_basetypes) { memoized_fields_searched[1]++; if (TREE_VALUE (memoized_basetypes) != these_basetypes) break; memoized_basetypes = TREE_CHAIN (memoized_basetypes); these_basetypes = BINFO_INHERITANCE_CHAIN (these_basetypes); } /* The following statement is true only when both are NULL. */ if (memoized_basetypes == these_basetypes) { memoized_fast_finds[1] += 1; return TREE_VALUE (tem); } /* else, we must re-find this field by hand. */ baselink = tree_cons (basetype_path, TREE_VALUE (baselink), TREE_CHAIN (baselink)); return baselink; } } }#ifdef GATHER_STATISTICS n_calls_lookup_fnfields++;#endif if (protect && flag_memoize_lookups && ! global_bindings_p ()) entry = make_memoized_table_entry (type, name, 1); else entry = 0; index = lookup_fnfields_here (type, name); if (index >= 0 || lookup_field_1 (type, name)) { rval_binfo = basetype_path; rval_binfo_h = rval_binfo; } if (index >= 0) { rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index); rvals = my_tree_cons (basetype_path, rval, rvals); if (BINFO_BASETYPES (binfo) && CLASSTYPE_BASELINK_VEC (type)) TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index); if (entry) { TREE_VALUE (entry) = rvals; TREE_TYPE (entry) = NULL_TREE; } return rvals; } rval = NULL_TREE; if (basetype_path == TYPE_BINFO (type)) { basetype_chain = CLASSTYPE_BINFO_AS_LIST (type); TREE_VIA_PUBLIC (basetype_chain) = 1; BINFO_VIA_PUBLIC (basetype_path) = 1; BINFO_INHERITANCE_CHAIN (basetype_path) = NULL_TREE; } else { 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; int index; /* 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 (99); } } /* 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. */ index = lookup_fnfields_here (type, name); if (index >= 0 || (lookup_field_1 (type, name)!=NULL_TREE && !find_all)) { if (rval_binfo && !find_all && 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 || find_all || hides (binfo_h, rval_binfo_h)) { /* This is ok, the member found is here (binfo), not in rval_binfo. */ if (index >= 0) { rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index); /* Note, rvals can only be previously set if find_all is true. */ rvals = my_tree_cons (basetype_path, rval, rvals); if (TYPE_BINFO_BASETYPES (type) && CLASSTYPE_BASELINK_VEC (type)) TREE_TYPE (rvals) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index); } else { /* Undo finding it before, as something else hides it. */ rval = NULL_TREE; rvals = NULL_TREE; } rval_binfo = binfo; rval_binfo_h = binfo_h; } else { /* This is ambiguous. */ errstr = "request for method `%D' is ambiguous"; rvals = error_mark_node; break; } } } { tree *tp = search_stack->first; tree *search_tail = tp + tail; while (tp < search_tail) { CLEAR_BINFO_FIELDS_MARKED (TREE_VALUE (TREE_CHAIN (*tp))); tp += 1; } } search_stack = pop_search_level (search_stack); if (entry) { if (errstr)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -