📄 search.c
字号:
ambiguous lookup, we return NULL. If PROTECT is 1, we issue an error message. If PROTECT is 2, we return a TREE_LIST whose TREEE_TYPE is error_mark_node and whose TREE_VALUEs are the list of ambiguous candidates. WANT_TYPE is 1 when we should only return TYPE_DECLs, if no TYPE_DECL can be found return NULL_TREE. */treelookup_member (xbasetype, name, protect, want_type) register tree xbasetype, name; int protect, want_type;{ tree rval, rval_binfo = NULL_TREE; tree type = NULL_TREE, basetype_path = NULL_TREE; struct lookup_field_info lfi; /* 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. */ const char *errstr = 0; if (xbasetype == current_class_type && TYPE_BEING_DEFINED (xbasetype) && IDENTIFIER_CLASS_VALUE (name)) { tree field = IDENTIFIER_CLASS_VALUE (name); if (TREE_CODE (field) != FUNCTION_DECL && ! (want_type && TREE_CODE (field) != TYPE_DECL)) /* We're in the scope of this class, and the value has already been looked up. Just return the cached value. */ return field; } 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 (type); my_friendly_assert (BINFO_INHERITANCE_CHAIN (basetype_path) == NULL_TREE, 980827); } else my_friendly_abort (97); complete_type (type);#ifdef GATHER_STATISTICS n_calls_lookup_field++;#endif /* GATHER_STATISTICS */ bzero ((PTR) &lfi, sizeof (lfi)); lfi.type = type; lfi.name = name; lfi.want_type = want_type; bfs_walk (basetype_path, &lookup_field_r, &lookup_field_queue_p, &lfi); rval = lfi.rval; rval_binfo = lfi.rval_binfo; if (rval_binfo) type = BINFO_TYPE (rval_binfo); errstr = lfi.errstr; /* If we are not interested in ambiguities, don't report them; just return NULL_TREE. */ if (!protect && lfi.ambiguous) return NULL_TREE; if (protect == 2) { if (lfi.ambiguous) return lfi.ambiguous; else protect = 0; } /* [class.access] In the case of overloaded function names, access control is applied to the function selected by overloaded resolution. */ if (rval && protect && !is_overloaded_fn (rval) && !IS_SIGNATURE_POINTER (DECL_REAL_CONTEXT (rval)) && !IS_SIGNATURE_REFERENCE (DECL_REAL_CONTEXT (rval)) && !enforce_access (xbasetype, rval)) return error_mark_node; if (errstr && protect) { cp_error (errstr, name, type); if (lfi.ambiguous) print_candidates (lfi.ambiguous); rval = error_mark_node; } /* If the thing we found was found via the implicit typename extension, build the typename type. */ if (rval && lfi.from_dep_base_p && !DECL_CLASS_TEMPLATE_P (rval)) rval = TYPE_STUB_DECL (build_typename_type (BINFO_TYPE (basetype_path), name, name, TREE_TYPE (rval))); if (rval && is_overloaded_fn (rval)) { rval = scratch_tree_cons (basetype_path, rval, NULL_TREE); SET_BASELINK_P (rval); } return rval;}/* Like lookup_member, except that if we find a function member we return NULL_TREE. */treelookup_field (xbasetype, name, protect, want_type) register tree xbasetype, name; int protect, want_type;{ tree rval = lookup_member (xbasetype, name, protect, want_type); /* Ignore functions. */ if (rval && TREE_CODE (rval) == TREE_LIST) return NULL_TREE; return rval;}/* Like lookup_member, except that if we find a non-function member we return NULL_TREE. */treelookup_fnfields (xbasetype, name, protect) register tree xbasetype, name; int protect;{ tree rval = lookup_member (xbasetype, name, protect, /*want_type=*/0); /* Ignore non-functions. */ if (rval && TREE_CODE (rval) != TREE_LIST) return NULL_TREE; return rval;}/* 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. */intlookup_fnfields_1 (type, name) tree type, name;{ register tree method_vec = CLASS_TYPE_P (type) ? CLASSTYPE_METHOD_VEC (type) : NULL_TREE; 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 /* GATHER_STATISTICS */ /* Constructors are first... */ if (*methods && name == ctor_identifier) return 0; /* and destructors are second. */ if (*++methods && name == dtor_identifier) return 1; while (++methods != end && *methods) {#ifdef GATHER_STATISTICS n_outer_fields_searched++;#endif /* GATHER_STATISTICS */ if (DECL_NAME (OVL_CURRENT (*methods)) == name) break; } /* If we didn't find it, it might have been a template conversion operator. (Note that we don't look for this case above so that we will always find specializations first.) */ if ((methods == end || !*methods) && IDENTIFIER_TYPENAME_P (name)) { methods = &TREE_VEC_ELT (method_vec, 0) + 1; while (++methods != end && *methods) { tree method_name = DECL_NAME (OVL_CURRENT (*methods)); if (!IDENTIFIER_TYPENAME_P (method_name)) { /* Since all conversion operators come first, we know there is no such operator. */ methods = end; break; } else if (TREE_CODE (OVL_CURRENT (*methods)) == TEMPLATE_DECL) break; } } if (methods != end && *methods) return methods - &TREE_VEC_ELT (method_vec, 0); } return -1;}/* Walk the class hierarchy dominated by TYPE. FN is called for each type in the hierarchy, in a breadth-first preorder traversal. . If it ever returns a non-NULL value, that value is immediately returned and the walk is terminated. At each node FN, is passed a BINFO indicating the path from the curently visited base-class to TYPE. The TREE_CHAINs of the BINFOs may be used for scratch space; they are otherwise unused. Before each base-class is walked QFN is called. If the value returned is non-zero, the base-class is walked; otherwise it is not. If QFN is NULL, it is treated as a function which always returns 1. Both FN and QFN are passed the DATA whenever they are called. */static treebfs_walk (binfo, fn, qfn, data) tree binfo; tree (*fn) PROTO((tree, void *)); tree (*qfn) PROTO((tree, void *)); void *data;{ size_t head; size_t tail; tree rval = NULL_TREE; /* An array of the base classes of BINFO. These will be built up in breadth-first order, except where QFN prunes the search. */ varray_type bfs_bases; /* Start with enough room for ten base classes. That will be enough for most hierarchies. */ VARRAY_TREE_INIT (bfs_bases, 10, "search_stack"); /* Put the first type into the stack. */ VARRAY_TREE (bfs_bases, 0) = binfo; tail = 1; for (head = 0; head < tail; ++head) { int i; int n_baselinks; tree binfos; /* Pull the next type out of the queue. */ binfo = VARRAY_TREE (bfs_bases, head); /* If this is the one we're looking for, we're done. */ rval = (*fn) (binfo, data); if (rval) break; /* Queue up the base types. */ binfos = BINFO_BASETYPES (binfo); n_baselinks = binfos ? TREE_VEC_LENGTH (binfos): 0; for (i = 0; i < n_baselinks; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); if (qfn) base_binfo = (*qfn) (base_binfo, data); if (base_binfo) { if (tail == VARRAY_SIZE (bfs_bases)) VARRAY_GROW (bfs_bases, 2 * VARRAY_SIZE (bfs_bases)); VARRAY_TREE (bfs_bases, tail) = base_binfo; ++tail; } } } /* Clean up. */ VARRAY_FREE (bfs_bases); return rval;}/* Exactly like bfs_walk, except that a depth-first traversal is performed, and PREFN is called in preorder, while POSTFN is called in postorder. */static treedfs_walk_real (binfo, prefn, postfn, qfn, data) tree binfo; tree (*prefn) PROTO((tree, void *)); tree (*postfn) PROTO((tree, void *)); tree (*qfn) PROTO((tree, void *)); void *data;{ int i; int n_baselinks; tree binfos; tree rval = NULL_TREE; /* Call the pre-order walking function. */ if (prefn) { rval = (*prefn) (binfo, data); if (rval) return rval; } /* Process the basetypes. */ binfos = BINFO_BASETYPES (binfo); n_baselinks = binfos ? TREE_VEC_LENGTH (binfos): 0; for (i = 0; i < n_baselinks; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); if (qfn) base_binfo = (*qfn) (base_binfo, data); if (base_binfo) { rval = dfs_walk_real (base_binfo, prefn, postfn, qfn, data); if (rval) return rval; } } /* Call the post-order walking function. */ if (postfn) rval = (*postfn) (binfo, data); return rval;}/* Exactly like bfs_walk, except that a depth-first post-order traversal is performed. */treedfs_walk (binfo, fn, qfn, data) tree binfo; tree (*fn) PROTO((tree, void *)); tree (*qfn) PROTO((tree, void *)); void *data;{ return dfs_walk_real (binfo, 0, fn, qfn, data);}struct gvnt_info { /* The name of the function we are looking for. */ tree name; /* The overloaded functions we have found. */ tree fields;};/* Called from get_virtuals_named_this via bfs_walk. */static treeget_virtuals_named_this_r (binfo, data) tree binfo; void *data;{ struct gvnt_info *gvnti = (struct gvnt_info *) data; tree type = BINFO_TYPE (binfo); int idx; idx = lookup_fnfields_here (BINFO_TYPE (binfo), gvnti->name); if (idx >= 0) gvnti->fields = scratch_tree_cons (binfo, TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx), gvnti->fields); return NULL_TREE;}/* Return the virtual functions with the indicated NAME in the type indicated by BINFO. The result is a TREE_LIST whose TREE_PURPOSE indicates the base class from which the TREE_VALUE (an OVERLOAD or just a FUNCTION_DECL) originated. */static treeget_virtuals_named_this (binfo, name) tree binfo; tree name;{ struct gvnt_info gvnti; tree fields; gvnti.name = name; gvnti.fields = NULL_TREE; bfs_walk (binfo, get_virtuals_named_this_r, 0, &gvnti); /* Get to the function decls, and return the first virtual function with this name, if there is one. */ for (fields = gvnti.fields; fields; fields = next_baselink (fields)) { tree fndecl; for (fndecl = TREE_VALUE (fields); fndecl; fndecl = OVL_NEXT (fndecl)) if (DECL_VINDEX (OVL_CURRENT (fndecl))) return fields; } return NULL_TREE;}static treeget_virtual_destructor (binfo, data) tree binfo; void *data ATTRIBUTE_UNUSED;{ tree type = BINFO_TYPE (binfo); 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 treetree_has_any_destructor_p (binfo, data) tree binfo; void *data ATTRIBUTE_UNUSED;{ tree type = BINFO_TYPE (binfo); return TYPE_NEEDS_DESTRUCTOR (type) ? binfo : NULL_TREE;}/* Returns > 0 if a function with type DRETTYPE overriding a function with type BRETTYPE is covariant, as defined in [class.virtual]. Returns 1 if trivial covariance, 2 if non-trivial (requiring runtime adjustment), or -1 if pedantically invalid covariance. */static intcovariant_return_p (brettype, drettype) tree brettype, drettype;{ tree binfo; if (TREE_CODE (brettype) == FUNCTION_DECL || TREE_CODE (brettype) == THUNK_DECL)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -