⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cp-search.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Breadth-first and depth-first routines for   searching multiple-inheritance lattice for GNU C++.   Copyright (C) 1987, 1989, 1992 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, 675 Mass Ave, Cambridge, MA 02139, USA.  */#if 0/* Remove before release, should only appear for development and testing. */#define CHECK_convert_pointer_to_single_level#endif/* High-level class interface. */#include "config.h"#include "tree.h"#include <stdio.h>#include "cp-tree.h"#include "obstack.h"#include "flags.h"#define obstack_chunk_alloc xmalloc#define obstack_chunk_free freevoid init_search ();extern struct obstack *current_obstack;#include "stack.h"/* Obstack used for remembering decision points of breadth-first.  */static struct obstack search_obstack;/* Obstack used to bridge from one function context to another.  */static struct obstack bridge_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;  /* FIXME.  Doesn't obstack_grow, in the case when the current chunk has     insufficient space, move the base so that obstack_next_free is not     valid?  Perhaps obstack_copy should be used rather than obstack_grow,     and its returned value be used.  -- Raeburn   */  stack = (struct stack_level *) obstack_next_free (obstack);  obstack_grow (obstack, tp, 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;static int saw_first_vbase;/* 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, &tem, sizeof (tem));}/* Discard a level of search allocation.  */#define pop_search_level pop_stack_level/* 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;/* 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, &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) = 0;  ((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 (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 (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, 0, *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 a visibility 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;}/* Recursively search for a path from PARENT to BINFO.   If RVAL is > 0 and we succeed, update the BINFO_NEXT_BINFO   pointers.   If we find a distinct basetype that's not the one from BINFO,   return -2;   If we don't find any path, return 0.   If we encounter a virtual basetype on the path, return RVAL   and don't change any pointers after that point.  */static intrecursive_bounded_basetype_p (parent, binfo, rval, update_chain)     tree parent, binfo;     int rval;     int update_chain;{  tree binfos;  if (BINFO_TYPE (parent) == BINFO_TYPE (binfo))    {      if (tree_int_cst_equal (BINFO_OFFSET (parent), BINFO_OFFSET (binfo)))	return rval;      return -2;    }  if (TREE_VIA_VIRTUAL (binfo))    update_chain = 0;  if (binfos = BINFO_BASETYPES (binfo))    {      int i, nval;      for (i = 0; i < TREE_VEC_LENGTH (binfos); i++)	{	  nval = recursive_bounded_basetype_p (parent, TREE_VEC_ELT (binfos, i),					       rval, update_chain);	  if (nval < 0)	    return nval;	  if (nval > 0 && update_chain)	    BINFO_INHERITANCE_CHAIN (TREE_VEC_ELT (binfos, i)) = binfo;	}      return rval;    }  return 0;}/* Check whether the type given in BINFO is derived from PARENT.  If   it isn't, return 0.  If it is, but the derivation is MI-ambiguous   AND protect != 0, emit an error message and return error_mark_node.   Otherwise, if TYPE is derived from PARENT, return the actual base   information, unless a one of the protection violations below   occurs, in which case emit an error message and return error_mark_node.   The below should be worded better.  It may not be exactly what the code   does, but there should be a lose correlation.  If you understand the code   well, please try and make the comments below more readable.   If PROTECT is 1, then check if access to a public field of PARENT   would be private.   If PROTECT is 2, then check if the given type is derived from   PARENT via private visibility rules.   If PROTECT is 3, then immediately private baseclass is ok,   but deeper than that, check if private.  */treeget_binfo (parent, binfo, protect)     register tree parent, binfo;{  tree xtype, type;  tree otype;  int head = 0, tail = 0;  int is_private = 0;  tree rval = NULL_TREE;  int rval_private = 0;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -