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

📄 class.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Functions related to building classes and their related objects.   Copyright (C) 1987, 1992, 1993, 1994, 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 "flags.h"#include "rtl.h"#include "output.h"#include "obstack.h"#define obstack_chunk_alloc xmalloc#define obstack_chunk_free freeextern struct obstack permanent_obstack;/* This is how we tell when two virtual member functions are really the   same. */#define SAME_FN(FN1DECL, FN2DECL) (DECL_ASSEMBLER_NAME (FN1DECL) == DECL_ASSEMBLER_NAME (FN2DECL))extern void set_class_shadows PROTO ((tree));/* Way of stacking class types.  */static tree *current_class_base, *current_class_stack;static int current_class_stacksize;int current_class_depth;struct class_level{  /* The previous class level.  */  struct class_level *level_chain;  /* The class instance variable, as a PARM_DECL.  */  tree decl;  /* The class instance variable, as an object.  */  tree object;  /* The virtual function table pointer     for the class instance variable.  */  tree vtable_decl;  /* Name of the current class.  */  tree name;  /* Type of the current class.  */  tree type;  /* Flags for this class level.  */  int this_is_variable;  int memoized_lookups;  int save_memoized;  int unused;};tree current_class_decl, C_C_D;	/* PARM_DECL: the class instance variable *//* The following two can be derived from the previous one */tree current_class_name;	/* IDENTIFIER_NODE: name of current class */tree current_class_type;	/* _TYPE: the type of the current class */tree previous_class_type;	/* _TYPE: the previous type that was a class */tree previous_class_values;		/* TREE_LIST: copy of the class_shadowed list				   when leaving an outermost class scope.  */static tree get_vfield_name PROTO((tree));tree the_null_vtable_entry;/* Way of stacking language names.  */tree *current_lang_base, *current_lang_stack;int current_lang_stacksize;/* Names of languages we recognize.  */tree lang_name_c, lang_name_cplusplus;tree current_lang_name;char *dont_allow_type_definitions;/* When layout out an aggregate type, the size of the   basetypes (virtual and non-virtual) is passed to layout_record   via this node.  */static tree base_layout_decl;/* Variables shared between class.c and call.c.  */int n_vtables = 0;int n_vtable_entries = 0;int n_vtable_searches = 0;int n_vtable_elems = 0;int n_convert_harshness = 0;int n_compute_conversion_costs = 0;int n_build_method_call = 0;int n_inner_fields_searched = 0;/* Virtual baseclass things.  */treebuild_vbase_pointer (exp, type)     tree exp, type;{  char *name;  name = (char *) alloca (TYPE_NAME_LENGTH (type) + sizeof (VBASE_NAME) + 1);  sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (type));  return build_component_ref (exp, get_identifier (name), 0, 0);}/* Is the type of the EXPR, the complete type of the object?   If we are going to be wrong, we must be conservative, and return 0. */intcomplete_type_p (expr)     tree expr;{  tree type = TYPE_MAIN_VARIANT (TREE_TYPE (expr));  while (1)    {      switch (TREE_CODE (expr))	{	case SAVE_EXPR:	case INDIRECT_REF:	case ADDR_EXPR:	case NOP_EXPR:	case CONVERT_EXPR:	  expr = TREE_OPERAND (expr, 0);	  continue;	case CALL_EXPR: 	  if (! TREE_HAS_CONSTRUCTOR (expr))	    break;	  /* fall through... */	case VAR_DECL:	case FIELD_DECL:	  if (TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE	      && IS_AGGR_TYPE (TREE_TYPE (TREE_TYPE (expr)))	      && TYPE_MAIN_VARIANT (TREE_TYPE (expr)) == type)	    return 1;	  /* fall through... */	case TARGET_EXPR:	case PARM_DECL:	  if (IS_AGGR_TYPE (TREE_TYPE (expr))	      && TYPE_MAIN_VARIANT (TREE_TYPE (expr)) == type)	    return 1;	  /* fall through... */	case PLUS_EXPR:	default:	  break;	}      break;    }  return 0;}/* Build multi-level access to EXPR using hierarchy path PATH.   CODE is PLUS_EXPR if we are going with the grain,   and MINUS_EXPR if we are not (in which case, we cannot traverse   virtual baseclass links).   TYPE is the type we want this path to have on exit.   ALIAS_THIS is non-zero if EXPR in an expression involving `this'.  */treebuild_vbase_path (code, type, expr, path, alias_this)     enum tree_code code;     tree type, expr, path;     int alias_this;{  register int changed = 0;  tree last = NULL_TREE, last_virtual = NULL_TREE;  int nonnull = 0;  int fixed_type_p = resolves_to_fixed_type_p (expr, &nonnull);  tree null_expr = 0, nonnull_expr;  tree basetype;  tree offset = integer_zero_node;  if (nonnull == 0 && (alias_this && flag_this_is_variable <= 0))    nonnull = 1;  /* We need additional logic to convert back to the unconverted type     (the static type of the complete object), and then convert back     to the type we want.  Until that is done, or until we can     recognize when that is, we cannot do the short cut logic. (mrs) */  /* Do this, until we can undo any previous conversions.  See net35.C     for a testcase. */  fixed_type_p = complete_type_p (expr);  if (!fixed_type_p && TREE_SIDE_EFFECTS (expr))    expr = save_expr (expr);  nonnull_expr = expr;  if (BINFO_INHERITANCE_CHAIN (path))    {      tree reverse_path = NULL_TREE;      while (path)	{	  tree r = copy_node (path);	  BINFO_INHERITANCE_CHAIN (r) = reverse_path;	  reverse_path = r;	  path = BINFO_INHERITANCE_CHAIN (path);	}      path = reverse_path;    }  basetype = BINFO_TYPE (path);  while (path)    {      if (TREE_VIA_VIRTUAL (path))	{	  last_virtual = BINFO_TYPE (path);	  if (code == PLUS_EXPR)	    {	      changed = ! fixed_type_p;	      if (changed)		{		  extern int flag_assume_nonnull_objects;		  tree ind;		  /* We already check for ambiguous things in the caller, just		     find a path. */		  if (last)		    {		      tree binfo = get_binfo (last, TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (nonnull_expr))), 0);		      nonnull_expr = convert_pointer_to_real (binfo, nonnull_expr);		    }		  ind = build_indirect_ref (nonnull_expr, NULL_PTR);		  nonnull_expr = build_vbase_pointer (ind, last_virtual);		  if (nonnull == 0		      && (TREE_CODE (type) == POINTER_TYPE			  || !flag_assume_nonnull_objects)		      && null_expr == NULL_TREE)		    {		      null_expr = build1 (NOP_EXPR, build_pointer_type (last_virtual), integer_zero_node);		      expr = build (COND_EXPR, build_pointer_type (last_virtual),				    build (EQ_EXPR, boolean_type_node, expr,					   integer_zero_node),				    null_expr, nonnull_expr);		    }		}	      /* else we'll figure out the offset below.  */	      /* Happens in the case of parse errors.  */	      if (nonnull_expr == error_mark_node)		return error_mark_node;	    }	  else	    {	      cp_error ("cannot cast up from virtual baseclass `%T'",			  last_virtual);	      return error_mark_node;	    }	}      last = path;      path = BINFO_INHERITANCE_CHAIN (path);    }  /* LAST is now the last basetype assoc on the path.  */  /* A pointer to a virtual base member of a non-null object     is non-null.  Therefore, we only need to test for zeroness once.     Make EXPR the canonical expression to deal with here.  */  if (null_expr)    {      TREE_OPERAND (expr, 2) = nonnull_expr;      TREE_TYPE (TREE_OPERAND (expr, 1)) = TREE_TYPE (nonnull_expr);    }  else    expr = nonnull_expr;  /* If we go through any virtual base pointers, make sure that     casts to BASETYPE from the last virtual base class use     the right value for BASETYPE.  */  if (changed)    {      tree intype = TREE_TYPE (TREE_TYPE (expr));      if (TYPE_MAIN_VARIANT (intype) != BINFO_TYPE (last))	{	  tree binfo = get_binfo (last, TYPE_MAIN_VARIANT (intype), 0);	  offset = BINFO_OFFSET (binfo);	}    }  else    {      if (last_virtual)	{	  offset = BINFO_OFFSET (binfo_member (last_virtual,					       CLASSTYPE_VBASECLASSES (basetype)));	  offset = size_binop (PLUS_EXPR, offset, BINFO_OFFSET (last));	}      else	offset = BINFO_OFFSET (last);    }  if (TREE_INT_CST_LOW (offset))    {      /* Bash types to make the backend happy.  */      offset = convert (type, offset);      expr = build1 (NOP_EXPR, type, expr);      /* For multiple inheritance: if `this' can be set by any	 function, then it could be 0 on entry to any function.	 Preserve such zeroness here.  Otherwise, only in the	 case of constructors need we worry, and in those cases,	 it will be zero, or initialized to some valid value to	 which we may add.  */      if (nonnull == 0)	{	  if (null_expr)	    TREE_TYPE (null_expr) = type;	  else	    null_expr = build1 (NOP_EXPR, type, integer_zero_node);	  if (TREE_SIDE_EFFECTS (expr))	    expr = save_expr (expr);	  return build (COND_EXPR, type,			build (EQ_EXPR, boolean_type_node, expr, integer_zero_node),			null_expr,			build (code, type, expr, offset));	}      else return build (code, type, expr, offset);    }  /* Cannot change the TREE_TYPE of a NOP_EXPR here, since it may     be used multiple times in initialization of multiple inheritance.  */  if (null_expr)    {      TREE_TYPE (expr) = type;      return expr;    }  else    return build1 (NOP_EXPR, type, expr);}/* Virtual function things.  *//* Virtual functions to be dealt with after laying out our base   classes.  We do all overrides after we layout virtual base classes.   */static tree pending_hard_virtuals;static int doing_hard_virtuals;/* Build an entry in the virtual function table.   DELTA is the offset for the `this' pointer.   PFN is an ADDR_EXPR containing a pointer to the virtual function.   Note that the index (DELTA2) in the virtual function table   is always 0.  */treebuild_vtable_entry (delta, pfn)     tree delta, pfn;{  if (flag_vtable_thunks)    {      HOST_WIDE_INT idelta = TREE_INT_CST_LOW (delta);      extern tree make_thunk ();      if (idelta)	{	  pfn = build1 (ADDR_EXPR, vtable_entry_type,			make_thunk (pfn, idelta));	  TREE_READONLY (pfn) = 1;	  TREE_CONSTANT (pfn) = 1;	}#ifdef GATHER_STATISTICS      n_vtable_entries += 1;#endif      return pfn;    }  else    {      extern int flag_huge_objects;      tree elems = tree_cons (NULL_TREE, delta,			      tree_cons (NULL_TREE, integer_zero_node,					 build_tree_list (NULL_TREE, pfn)));      tree entry = build (CONSTRUCTOR, vtable_entry_type, NULL_TREE, elems);      /* DELTA is constructed by `size_int', which means it may be an	 unsigned quantity on some platforms.  Therefore, we cannot use	 `int_fits_type_p', because when DELTA is really negative,	 `force_fit_type' will make it look like a very large number.  */      if ((TREE_INT_CST_LOW (TYPE_MAX_VALUE (delta_type_node))	   < TREE_INT_CST_LOW (delta))	  || (TREE_INT_CST_LOW (delta)	      < TREE_INT_CST_LOW (TYPE_MIN_VALUE (delta_type_node))))	if (flag_huge_objects)	  sorry ("object size exceeds built-in limit for virtual function table implementation");	else	  sorry ("object size exceeds normal limit for virtual function table implementation, recompile all source and use -fhuge-objects");      TREE_CONSTANT (entry) = 1;      TREE_STATIC (entry) = 1;      TREE_READONLY (entry) = 1;#ifdef GATHER_STATISTICS      n_vtable_entries += 1;#endif      return entry;    }}/* Given an object INSTANCE, return an expression which yields the   virtual function corresponding to INDEX.  There are many special   cases for INSTANCE which we take care of here, mainly to avoid   creating extra tree nodes when we don't have to.  */

⌨️ 快捷键说明

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