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

📄 init.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Handle initialization things in 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 "rtl.h"#include "cp-tree.h"#include "flags.h"#include "output.h"#undef NULL#define NULL 0/* In C++, structures with well-defined constructors are initialized by   those constructors, unasked.  CURRENT_BASE_INIT_LIST   holds a list of stmts for a BASE_INIT term in the grammar.   This list has one element for each base class which must be   initialized.  The list elements are [basename, init], with   type basetype.  This allows the possibly anachronistic form   (assuming d : a, b, c) "d (int a) : c(a+5), b (a-4), a (a+3)"   where each successive term can be handed down the constructor   line.  Perhaps this was not intended.  */tree current_base_init_list, current_member_init_list;void emit_base_init ();void check_base_init ();static void expand_aggr_vbase_init ();void expand_member_init ();void expand_aggr_init ();static void expand_aggr_init_1 ();static void expand_recursive_init_1 ();static void expand_recursive_init ();static void expand_virtual_init PROTO((tree, tree));tree expand_vec_init ();static void add_friend (), add_friends ();/* Cache _builtin_new and _builtin_delete exprs.  */static tree BIN, BID, BIVN, BIVD;/* Cache the identifier nodes for the two magic field of a new cookie.  */static tree nc_nelts_field_id;#if 0static tree nc_ptr_2comp_field_id;#endifstatic tree minus_one;/* Set up local variable for this file.  MUST BE CALLED AFTER   INIT_DECL_PROCESSING.  */tree BI_header_type, BI_header_size;void init_init_processing (){  tree fields[1];  /* Define implicit `operator new' and `operator delete' functions.  */  BIN = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) NEW_EXPR])));  TREE_USED (TREE_OPERAND (BIN, 0)) = 0;  BID = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) DELETE_EXPR])));  TREE_USED (TREE_OPERAND (BID, 0)) = 0;  BIVN = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) VEC_NEW_EXPR])));  TREE_USED (TREE_OPERAND (BIVN, 0)) = 0;  BIVD = default_conversion (get_first_fn (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) VEC_DELETE_EXPR])));  TREE_USED (TREE_OPERAND (BIVD, 0)) = 0;  minus_one = build_int_2 (-1, -1);  /* Define the structure that holds header information for     arrays allocated via operator new.  */  BI_header_type = make_lang_type (RECORD_TYPE);  nc_nelts_field_id = get_identifier ("nelts");  fields[0] = build_lang_field_decl (FIELD_DECL, nc_nelts_field_id, sizetype);  finish_builtin_type (BI_header_type, "__new_cookie", fields,		       0, double_type_node);  BI_header_size = size_in_bytes (BI_header_type);}/* Subroutine of emit_base_init.  For BINFO, initialize all the   virtual function table pointers, except those that come from   virtual base classes.  Initialize binfo's vtable pointer, if   INIT_SELF is true.  CAN_ELIDE is true when we know that all virtual   function table pointers in all bases have been initialized already,   probably because their constructors have just be run.  ADDR is the   pointer to the object whos vtables we are going to initialize.   REAL_BINFO is usually the same as BINFO, except when addr is not of   pointer to the type of the real derived type that we want to   initialize for.  This is the case when addr is a pointer to a sub   object of a complete object, and we only want to do part of the   complete object's initialization of vtable pointers.  This is done   for all virtual table pointers in virtual base classes.  REAL_BINFO   is used to find the BINFO_VTABLE that we initialize with.  BINFO is   used for conversions of addr to subobjects.   BINFO_TYPE (real_binfo) must be BINFO_TYPE (binfo).   Relies upon binfo being inside TYPE_BINFO (TREE_TYPE (TREE_TYPE   (addr))).  */voidexpand_direct_vtbls_init (real_binfo, binfo, init_self, can_elide, addr)     tree real_binfo, binfo, addr;     int init_self, can_elide;{  tree real_binfos = BINFO_BASETYPES (real_binfo);  tree binfos = BINFO_BASETYPES (binfo);  int i, n_baselinks = real_binfos ? TREE_VEC_LENGTH (real_binfos) : 0;  for (i = 0; i < n_baselinks; i++)    {      tree real_base_binfo = TREE_VEC_ELT (real_binfos, i);      tree base_binfo = TREE_VEC_ELT (binfos, i);      int is_not_base_vtable =	i != CLASSTYPE_VFIELD_PARENT (BINFO_TYPE (real_binfo));      if (! TREE_VIA_VIRTUAL (real_base_binfo))	expand_direct_vtbls_init (real_base_binfo, base_binfo,				  is_not_base_vtable, can_elide, addr);    }#if 0  /* Before turning this on, make sure it is correct.  */  if (can_elide && ! BINFO_MODIFIED (binfo))    return;#endif  /* Should we use something besides CLASSTYPE_VFIELDS? */  if (init_self && CLASSTYPE_VFIELDS (BINFO_TYPE (real_binfo)))    {      tree base_ptr = convert_pointer_to_real (binfo, addr);      expand_virtual_init (real_binfo, base_ptr);    }}/* 348 - 351 *//* Subroutine of emit_base_init.  */static voidperform_member_init (member, name, init, explicit, protect_list)     tree member, name, init, *protect_list;     int explicit;{  tree decl;  tree type = TREE_TYPE (member);  if (TYPE_NEEDS_CONSTRUCTING (type)      || (init && TYPE_HAS_CONSTRUCTOR (type)))    {      /* Since `init' is already a TREE_LIST on the current_member_init_list,	 only build it into one if we aren't already a list.  */      if (init != NULL_TREE && TREE_CODE (init) != TREE_LIST)	init = build_tree_list (NULL_TREE, init);      decl = build_component_ref (C_C_D, name, 0, explicit);      if (explicit	  && TREE_CODE (type) == ARRAY_TYPE	  && init != NULL_TREE	  && TREE_CHAIN (init) == NULL_TREE	  && TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE)	{	  /* Initialization of one array from another.  */	  expand_vec_init (TREE_OPERAND (decl, 1), decl,			   array_type_nelts (type), TREE_VALUE (init), 1);	}      else	expand_aggr_init (decl, init, 0, 0);    }  else    {      if (init == NULL_TREE)	{	  if (explicit)	    {	      cp_error ("incomplete initializer for member `%D' of class `%T' which has no constructor",			member, current_class_type);	      init = error_mark_node;	    }	  /* member traversal: note it leaves init NULL */	  else if (TREE_CODE (TREE_TYPE (member)) == REFERENCE_TYPE)	    cp_pedwarn ("uninitialized reference member `%D'", member);	}      else if (TREE_CODE (init) == TREE_LIST)	{	  /* There was an explicit member initialization.  Do some	     work in that case.  */	  if (TREE_CHAIN (init))	    {	      warning ("initializer list treated as compound expression");	      init = build_compound_expr (init);	    }	  else	    init = TREE_VALUE (init);	}      /* We only build this with a null init if we got it from the	 current_member_init_list.  */      if (init || explicit)	{	  decl = build_component_ref (C_C_D, name, 0, explicit);	  expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));	}    }  expand_cleanups_to (NULL_TREE);  if (TYPE_NEEDS_DESTRUCTOR (type))    {      tree expr = build_component_ref (C_C_D, name, 0, explicit);      expr = build_delete (type, expr, integer_zero_node,			   LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);      if (expr != error_mark_node)	{	  start_protect ();	  *protect_list = tree_cons (NULL_TREE, expr, *protect_list);	}    }}extern int warn_reorder;/* Subroutine of emit_member_init.  */static treesort_member_init (t)     tree t;{  tree x, member, name, field, init;  tree init_list = NULL_TREE;  tree fields_to_unmark = NULL_TREE;  int last_pos = 0;  tree last_field;  for (member = TYPE_FIELDS (t); member ; member = TREE_CHAIN (member))    {      int pos;      /* member could be, for example, a CONST_DECL for an enumerated	 tag; we don't want to try to initialize that, since it already	 has a value.  */      if (TREE_CODE (member) != FIELD_DECL || !DECL_NAME (member))	continue;      for (x = current_member_init_list, pos = 0; x; x = TREE_CHAIN (x), ++pos)	{	  /* If we cleared this out, then pay no attention to it.  */	  if (TREE_PURPOSE (x) == NULL_TREE)	    continue;	  name = TREE_PURPOSE (x);#if 0	  field = (TREE_CODE (name) == COMPONENT_REF		   ? TREE_OPERAND (name, 1) : IDENTIFIER_CLASS_VALUE (name));#else	  /* Let's find out when this happens.  */	  my_friendly_assert (TREE_CODE (name) != COMPONENT_REF, 348);	  field = IDENTIFIER_CLASS_VALUE (name);#endif	  /* If one member shadows another, get the outermost one.  */	  if (TREE_CODE (field) == TREE_LIST)	    field = TREE_VALUE (field);	  if (field == member)	    {	      if (warn_reorder)		{		  if (pos < last_pos)		    {		      cp_warning_at ("member initializers for `%#D'", last_field);		      cp_warning_at ("  and `%#D'", field);		      warning ("  will be re-ordered to match declaration order");		    }		  last_pos = pos;		  last_field = field;		}	      /* Make sure we won't try to work on this init again.  */	      TREE_PURPOSE (x) = NULL_TREE;	      x = build_tree_list (name, TREE_VALUE (x));	      goto got_it;	    }	}      /* If we didn't find MEMBER in the list, create a dummy entry	 so the two lists (INIT_LIST and the list of members) will be	 symmetrical.  */      x = build_tree_list (NULL_TREE, NULL_TREE);    got_it:      init_list = chainon (init_list, x);     }  /* Initializers for base members go at the end.  */  for (x = current_member_init_list ; x ; x = TREE_CHAIN (x))    {      name = TREE_PURPOSE (x);      if (name)	{	  if (purpose_member (name, init_list))	    {	      cp_error ("multiple initializations given for member `%D'",			IDENTIFIER_CLASS_VALUE (name));	      continue;	    }	      	  init_list = chainon (init_list,			       build_tree_list (name, TREE_VALUE (x)));	  TREE_PURPOSE (x) = NULL_TREE;	}    }  return init_list;}static voidsort_base_init (t, rbase_ptr, vbase_ptr)     tree t, *rbase_ptr, *vbase_ptr;{  tree binfos = BINFO_BASETYPES (TYPE_BINFO (t));  int n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;  int i;  tree x;  tree last;  /* For warn_reorder.  */  int last_pos = 0;  tree last_base = NULL_TREE;  tree rbases = NULL_TREE;  tree vbases = NULL_TREE;  /* First walk through and splice out vbase and invalid initializers.     Also replace names with binfos.  */  last = tree_cons (NULL_TREE, NULL_TREE, current_base_init_list);  for (x = TREE_CHAIN (last); x; x = TREE_CHAIN (x))    {      tree basename = TREE_PURPOSE (x);      tree binfo;      if (basename == NULL_TREE)	{	  /* Initializer for single base class.  Must not	     use multiple inheritance or this is ambiguous.  */	  switch (n_baseclasses)	    {	    case 0:	      cp_error ("`%T' does not have a base class to initialize",			current_class_type);	      return;	    case 1:	      break;	    default:	      cp_error ("unnamed initializer ambiguous for `%T' which uses multiple inheritance",			current_class_type);	      return;	    }	  binfo = TREE_VEC_ELT (binfos, 0);	}      else if (is_aggr_typedef (basename, 1))	{	  binfo = binfo_or_else (IDENTIFIER_TYPE_VALUE (basename), t);	  if (binfo == NULL_TREE)	    continue;	  /* Virtual base classes are special cases.  Their initializers	     are recorded with this constructor, and they are used when	     this constructor is the top-level constructor called.  */	  if (TREE_VIA_VIRTUAL (binfo))	    {	      tree v = CLASSTYPE_VBASECLASSES (t);	      while (BINFO_TYPE (v) != BINFO_TYPE (binfo))		v = TREE_CHAIN (v);	      vbases = tree_cons (v, TREE_VALUE (x), vbases);	      continue;	    }	  else	    {	      /* Otherwise, if it is not an immediate base class, complain.  */	      for (i = n_baseclasses-1; i >= 0; i--)		if (BINFO_TYPE (binfo) == BINFO_TYPE (TREE_VEC_ELT (binfos, i)))		  break;	      if (i < 0)		{		  cp_error ("`%T' is not an immediate base class of `%T'",			    IDENTIFIER_TYPE_VALUE (basename),			    current_class_type);		  continue;		}	    }	}      else	my_friendly_abort (365);      TREE_PURPOSE (x) = binfo;      TREE_CHAIN (last) = x;      last = x;    }  TREE_CHAIN (last) = NULL_TREE;  /* Now walk through our regular bases and make sure they're initialized.  */  for (i = 0; i < n_baseclasses; ++i)    {      tree base_binfo = TREE_VEC_ELT (binfos, i);      int pos;      if (TREE_VIA_VIRTUAL (base_binfo))	continue;      for (x = current_base_init_list, pos = 0; x; x = TREE_CHAIN (x), ++pos)

⌨️ 快捷键说明

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