📄 search.c
字号:
{ 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. TYPE 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. */HOST_WIDE_INTbreadth_first_search (binfo, testfn, qfn) tree binfo; int (*testfn)(); int (*qfn)();{ 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 tree (*pft)();typedef int (*pfi)();int tree_needs_constructor_p (binfo, i) tree binfo; int i;{ tree basetype; my_friendly_assert (i != 0, 296); basetype = BINFO_TYPE (BINFO_BASETYPE (binfo, i)); return TYPE_NEEDS_CONSTRUCTING (basetype);}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 tree get_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), 0))) return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0); return 0;}int tree_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)) sorry ("adjusting pointers for covariant returns"); } if (TYPE_READONLY (d) > TYPE_READONLY (b)) { cp_error ("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 ("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 (" with `%#D'", fndecl); } else if (IDENTIFIER_ERROR_LOCUS (name) == NULL_TREE) { cp_error ("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; } } if (best == NULL_TREE && warn_overloaded_virtual) cp_warning_at ("conflicting specification deriving virtual function `%D'", fndecl); 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, abstract_virtuals; int do_self;{ 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_VIRTUAL (base_binfo)) abstract_virtuals = get_abstract_virtuals_1 (base_binfo, is_not_base_vtable, abstract_virtuals); } /* Should we use something besides CLASSTYPE_VFIELDS? */ if (do_self && CLASSTYPE_VFIELDS (BINFO_TYPE (binfo))) { tree virtuals = BINFO_VIRTUALS (binfo); skip_rtti_stuff (&virtuals); while (virtuals) { tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)); tree base_fndecl = TREE_OPERAND (base_pfn, 0); if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl)) abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals); virtuals = TREE_CHAIN (virtuals); } } return abstract_virtuals;}/* Return the list of virtual functions which are abstract in type TYPE. This information is cached, and so must be built on a non-temporary obstack. */treeget_abstract_virtuals (type) tree type;{ tree vbases; tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (type); /* First get all from non-virtual bases. */ abstract_virtuals = get_abstract_virtuals_1 (TYPE_BINFO (type), 1, abstract_virtuals); for (vbases = CLASSTYPE_VBASECLASSES (type); vbases; vbases = TREE_CHAIN (vbases)) { tree virtuals = BINFO_VIRTUALS (vbases); skip_rtti_stuff (&virtuals); while (virtuals) { tree base_pfn = FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (virtuals)); tree base_fndecl = TREE_OPERAND (base_pfn, 0); if (DECL_ABSTRACT_VIRTUAL_P (base_fndecl)) abstract_virtuals = tree_cons (NULL_TREE, base_fndecl, abstract_virtuals); virtuals = TREE_CHAIN (virtuals); } } return nreverse (abstract_virtuals);}/* For the type TYPE, return a list of member functions available from base classes with name NAME. The TREE_VALUE of the list is a chain of member functions with name NAME. The TREE_PURPOSE of the list is a basetype, or a list of base types (in reverse order) which were traversed to reach the chain of member functions. If we reach a base type which provides a member function of name NAME, and which has at most one base type itself, then we can terminate the search. */treeget_baselinks (type_as_binfo_list, type, name) tree type_as_binfo_list; tree type, name;{ int head = 0, tail = 0, index; tree rval = 0, nval = 0; tree basetypes = type_as_binfo_list; tree binfo = TYPE_BINFO (type); search_stack = push_search_level (search_stack, &search_obstack); while (1) { tree binfos = BINFO_BASETYPES (binfo); int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; /* Process and/or queue base types. */ for (i = 0; i < n_baselinks; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); tree btypes; btypes = hash_tree_cons (TREE_VIA_PUBLIC (base_binfo), TREE_VIA_VIRTUAL (base_binfo), TREE_VIA_PROTECTED (base_binfo), NULL_TREE, base_binfo, basetypes); obstack_ptr_grow (&search_obstack, btypes); search_stack->first = (tree *)obstack_base (&search_obstack); tail += 1; } dont_queue: /* Process head of queue, if one exists. */ if (head >= tail) break; basetypes = search_stack->first[head++]; binfo = TREE_VALUE (basetypes); type = BINFO_TYPE (binfo); index = lookup_fnfields_1 (type, name); if (index >= 0) { nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), index); rval = hash_tree_cons (0, 0, 0, basetypes, nval, rval); if (TYPE_BINFO_BASETYPES (type) == 0) goto dont_queue; else if (TREE_VEC_LENGTH (TYPE_BINFO_BASETYPES (type)) == 1) { if (CLASSTYPE_BASELINK_VEC (type)) TREE_TYPE (rval) = TREE_VEC_ELT (CLASSTYPE_BASELINK_VEC (type), index); goto dont_queue; } } nval = NULL_TREE; } search_stack = pop_search_level (search_stack); return rval;}treenext_baselink (baselink) tree baselink;{ tree tmp = TREE_TYPE (baselink); baselink = TREE_CHAIN (baselink); while (tmp) { /* @@ does not yet add previous base types. */ baselink = tree_cons (TREE_PURPOSE (tmp), TREE_VALUE (tmp), baselink); TREE_TYPE (baselink) = TREE_TYPE (tmp); tmp = TREE_CHAIN (tmp); } return baselink;}/* DEPTH-FIRST SEARCH ROUTINES. *//* Assign unique numbers to _CLASSTYPE members of the lattice spe
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -