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

📄 cp-init.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
/* Handle initialization things in 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.  *//* High-level class interface. */#include "config.h"#include "tree.h"#include "rtl.h"#include "cp-tree.h"#include "flags.h"#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 ();tree expand_vec_init ();tree build_vec_delete ();static void add_friend (), add_friends ();int is_aggr_typedef ();/* Cache _builtin_new and _builtin_delete exprs.  */static tree BIN, BID;#ifdef SOStree get_linktable_name (), get_dtable_name (), get_sos_dtable ();static tree __sosFindCode, __sosLookup, __sosImport;static tree build_dynamic_new ();#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 op_id;  tree fields[2];  /* Define implicit `operator new' and `operator delete' functions.  */  BIN = default_conversion (TREE_VALUE (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) NEW_EXPR])));  TREE_USED (TREE_OPERAND (BIN, 0)) = 0;  BID = default_conversion (TREE_VALUE (IDENTIFIER_GLOBAL_VALUE (ansi_opname[(int) DELETE_EXPR])));  TREE_USED (TREE_OPERAND (BID, 0)) = 0;  minus_one = build_int_2 (-1, -1);  op_id = ansi_opname[(int) NEW_EXPR];  IDENTIFIER_GLOBAL_VALUE (op_id) = BIN;  op_id = ansi_opname[(int) DELETE_EXPR];  IDENTIFIER_GLOBAL_VALUE (op_id) = BID;#ifdef SOS  if (flag_all_virtual == 2)    {      __sosFindCode = default_conversion (lookup_name (get_identifier ("sosFindCode"), 0));      __sosLookup = default_conversion (lookup_name (get_identifier ("sosLookup"), 0));      __sosImport = default_conversion (lookup_name (get_identifier ("sosImport"), 0));    }#endif  /* Define the structure that holds header information for     arrays allocated via operator new.  */  BI_header_type = make_lang_type (RECORD_TYPE);  fields[0] = build_lang_field_decl (FIELD_DECL, get_identifier ("nelts"),				     sizetype);  fields[1] = build_lang_field_decl (FIELD_DECL, get_identifier ("ptr_2comp"),				     ptr_type_node);  finish_builtin_type (BI_header_type, "__new_cookie", fields, 1, double_type_node);  BI_header_size = size_in_bytes (BI_header_type);}/* Recursive subroutine of emit_base_init.  For main type T,   recursively initialize the vfields of the base type PARENT.   RECURSE is non-zero when this function is being called   recursively.  */static voidinit_vfields (t, parent, recurse)     tree t, parent;     int recurse;{  tree vfields;  /* Initialize all the virtual function table fields that     do not come from virtual base classes.  */  vfields = CLASSTYPE_VFIELDS (parent);  while (vfields)    {      tree basetype = VF_DERIVED_VALUE (vfields)	? TYPE_MAIN_VARIANT (VF_DERIVED_VALUE (vfields))	  : VF_BASETYPE_VALUE (vfields);      /* If the vtable installed by the constructor was not	 the right one, fix that here.  */      if (TREE_ADDRESSABLE (vfields)	  && CLASSTYPE_NEEDS_VIRTUAL_REINIT (basetype)	  && (recurse > 0	      || TYPE_HAS_CONSTRUCTOR (basetype)	      /* BASE_INIT_LIST has already initialized the immediate basetypes.  */	      || get_base_distance (basetype, t, 0, 0) > 1))	{	  tree binfo = binfo_value (basetype, t, 0);	  if ((recurse != 0 && (binfo != binfo_value (basetype, parent, 0)))	      || (recurse == 0		  && BINFO_VTABLE (binfo) != TYPE_BINFO_VTABLE (basetype)))	    {	      tree ptr = convert_pointer_to (binfo, current_class_decl);	      expand_expr_stmt (build_virtual_init (TYPE_BINFO (t), binfo, ptr));	    }	  init_vfields (t, basetype, recurse+1);	}      vfields = TREE_CHAIN (vfields);    }}/* Perform whatever initialization have yet to be done on the   base class of the class variable.  These actions are in   the global variable CURRENT_BASE_INIT_LIST.  Such an   action could be NULL_TREE, meaning that the user has explicitly   called the base class constructor with no arguments.   If there is a need for a call to a constructor, we   must surround that call with a pushlevel/poplevel pair,   since we are technically at the PARM level of scope.   Argument IMMEDIATELY, if zero, forces a new sequence to be generated   to contain these new insns, so it can be emitted later.  This sequence   is saved in the global variable BASE_INIT_INSNS.  Otherwise, the insns   are emitted into the current sequence.   Note that emit_base_init does *not* initialize virtual   base classes.  That is done specially, elsewhere.  */   voidemit_base_init (t, immediately)     tree t;     int immediately;{  extern tree in_charge_identifier;  tree member, decl, vbases;  tree init_list;  int pass, start;  tree t_binfo = TYPE_BINFO (t);  tree binfos = BINFO_BASETYPES (t_binfo);  int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;  tree fields_to_unmark = NULL_TREE;  if (! immediately)    {      do_pending_stack_adjust ();      start_sequence ();    }  if (write_symbols == NO_DEBUG)    /* As a matter of principle, `start_sequence' should do this.  */    emit_note (0, -1);  else    /* Always emit a line number note so we can step into constructors.  */    emit_line_note_force (DECL_SOURCE_FILE (current_function_decl),			  DECL_SOURCE_LINE (current_function_decl));  /* In this case, we always need IN_CHARGE_NODE, because we have     to know whether to deallocate or not before exiting.  */  if (flag_handle_exceptions == 2      && lookup_name (in_charge_identifier, 0) == NULL_TREE)    {      tree in_charge_node = pushdecl (build_decl (VAR_DECL, in_charge_identifier,						  integer_type_node));      store_init_value (in_charge_node, build (EQ_EXPR, integer_type_node,					       current_class_decl,					       integer_zero_node));      expand_decl (in_charge_node);      expand_decl_init (in_charge_node);    }  start = ! TYPE_USES_VIRTUAL_BASECLASSES (t);  for (pass = start; pass < 2; pass++)    {      tree vbase_init_list = NULL_TREE;      for (init_list = current_base_init_list; init_list;	   init_list = TREE_CHAIN (init_list))	{	  tree basename = TREE_PURPOSE (init_list);	  tree binfo;	  tree init = TREE_VALUE (init_list);	  if (basename == NULL_TREE)	    {	      /* Initializer for single base class.  Must not		 use multiple inheritance or this is ambiguous.  */	      switch (n_baseclasses)		{		case 0:		  error ("type `%s' does not have a base class to initialize",			 IDENTIFIER_POINTER (current_class_name));		  return;		case 1:		  break;		default:		  error ("unnamed initializer ambiguous for type `%s' which uses multiple inheritance", IDENTIFIER_POINTER (current_class_name));		  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))		{		  /* 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)		    {		      error ("type `%s' is not an immediate base class of type `%s'",			     IDENTIFIER_POINTER (basename),			     IDENTIFIER_POINTER (current_class_name));		      continue;		    }		}	    }	  else	    continue;	  /* The base initialization list goes up to the first	     base class which can actually use it.  */	  if (pass == start)	    {	      char *msgp = (! TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (binfo)))		? "cannot pass initialization up to class `%s'" : 0;	      while (! TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (binfo))		     && BINFO_BASETYPES (binfo) != NULL_TREE		     && TREE_VEC_LENGTH (BINFO_BASETYPES (binfo)) == 1)		{		  /* ?? This should be fixed in RENO by forcing		     default constructors to exist.  */		  SET_BINFO_BASEINIT_MARKED (binfo);		  binfo = BINFO_BASETYPE (binfo, 0);		}	      if (TYPE_HAS_CONSTRUCTOR (BINFO_TYPE (binfo)))		{		  if (msgp)		    {		      if (pedantic)			error_with_aggr_type (binfo, msgp);		      else			msgp = 0;		    }		}	      else		{		  msgp = "no constructor found for initialization of `%s'";		  error (msgp, IDENTIFIER_POINTER (basename));		}	      if (BINFO_BASEINIT_MARKED (binfo))		{		  msgp = "class `%s' initializer already specified";		  error (msgp, IDENTIFIER_POINTER (basename));		}	      if (msgp)		continue;	      SET_BINFO_BASEINIT_MARKED (binfo);	      if (TREE_VIA_VIRTUAL (binfo))		{		  vbase_init_list = tree_cons (init, BINFO_TYPE (binfo),					       vbase_init_list);		  continue;		}	      if (pass == 0)		continue;	    }	  else if (TREE_VIA_VIRTUAL (binfo))	    continue;	  member = convert_pointer_to (binfo, current_class_decl);	  expand_aggr_init_1 (t_binfo, 0,			      build_indirect_ref (member, 0), init,			      BINFO_OFFSET_ZEROP (binfo),			      LOOKUP_PROTECTED_OK|LOOKUP_COMPLAIN);	  if (flag_handle_exceptions == 2 && TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (binfo)))	    {	      cplus_expand_start_try (1);	      push_exception_cleanup (member);	    }	}      if (pass == 0)	{	  tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));	  tree vbases;	  if (DECL_NAME (current_function_decl) == NULL_TREE	      && TREE_CHAIN (first_arg) != NULL_TREE)	    {	      /* If there are virtual baseclasses without initialization		 specified, and this is a default X(X&) constructor,		 build the initialization list so that each virtual baseclass		 of the new object is initialized from the virtual baseclass		 of the incoming arg.  */	      tree init_arg = build_unary_op (ADDR_EXPR, TREE_CHAIN (first_arg), 0);	      for (vbases = CLASSTYPE_VBASECLASSES (t);		   vbases; vbases = TREE_CHAIN (vbases))		{		  if (BINFO_BASEINIT_MARKED (vbases) == 0)		    {		      member = convert_pointer_to (vbases, init_arg);		      if (member == init_arg)			member = TREE_CHAIN (first_arg);		      else			TREE_TYPE (member) = build_reference_type (BINFO_TYPE (vbases));		      vbase_init_list = tree_cons (convert_from_reference (member),						   vbases, vbase_init_list);		      SET_BINFO_BASEINIT_MARKED (vbases);		    }		}	    }	  expand_start_cond (first_arg, 0);	  expand_aggr_vbase_init (t_binfo, C_C_D, current_class_decl,				  vbase_init_list);	  expand_expr_stmt (build_vbase_vtables_init (t_binfo, t_binfo,						      C_C_D, current_class_decl, 1));	  expand_end_cond ();	}    }  current_base_init_list = NULL_TREE;  /* Now, perform default initialization of all base classes which     have not yet been initialized, and unmark baseclasses which     have been initialized.  */  for (i = 0; i < n_baseclasses; i++)    {      tree base = current_class_decl;      tree base_binfo = TREE_VEC_ELT (binfos, i);      if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (base_binfo)))	{	  if (! TREE_VIA_VIRTUAL (base_binfo)	      && ! BINFO_BASEINIT_MARKED (base_binfo))	    {	      tree ref;	      if (BINFO_OFFSET_ZEROP (base_binfo))		base = build1 (NOP_EXPR,			       TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),			       current_class_decl);	      else		base = build (PLUS_EXPR,			      TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),			      current_class_decl, BINFO_OFFSET (base_binfo));	      ref = build_indirect_ref (base, 0);	      expand_aggr_init_1 (t_binfo, 0, ref, NULL_TREE,				  BINFO_OFFSET_ZEROP (base_binfo),				  LOOKUP_PROTECTED_OK|LOOKUP_COMPLAIN);	      if (flag_handle_exceptions == 2		  && TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))		{		  cplus_expand_start_try (1);		  push_exception_cleanup (base);		}	    }	}      CLEAR_BINFO_BASEINIT_MARKED (base_binfo);    }

⌨️ 快捷键说明

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