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

📄 search.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Breadth-first and depth-first routines for   searching multiple-inheritance lattice for GNU C++.   Copyright (C) 1987, 89, 92-96, 1997 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 freeextern 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 void clear_memoized_cache PROTO((void));static tree make_memoized_table_entry PROTO((tree, tree, int));static tree get_abstract_virtuals_1 PROTO((tree, int, tree));static tree get_vbase_1 PROTO((tree, tree, unsigned int *));static tree convert_pointer_to_vbase PROTO((tree, tree));static tree lookup_field_1 PROTO((tree, tree));static tree convert_pointer_to_single_level PROTO((tree, tree));static int lookup_fnfields_1 PROTO((tree, tree));static int lookup_fnfields_here PROTO((tree, tree));static int is_subobject_of_p PROTO((tree, tree));static int hides PROTO((tree, tree));static tree virtual_context PROTO((tree, tree, tree));static tree get_template_base_recursive	PROTO((tree, tree, tree, int));static void dfs_walk PROTO((tree, void (*) (tree), int (*) (tree)));static void envelope_add_decl PROTO((tree, tree, tree *));static int get_base_distance_recursive	PROTO((tree, int, int, int, int *, tree *, tree, tree *,	       int, int *, int, int));static void expand_upcast_fixups 	PROTO((tree, tree, tree, tree, tree, tree, tree *));static void fixup_virtual_upcast_offsets	PROTO((tree, tree, int, int, tree, tree, tree, tree,	       tree *));static int markedp PROTO((tree));static int unmarkedp PROTO((tree));static int numberedp PROTO((tree));static int unnumberedp PROTO((tree));static int marked_vtable_pathp PROTO((tree));static int unmarked_vtable_pathp PROTO((tree));static int marked_new_vtablep PROTO((tree));static int unmarked_new_vtablep PROTO((tree));static int dfs_debug_unmarkedp PROTO((tree));static void dfs_number PROTO((tree));static void dfs_unnumber PROTO((tree));static void dfs_debug_mark PROTO((tree));static void dfs_find_vbases PROTO((tree));static void dfs_clear_vbase_slots PROTO((tree));static void dfs_unmark PROTO((tree));static void dfs_init_vbase_pointers PROTO((tree));static void dfs_get_vbase_types PROTO((tree));static void dfs_record_inheritance PROTO((tree));static void dfs_pushdecls PROTO((tree));static void dfs_compress_decls PROTO((tree));static void dfs_unuse_fields PROTO((tree));static void add_conversions PROTO((tree));static tree get_virtuals_named_this PROTO((tree));static tree get_virtual_destructor PROTO((tree, int));static int tree_has_any_destructor_p PROTO((tree, int));static struct search_level *push_search_level	PROTO((struct stack_level *, struct obstack *));static struct search_level *pop_search_level	PROTO((struct stack_level *));static struct type_level *push_type_level	PROTO((struct stack_level *, struct obstack *));static struct type_level *pop_type_level	PROTO((struct type_level *));static tree my_tree_cons PROTO((tree, tree, tree));static tree my_build_string PROTO((char *));static struct memoized_entry * my_new_memoized_entry	PROTO((struct memoized_entry *));static HOST_WIDE_INT breadth_first_search	PROTO((tree, int (*) (tree, int), int (*) (tree, int)));static tree vbase_types;static tree vbase_decl_ptr_intermediate, vbase_decl_ptr;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;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];#ifdef GATHER_STATISTICSstatic 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;#endif /* GATHER_STATISTICS *//* 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;}/* Clears the deferred pop from pop_memoized_context, if any.  */static voidclear_memoized_cache (){  if (prev_type_stack)    {      type_stack = pop_type_level (prev_type_stack);      prev_type_memoized = 0;      prev_type_stack = 0;    }}/* Make an entry in the memoized table for type TYPE   that the entry for NAME is FIELD.  */static treemake_memoized_table_entry (type, name, function_p)     tree type, name;     int function_p;{  int idx = MEMOIZED_HASH_FN (name);  tree entry, *prev_entry;  /* Since we allocate from the type_obstack, we must pop any deferred     levels.  */   clear_memoized_cache ();  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), idx);  else    prev_entry = &MEMOIZED_FIELDS (CLASSTYPE_MTABLE_ENTRY (type), idx);  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 /* GATHER_STATISTICS */	  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.  */      clear_memoized_cache ();    }  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]);      /* If there was a deferred pop, we need to pop it now.  */      clear_memoized_cache ();      prev_type_stack = type_stack;      prev_type_memoized = type_stack->type;    }

⌨️ 快捷键说明

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