📄 search.c
字号:
/* Breadth-first and depth-first routines for searching multiple-inheritance lattice for GNU C++. Copyright (C) 1987, 89, 92, 93, 94, 1995 Free Software Foundation, Inc. Contributed by Michael Tiemann (tiemann@cygnus.com)This file is part of GNU CC.GNU CC is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2, or (at your option)any later version.GNU CC is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU CC; see the file COPYING. If not, write tothe Free Software Foundation, 59 Temple Place - Suite 330,Boston, MA 02111-1307, USA. *//* High-level class interface. */#include "config.h"#include "tree.h"#include <stdio.h>#include "cp-tree.h"#include "obstack.h"#include "flags.h"#include "rtl.h"#include "output.h"#define obstack_chunk_alloc xmalloc#define obstack_chunk_free freevoid init_search ();extern struct obstack *current_obstack;extern tree abort_fndecl;#include "stack.h"/* Obstack used for remembering decision points of breadth-first. */static struct obstack search_obstack;/* Methods for pushing and popping objects to and from obstacks. */struct stack_level *push_stack_level (obstack, tp, size) struct obstack *obstack; char *tp; /* Sony NewsOS 5.0 compiler doesn't like void * here. */ int size;{ struct stack_level *stack; obstack_grow (obstack, tp, size); stack = (struct stack_level *) ((char*)obstack_next_free (obstack) - size); obstack_finish (obstack); stack->obstack = obstack; stack->first = (tree *) obstack_base (obstack); stack->limit = obstack_room (obstack) / sizeof (tree *); return stack;}struct stack_level *pop_stack_level (stack) struct stack_level *stack;{ struct stack_level *tem = stack; struct obstack *obstack = tem->obstack; stack = tem->prev; obstack_free (obstack, tem); return stack;}#define search_level stack_levelstatic struct search_level *search_stack;static tree lookup_field_1 ();static int lookup_fnfields_1 ();static void dfs_walk ();static int markedp ();static void dfs_unmark ();static void dfs_init_vbase_pointers ();static tree vbase_types;static tree vbase_decl, vbase_decl_ptr;static tree vbase_decl_ptr_intermediate;static tree vbase_init_result;/* Allocate a level of searching. */static struct search_level *push_search_level (stack, obstack) struct stack_level *stack; struct obstack *obstack;{ struct search_level tem; tem.prev = stack; return push_stack_level (obstack, (char *)&tem, sizeof (tem));}/* Discard a level of search allocation. */static struct search_level *pop_search_level (obstack) struct stack_level *obstack;{ register struct search_level *stack = pop_stack_level (obstack); return stack;}/* Search memoization. */struct type_level{ struct stack_level base; /* First object allocated in obstack of entries. */ char *entries; /* Number of types memoized in this context. */ int len; /* Type being memoized; save this if we are saving memoized contexts. */ tree type;};/* Obstack used for memoizing member and member function lookup. */static struct obstack type_obstack, type_obstack_entries;static struct type_level *type_stack;static tree _vptr_name;/* Make things that look like tree nodes, but allocate them on type_obstack_entries. */static int my_tree_node_counter;static tree my_tree_cons (), my_build_string ();extern int flag_memoize_lookups, flag_save_memoized_contexts;/* Variables for gathering statistics. */static int my_memoized_entry_counter;static int memoized_fast_finds[2], memoized_adds[2], memoized_fast_rejects[2];static int memoized_fields_searched[2];static int n_fields_searched;static int n_calls_lookup_field, n_calls_lookup_field_1;static int n_calls_lookup_fnfields, n_calls_lookup_fnfields_1;static int n_calls_get_base_type;static int n_outer_fields_searched;static int n_contexts_saved;/* Local variables to help save memoization contexts. */static tree prev_type_memoized;static struct type_level *prev_type_stack;/* This list is used by push_class_decls to know what decls need to be pushed into class scope. */static tree closed_envelopes = NULL_TREE;/* Allocate a level of type memoization context. */static struct type_level *push_type_level (stack, obstack) struct stack_level *stack; struct obstack *obstack;{ struct type_level tem; tem.base.prev = stack; obstack_finish (&type_obstack_entries); tem.entries = (char *) obstack_base (&type_obstack_entries); tem.len = 0; tem.type = NULL_TREE; return (struct type_level *)push_stack_level (obstack, (char *)&tem, sizeof (tem));}/* Discard a level of type memoization context. */static struct type_level *pop_type_level (stack) struct type_level *stack;{ obstack_free (&type_obstack_entries, stack->entries); return (struct type_level *)pop_stack_level ((struct stack_level *)stack);}/* Make something that looks like a TREE_LIST, but do it on the type_obstack_entries obstack. */static treemy_tree_cons (purpose, value, chain) tree purpose, value, chain;{ tree p = (tree)obstack_alloc (&type_obstack_entries, sizeof (struct tree_list)); ++my_tree_node_counter; TREE_TYPE (p) = NULL_TREE; ((HOST_WIDE_INT *)p)[3] = 0; TREE_SET_CODE (p, TREE_LIST); TREE_PURPOSE (p) = purpose; TREE_VALUE (p) = value; TREE_CHAIN (p) = chain; return p;}static treemy_build_string (str) char *str;{ tree p = (tree)obstack_alloc (&type_obstack_entries, sizeof (struct tree_string)); ++my_tree_node_counter; TREE_TYPE (p) = 0; ((int *)p)[3] = 0; TREE_SET_CODE (p, STRING_CST); TREE_STRING_POINTER (p) = str; TREE_STRING_LENGTH (p) = strlen (str); return p;}/* Memoizing machinery to make searches for multiple inheritance reasonably efficient. */#define MEMOIZE_HASHSIZE 8typedef struct memoized_entry{ struct memoized_entry *chain; int uid; tree data_members[MEMOIZE_HASHSIZE]; tree function_members[MEMOIZE_HASHSIZE];} *ME;#define MEMOIZED_CHAIN(ENTRY) (((ME)ENTRY)->chain)#define MEMOIZED_UID(ENTRY) (((ME)ENTRY)->uid)#define MEMOIZED_FIELDS(ENTRY,INDEX) (((ME)ENTRY)->data_members[INDEX])#define MEMOIZED_FNFIELDS(ENTRY,INDEX) (((ME)ENTRY)->function_members[INDEX])/* The following is probably a lousy hash function. */#define MEMOIZED_HASH_FN(NODE) (((long)(NODE)>>4)&(MEMOIZE_HASHSIZE - 1))static struct memoized_entry *my_new_memoized_entry (chain) struct memoized_entry *chain;{ struct memoized_entry *p = (struct memoized_entry *)obstack_alloc (&type_obstack_entries, sizeof (struct memoized_entry)); bzero ((char *) p, sizeof (struct memoized_entry)); MEMOIZED_CHAIN (p) = chain; MEMOIZED_UID (p) = ++my_memoized_entry_counter; return p;}/* Make an entry in the memoized table for type TYPE that the entry for NAME is FIELD. */treemake_memoized_table_entry (type, name, function_p) tree type, name; int function_p;{ int index = MEMOIZED_HASH_FN (name); tree entry, *prev_entry; memoized_adds[function_p] += 1; if (CLASSTYPE_MTABLE_ENTRY (type) == 0) { obstack_ptr_grow (&type_obstack, type); obstack_blank (&type_obstack, sizeof (struct memoized_entry *)); CLASSTYPE_MTABLE_ENTRY (type) = (char *)my_new_memoized_entry ((struct memoized_entry *)0); type_stack->len++; if (type_stack->len * 2 >= type_stack->base.limit) my_friendly_abort (88); } if (function_p) prev_entry = &MEMOIZED_FNFIELDS (CLASSTYPE_MTABLE_ENTRY (type), index); else prev_entry = &MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), index); entry = my_tree_cons (name, NULL_TREE, *prev_entry); *prev_entry = entry; /* Don't know the error message to give yet. */ TREE_TYPE (entry) = error_mark_node; return entry;}/* When a new function or class context is entered, we build a table of types which have been searched for members. The table is an array (obstack) of types. When a type is entered into the obstack, its CLASSTYPE_MTABLE_ENTRY field is set to point to a new record, of type struct memoized_entry. A non-NULL TREE_TYPE of the entry contains an access control error message. The slots for the data members are arrays of tree nodes. These tree nodes are lists, with the TREE_PURPOSE of this list the known member name, and the TREE_VALUE as the FIELD_DECL for the member. For member functions, the TREE_PURPOSE is again the name of the member functions for that class, and the TREE_VALUE of the list is a pairs whose TREE_PURPOSE is a member functions of this name, and whose TREE_VALUE is a list of known argument lists this member function has been called with. The TREE_TYPE of the pair, if non-NULL, is an error message to print. *//* Tell search machinery that we are entering a new context, and to update tables appropriately. TYPE is the type of the context we are entering, which can be NULL_TREE if we are not in a class's scope. USE_OLD, if nonzero tries to use previous context. */voidpush_memoized_context (type, use_old) tree type; int use_old;{ int len; tree *tem; if (prev_type_stack) { if (use_old && prev_type_memoized == type) {#ifdef GATHER_STATISTICS n_contexts_saved++;#endif type_stack = prev_type_stack; prev_type_stack = 0; tem = &type_stack->base.first[0]; len = type_stack->len; while (len--) CLASSTYPE_MTABLE_ENTRY (tem[len*2]) = (char *)tem[len*2+1]; return; } /* Otherwise, need to pop old stack here. */ type_stack = pop_type_level (prev_type_stack); prev_type_memoized = 0; prev_type_stack = 0; } type_stack = push_type_level ((struct stack_level *)type_stack, &type_obstack); type_stack->type = type;}/* Tell search machinery that we have left a context. We do not currently save these contexts for later use. If we wanted to, we could not use pop_search_level, since poping that level allows the data we have collected to be clobbered; a stack of obstacks would be needed. */voidpop_memoized_context (use_old) int use_old;{ int len; tree *tem = &type_stack->base.first[0]; if (! flag_save_memoized_contexts) use_old = 0; else if (use_old) { len = type_stack->len; while (len--) tem[len*2+1] = (tree)CLASSTYPE_MTABLE_ENTRY (tem[len*2]); prev_type_stack = type_stack; prev_type_memoized = type_stack->type; } if (flag_memoize_lookups) { len = type_stack->len; while (len--) CLASSTYPE_MTABLE_ENTRY (tem[len*2]) = (char *)MEMOIZED_CHAIN (CLASSTYPE_MTABLE_ENTRY (tem[len*2])); } if (! use_old) type_stack = pop_type_level (type_stack); else type_stack = (struct type_level *)type_stack->base.prev;}/* Get a virtual binfo that is found inside BINFO's hierarchy that is the same type as the type given in PARENT. To be optimal, we want the first one that is found by going through the least number of virtual bases. DEPTH should be NULL_PTR. */static treeget_vbase (parent, binfo, depth) tree parent, binfo; unsigned int *depth;{ tree binfos; int i, n_baselinks; tree rval = NULL_TREE; if (depth == 0) { unsigned int d = (unsigned int)-1; return get_vbase (parent, binfo, &d); } if (BINFO_TYPE (binfo) == parent && TREE_VIA_VIRTUAL (binfo)) { *depth = 0; return binfo; } *depth = *depth - 1; binfos = BINFO_BASETYPES (binfo); n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0; /* Process base types. */ for (i = 0; i < n_baselinks; i++) { tree base_binfo = TREE_VEC_ELT (binfos, i); tree nrval; if (*depth == 0) break; nrval = get_vbase (parent, base_binfo, depth); if (nrval) rval = nrval; } *depth = *depth+1; return rval;}/* Convert EXPR to a virtual base class of type TYPE. We know that EXPR is a non-null POINTER_TYPE to RECORD_TYPE. We also know that the type of what expr points to has a virtual base of type TYPE. */treeconvert_pointer_to_vbase (type, expr) tree type; tree expr;{ tree vb = get_vbase (type, TYPE_BINFO (TREE_TYPE (TREE_TYPE (expr))), NULL_PTR); return convert_pointer_to_real (vb, expr);}/* This is the newer recursive depth first search routine. */#if 0 /* unused *//* Return non-zero if PARENT is directly derived from TYPE. By directly we mean it's only one step up the inheritance lattice. We check this by walking horizontally across the types that TYPE directly inherits from, to see if PARENT is among them. This is used by get_binfo and by compute_access. */static intimmediately_derived (parent, type) tree parent, type;{ if (TYPE_BINFO (type))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -