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

📄 cp-init.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
	  error_with_aggr_type (binfo, "in base initialization for class `%s',");	  error_with_aggr_type (type, "invalid initializer to constructor for type `%s'");	  return;	}    }  else    {      if (init == NULL_TREE)	my_friendly_assert (parms == NULL_TREE, 210);      if (parms == NULL_TREE && TREE_VIA_VIRTUAL (binfo))	error_with_aggr_type (binfo, "virtual baseclass `%s' does not have default initializer");      else	{	  error_with_aggr_type (binfo, "in base initialization for class `%s',");	  /* This will make an error message for us.  */	  build_method_call (exp, constructor_name (type), parms, binfo,			     (TYPE_USES_VIRTUAL_BASECLASSES (type)			      ? LOOKUP_NORMAL|LOOKUP_HAS_IN_CHARGE			      : LOOKUP_NORMAL));	}      return;    }  /* Constructor has been called, but vtables may be for TYPE     rather than for FOR_TYPE.  */}/* This function is responsible for initializing EXP with INIT   (if any).   BINFO is the binfo of the type for who we are performing the   initialization.  For example, if W is a virtual base class of A and B,   and C : A, B.   If we are initializing B, then W must contain B's W vtable, whereas   were we initializing C, W must contain C's W vtable.   TRUE_EXP is nonzero if it is the true expression being initialized.   In this case, it may be EXP, or may just contain EXP.  The reason we   need this is because if EXP is a base element of TRUE_EXP, we   don't necessarily know by looking at EXP where its virtual   baseclass fields should really be pointing.  But we do know   from TRUE_EXP.  In constructors, we don't know anything about   the value being initialized.   ALIAS_THIS serves the same purpose it serves for expand_aggr_init.   FLAGS is just passes to `build_method_call'.  See that function for   its description.  */static voidexpand_aggr_init_1 (binfo, true_exp, exp, init, alias_this, flags)     tree binfo;     tree true_exp, exp;     tree init;     int alias_this;     int flags;{  tree type = TREE_TYPE (exp);  tree init_type = NULL_TREE;  tree rval;  my_friendly_assert (init != error_mark_node && type != error_mark_node, 211);  /* Use a function returning the desired type to initialize EXP for us.     If the function is a constructor, and its first argument is     NULL_TREE, know that it was meant for us--just slide exp on     in and expand the constructor.  Constructors now come     as TARGET_EXPRs.  */  if (init)    {      tree init_list = NULL_TREE;      if (TREE_CODE (init) == TREE_LIST)	{	  init_list = init;	  if (TREE_CHAIN (init) == NULL_TREE)	    init = TREE_VALUE (init);	}      init_type = TREE_TYPE (init);      if (TREE_CODE (init) != TREE_LIST)	{	  if (TREE_CODE (init_type) == ERROR_MARK)	    return;#if 0	  /* These lines are found troublesome 5/11/89.  */	  if (TREE_CODE (init_type) == REFERENCE_TYPE)	    init_type = TREE_TYPE (init_type);#endif	  /* This happens when we use C++'s functional cast notation.	     If the types match, then just use the TARGET_EXPR	     directly.  Otherwise, we need to create the initializer	     separately from the object being initialized.  */	  if (TREE_CODE (init) == TARGET_EXPR)	    {	      if (init_type == type)		{		  if (TREE_CODE (exp) == VAR_DECL		      || TREE_CODE (exp) == RESULT_DECL)		    /* Unify the initialization targets.  */		    DECL_RTL (TREE_OPERAND (init, 0)) = DECL_RTL (exp);		  else		    DECL_RTL (TREE_OPERAND (init, 0)) = expand_expr (exp, 0, 0, 0);		  expand_expr_stmt (init);		  return;		}	      else		{		  init = TREE_OPERAND (init, 1);		  init = build (CALL_EXPR, init_type,				TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), 0);		  TREE_SIDE_EFFECTS (init) = 1;#if 0		  TREE_RAISES (init) = ??#endif		    if (init_list)		      TREE_VALUE (init_list) = init;		}	    }	  if (init_type == type && TREE_CODE (init) == CALL_EXPR#if 0	      /* It is legal to directly initialize from a CALL_EXPR		 without going through X(X&), apparently.  */	      && ! TYPE_GETS_INIT_REF (type)#endif	      )	    {	      /* A CALL_EXPR is a legitimate form of initialization, so		 we should not print this warning message.  */#if 0	      /* Should have gone away due to 5/11/89 change.  */	      if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE)		init = convert_from_reference (init);#endif	      expand_assignment (exp, init, 0, 0);	      if (exp == DECL_RESULT (current_function_decl))		{		  /* Failing this assertion means that the return value		     from receives multiple initializations.  */		  my_friendly_assert (DECL_INITIAL (exp) == NULL_TREE				      || DECL_INITIAL (exp) == error_mark_node,				      212);		  DECL_INITIAL (exp) = init;		}	      return;	    }	  else if (init_type == type		   && TREE_CODE (init) == COND_EXPR)	    {	      /* Push value to be initialized into the cond, where possible.	         Avoid spurious warning messages when initializing the		 result of this function.  */	      TREE_OPERAND (init, 1)		= build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 1));	      if (exp == DECL_RESULT (current_function_decl))		DECL_INITIAL (exp) = NULL_TREE;	      TREE_OPERAND (init, 2)		= build_modify_expr (exp, INIT_EXPR, TREE_OPERAND (init, 2));	      if (exp == DECL_RESULT (current_function_decl))		DECL_INITIAL (exp) = init;	      expand_expr (init, const0_rtx, VOIDmode, 0);	      free_temp_slots ();	      return;	    }	}      /* We did not know what we were initializing before.  Now we do.  */      if (TREE_CODE (init) == TARGET_EXPR)	{	  tree tmp = TREE_OPERAND (TREE_OPERAND (init, 1), 1);	  if (TREE_CODE (TREE_VALUE (tmp)) == NOP_EXPR	      && TREE_OPERAND (TREE_VALUE (tmp), 0) == integer_zero_node)	    {	      /* In order for this to work for RESULT_DECLs, if their		 type has a constructor, then they must be BLKmode		 so that they will be meaningfully addressable.  */	      tree arg = build_unary_op (ADDR_EXPR, exp, 0);	      init = TREE_OPERAND (init, 1);	      init = build (CALL_EXPR, build_pointer_type (TREE_TYPE (init)),			    TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), 0);	      TREE_SIDE_EFFECTS (init) = 1;#if 0	      TREE_RAISES (init) = ??#endif	      TREE_VALUE (TREE_OPERAND (init, 1))		= convert_pointer_to (TREE_TYPE (TREE_TYPE (TREE_VALUE (tmp))), arg);	      if (alias_this)		{		  expand_assignment (current_function_decl, init, 0, 0);		  return;		}	      if (exp == DECL_RESULT (current_function_decl))		{		  if (DECL_INITIAL (DECL_RESULT (current_function_decl)))		    fatal ("return value from function receives multiple initializations");		  DECL_INITIAL (exp) = init;		}	      expand_expr_stmt (init);	      return;	    }	}      /* Handle this case: when calling a constructor: xyzzy foo(bar);	 which really means:  xyzzy foo = bar; Ugh!	 We can also be called with an initializer for an object	 which has virtual functions, but no constructors.  In that	 case, we perform the assignment first, then initialize	 the virtual function table pointer fields.  */      if (! TYPE_NEEDS_CONSTRUCTING (type))	{	  if (init_list && TREE_CHAIN (init_list))	    {	      warning ("initializer list being treated as compound expression");	      init = convert (TREE_TYPE (exp), build_compound_expr (init_list));	      if (init == error_mark_node)		return;	    }	  if (TREE_CODE (exp) == VAR_DECL	      && TREE_CODE (init) == CONSTRUCTOR	      && TREE_HAS_CONSTRUCTOR (init)	      && flag_pic == 0)	    store_init_value (exp, init);	  else	    expand_assignment (exp, init, 0, 0);	  if (TYPE_VIRTUAL_P (type))	    expand_recursive_init (binfo, true_exp, exp, init, CLASSTYPE_BASE_INIT_LIST (type), alias_this);	  return;	}      /* See whether we can go through a type conversion operator.	 This wins over going through a non-existent constructor.  If	 there is a constructor, it is ambiguous.  */      if (TREE_CODE (init) != TREE_LIST)	{	  tree ttype = TREE_CODE (init_type) == REFERENCE_TYPE	    ? TREE_TYPE (init_type) : init_type;	  if (ttype != type && IS_AGGR_TYPE (ttype))	    {	      tree rval = build_type_conversion (CONVERT_EXPR, type, init, 0);	      if (rval)		{		  /* See if there is a constructor for``type'' that takes a		     ``ttype''-typed object. */		  tree parms = build_tree_list (NULL_TREE, init);		  tree as_cons = NULL_TREE;		  if (TYPE_HAS_CONSTRUCTOR (type))		    as_cons = build_method_call (exp, constructor_name (type),						 parms, binfo,						 LOOKUP_SPECULATIVELY);		  if (as_cons != NULL_TREE && as_cons != error_mark_node)		    {		      tree name = TYPE_NAME (type);		      if (TREE_CODE (name) == TYPE_DECL)			name = DECL_NAME (name);		      /* ANSI C++ June 5 1992 WP 12.3.2.6.1 */		      error ("ambiguity between conversion to `%s' and constructor",			     IDENTIFIER_POINTER (name));		    }		  else		    expand_assignment (exp, rval, 0, 0);		  return;		}	    }	}    }  /* Handle default copy constructors here, does not matter if there is     a constructor or not.  */  if (type == init_type && IS_AGGR_TYPE (type)      && init && TREE_CODE (init) != TREE_LIST)    expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags);  /* Not sure why this is here... */  else if (TYPE_HAS_CONSTRUCTOR (type))    expand_default_init (binfo, true_exp, exp, type, init, alias_this, flags);  else if (TREE_CODE (type) == ARRAY_TYPE)    {      if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type)))	expand_vec_init (exp, exp, array_type_nelts (type), init, 0);      else if (TYPE_VIRTUAL_P (TREE_TYPE (type)))	sorry ("arrays of objects with virtual functions but no constructors");    }  else    expand_recursive_init (binfo, true_exp, exp, init,			   CLASSTYPE_BASE_INIT_LIST (type), alias_this);}/* A pointer which holds the initializer.  First call to   expand_aggr_init gets this value pointed to, and sets it to init_null.  */static tree *init_ptr, init_null;/* Subroutine of expand_recursive_init:   ADDR is the address of the expression being initialized.   INIT_LIST is the cons-list of initializations to be performed.   ALIAS_THIS is its same, lovable self.  */static voidexpand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this)     tree binfo, true_exp, addr;     tree init_list;     int alias_this;{  while (init_list)    {      if (TREE_PURPOSE (init_list))	{	  if (TREE_CODE (TREE_PURPOSE (init_list)) == FIELD_DECL)	    {	      tree member = TREE_PURPOSE (init_list);	      tree subexp = build_indirect_ref (convert_pointer_to (TREE_VALUE (init_list), addr), 0);	      tree member_base = build (COMPONENT_REF, TREE_TYPE (member), subexp, member);	      if (IS_AGGR_TYPE (TREE_TYPE (member)))		expand_aggr_init (member_base, DECL_INITIAL (member), 0);	      else if (TREE_CODE (TREE_TYPE (member)) == ARRAY_TYPE		       && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (member)))		{		  member_base = save_expr (default_conversion (member_base));		  expand_vec_init (member, member_base,				   array_type_nelts (TREE_TYPE (member)),				   DECL_INITIAL (member), 0);		}	      else expand_expr_stmt (build_modify_expr (member_base, INIT_EXPR, DECL_INITIAL (member)));	    }	  else if (TREE_CODE (TREE_PURPOSE (init_list)) == TREE_LIST)	    {	      expand_recursive_init_1 (binfo, true_exp, addr, TREE_PURPOSE (init_list), alias_this);	      expand_recursive_init_1 (binfo, true_exp, addr, TREE_VALUE (init_list), alias_this);	    }	  else if (TREE_CODE (TREE_PURPOSE (init_list)) == ERROR_MARK)	    {	      /* Only initialize the virtual function tables if we		 are initializing the ultimate users of those vtables.  */	      if (TREE_VALUE (init_list))		{		  expand_expr_stmt (build_virtual_init (binfo, TREE_VALUE (init_list), addr));		  if (TREE_VALUE (init_list) == binfo		      && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))		    expand_expr_stmt (build_vbase_vtables_init (binfo, binfo, true_exp, addr, 1));		}	    }	  else my_friendly_abort (49);	}      else if (TREE_VALUE (init_list)	       && TREE_CODE (TREE_VALUE (init_list)) == TREE_VEC)	{	  tree subexp = build_indirect_ref (convert_pointer_to (TREE_VALUE (init_list), addr), 0);	  expand_aggr_init_1 (binfo, true_exp, subexp, *init_ptr,			      alias_this && BINFO_OFFSET_ZEROP (TREE_VALUE (init_list)),			      LOOKUP_PROTECTED_OK|LOOKUP_COMPLAIN);	  /* INIT_PTR is used up.  */	  init_ptr = &init_null;	}      else	my_friendly_abort (50);      init_list = TREE_CHAIN (init_list);    }}/* Initialize EXP with INIT.  Type EXP does not have a constructor,   but it has a baseclass with a constructor or a virtual function   table which needs initializing.   INIT_LIST is a cons-list describing what parts of EXP actually   need to be initialized.  INIT is given to the *unique*, first   constructor within INIT_LIST.  If there are multiple first   constructors, such as with multiple inheritance, INIT must   be zero or an ambiguity error is reported.   ALIAS_THIS is passed from `expand_aggr_init'.  See comments   there.  */static voidexpand_recursive_init (binfo, true_exp, exp, init, init_list, alias_this)     tree binfo, true_exp, exp, init;     tree init_list;     int alias_this;{  tree *old_init_ptr = init_ptr;  tree addr = build_unary_op (ADDR_EXPR, exp, 0);  init_ptr = &init;  if (true_exp == exp && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))    {      expand_aggr_vbase_init (binfo, exp, addr, init_list);      expand_expr_stmt (build_vbase_vtables_init (binfo, binfo, true_exp, addr, 1));    }  expand_recursive_init_1 (binfo, true_exp, addr, init_list, alias_this);  if (*init_ptr)    {      tree type = TREE_TYPE (exp);      if (TREE_CODE (type) == REFERENCE_TYPE)	type = TREE_TYPE (type);      if (IS_AGGR_TYPE (type))	error_with_aggr_type (type, "unexpected argument to constructor `%s'");      else	error ("unexpected argument to constructor");    }  init_ptr = old_init_ptr;}/* Report an error if NAME is not the name of a user-defined,   aggregate type.  If OR_ELSE is nonzero, give an error message.  */int

⌨️ 快捷键说明

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