📄 search.c
字号:
{ TREE_VALUE (entry) = rvals; TREE_TYPE (entry) = NULL_TREE; } return rvals; } rval = NULL_TREE; if (name == ctor_identifier || name == dtor_identifier) { /* Don't allow lookups of constructors and destructors to go deeper than the first place we look. */ if (entry) TREE_TYPE (entry) = TREE_VALUE (entry) = NULL_TREE; return 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_expr_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 idx; /* 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 = my_tree_cons (NULL_TREE, TYPE_BINFO (BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo_h), i))), btypes); else btypes = my_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. */ idx = lookup_fnfields_here (type, name); if (idx >= 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 (idx >= 0) { rval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx); /* 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), idx); } 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) { 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; TREE_VALUE (entry) = rvals; } } if (errstr && protect) { cp_error (errstr, name); rvals = error_mark_node; } return rvals;}/* BREADTH-FIRST SEARCH ROUTINES. *//* Search a multiple inheritance hierarchy by breadth-first search. BINFO is an aggregate type, possibly in a multiple-inheritance hierarchy. TESTFN is a function, which, if true, means that our condition has been met, and its return value should be returned. QFN, if non-NULL, is a predicate dictating whether the type should even be queued. */static HOST_WIDE_INTbreadth_first_search (binfo, testfn, qfn) tree binfo; int (*testfn) PROTO((tree, int)); int (*qfn) PROTO((tree, int));{ int head = 0, tail = 0; int rval = 0; search_stack = push_search_level (search_stack, &search_obstack); while (1) { tree binfos = BINFO_BASETYPES (binfo); int n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; int i; /* Process and/or queue base types. */ for (i = 0; i < n_baselinks; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); if (BINFO_MARKED (base_binfo) == 0 && (qfn == 0 || (*qfn) (binfo, i))) { SET_BINFO_MARKED (base_binfo); obstack_ptr_grow (&search_obstack, binfo); obstack_ptr_grow (&search_obstack, (HOST_WIDE_INT) i); tail += 2; if (tail >= search_stack->limit) my_friendly_abort (100); } } /* Process head of queue, if one exists. */ if (head >= tail) { rval = 0; break; } binfo = search_stack->first[head++]; i = (HOST_WIDE_INT) search_stack->first[head++]; if (rval = (*testfn) (binfo, i)) break; binfo = BINFO_BASETYPE (binfo, i); } { tree *tp = search_stack->first; tree *search_tail = tp + tail; while (tp < search_tail) { tree binfo = *tp++; int i = (HOST_WIDE_INT)(*tp++); CLEAR_BINFO_MARKED (BINFO_BASETYPE (binfo, i)); } } search_stack = pop_search_level (search_stack); return rval;}/* Functions to use in breadth first searches. */typedef int (*pfi) PROTO((tree, int));static tree declarator;static treeget_virtuals_named_this (binfo) tree binfo;{ tree fields; fields = lookup_fnfields (binfo, declarator, -1); /* fields cannot be error_mark_node */ if (fields == 0) return 0; /* Get to the function decls, and return the first virtual function with this name, if there is one. */ while (fields) { tree fndecl; for (fndecl = TREE_VALUE (fields); fndecl; fndecl = DECL_CHAIN (fndecl)) if (DECL_VINDEX (fndecl)) return fields; fields = next_baselink (fields); } return NULL_TREE;}static treeget_virtual_destructor (binfo, i) tree binfo; int i;{ tree type = BINFO_TYPE (binfo); if (i >= 0) type = BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo), i)); if (TYPE_HAS_DESTRUCTOR (type) && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 1))) return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 1); return 0;}static inttree_has_any_destructor_p (binfo, i) tree binfo; int i;{ tree type = BINFO_TYPE (binfo); if (i >= 0) type = BINFO_TYPE (TREE_VEC_ELT (BINFO_BASETYPES (binfo), i)); return TYPE_NEEDS_DESTRUCTOR (type);}/* Given a class type TYPE, and a function decl FNDECL, look for a virtual function in TYPE's hierarchy which FNDECL could match as a virtual function. It doesn't matter which one we find. DTORP is nonzero if we are looking for a destructor. Destructors need special treatment because they do not match by name. */treeget_matching_virtual (binfo, fndecl, dtorp) tree binfo, fndecl; int dtorp;{ tree tmp = NULL_TREE; /* Breadth first search routines start searching basetypes of TYPE, so we must perform first ply of search here. */ if (dtorp) { if (tree_has_any_destructor_p (binfo, -1)) tmp = get_virtual_destructor (binfo, -1); if (tmp) return tmp; tmp = (tree) breadth_first_search (binfo, (pfi) get_virtual_destructor, tree_has_any_destructor_p); return tmp; } else { tree drettype, dtypes, btypes, instptr_type; tree basetype = DECL_CLASS_CONTEXT (fndecl); tree baselink, best = NULL_TREE; tree name = DECL_ASSEMBLER_NAME (fndecl); declarator = DECL_NAME (fndecl); if (IDENTIFIER_VIRTUAL_P (declarator) == 0) return NULL_TREE; baselink = get_virtuals_named_this (binfo); if (baselink == NULL_TREE) return NULL_TREE; drettype = TREE_TYPE (TREE_TYPE (fndecl)); dtypes = TYPE_ARG_TYPES (TREE_TYPE (fndecl)); if (DECL_STATIC_FUNCTION_P (fndecl)) instptr_type = NULL_TREE; else instptr_type = TREE_TYPE (TREE_VALUE (dtypes)); for (; baselink; baselink = next_baselink (baselink)) { for (tmp = TREE_VALUE (baselink); tmp; tmp = DECL_CHAIN (tmp)) { if (! DECL_VINDEX (tmp)) continue; btypes = TYPE_ARG_TYPES (TREE_TYPE (tmp)); if (instptr_type == NULL_TREE) { if (compparms (TREE_CHAIN (btypes), dtypes, 3)) /* Caller knows to give error in this case. */ return tmp; return NULL_TREE; } if ((TYPE_READONLY (TREE_TYPE (TREE_VALUE (btypes))) == TYPE_READONLY (instptr_type)) && compparms (TREE_CHAIN (btypes), TREE_CHAIN (dtypes), 3)) { tree brettype = TREE_TYPE (TREE_TYPE (tmp)); if (comptypes (brettype, drettype, 1)) /* OK */; else if (TREE_CODE (brettype) == TREE_CODE (drettype) && (TREE_CODE (brettype) == POINTER_TYPE || TREE_CODE (brettype) == REFERENCE_TYPE) && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (brettype)), TYPE_MAIN_VARIANT (TREE_TYPE (drettype)), 0)) /* covariant return type */ { tree b = TREE_TYPE (brettype), d = TREE_TYPE (drettype); if (TYPE_MAIN_VARIANT (b) != TYPE_MAIN_VARIANT (d)) { tree binfo = get_binfo (b, d, 1); if (binfo != error_mark_node && (! BINFO_OFFSET_ZEROP (binfo) || TREE_VIA_VIRTUAL (binfo))) sorry ("adjusting pointers for covariant returns"); } if (TYPE_READONLY (d) > TYPE_READONLY (b)) { cp_error_at ("return type of `%#D' adds const", fndecl); cp_error_at (" overriding definition as `%#D'", tmp); } else if (TYPE_VOLATILE (d) > TYPE_VOLATILE (b)) { cp_error_at ("return type of `%#D' adds volatile", fndecl); cp_error_at (" overriding definition as `%#D'", tmp); } } else if (IS_AGGR_TYPE_2 (brettype, drettype) && comptypes (brettype, drettype, 0)) { error ("invalid covariant return type (must use pointer or reference)"); cp_error_at (" overriding `%#D'", tmp); cp_error_at (" with `%#D'", fndecl); } else if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE) { cp_error_at ("conflicting return type specified for virtual function `%#D'", fndecl); cp_error_at (" overriding definition as `%#D'", tmp); SET_IDENTIFIER_ERROR_LOCUS (name, basetype); } break; } } if (tmp) { best = tmp; break; } } return best; }}/* Return the list of virtual functions which are abstract in type TYPE that come from non virtual base classes. See expand_direct_vtbls_init for the style of search we do. */static treeget_abstract_virtuals_1 (binfo, do_self, abstract_virtuals) tree binfo; int do_self; tree abstract_virtuals;{ tree binfos = BINFO_BASETYPES (binfo); 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); int is_not_base_vtable = i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (binfo)); if (! TREE_VIA_VIRTU
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -