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

📄 init.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
   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;  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 (TYPE_MAIN_VARIANT (init_type) == TYPE_MAIN_VARIANT (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, NULL_RTX, 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 (init_list)		      TREE_VALUE (init_list) = init;		}	    }	  if (init_type == type && TREE_CODE (init) == CALL_EXPR#if 0	      /* It is valid 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;	      TREE_SIDE_EFFECTS (init) = 1;	      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;	      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;	    }	}      if (TREE_CODE (exp) == VAR_DECL	  && TREE_CODE (init) == CONSTRUCTOR	  && TREE_HAS_CONSTRUCTOR (init))	{	  tree t = store_init_value (exp, init);	  if (!t)	    {	      expand_decl_init (exp);	      return;	    }	  t = build (INIT_EXPR, type, exp, init);	  TREE_SIDE_EFFECTS (t) = 1;	  expand_expr_stmt (t);	  return;	}      /* Handle this case: when calling a constructor: xyzzy foo(bar);	 which really means:  xyzzy foo = bar; Ugh!	 More useful for this case: xyzzy *foo = new xyzzy (bar);  */      if (! TYPE_NEEDS_CONSTRUCTING (type) && ! IS_AGGR_TYPE (type))	{	  if (init_list && TREE_CHAIN (init_list))	    {	      warning ("initializer list being treated as compound expression");	      init = convert (type, build_compound_expr (init_list));	      if (init == error_mark_node)		return;	    }	  expand_assignment (exp, init, 0, 0);	  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_full (type),						 parms, binfo,						 LOOKUP_SPECULATIVELY|LOOKUP_NO_CONVERSION);		  if (as_cons != NULL_TREE && as_cons != error_mark_node)		    /* ANSI C++ June 5 1992 WP 12.3.2.6.1 */		    cp_error ("ambiguity between conversion to `%T' and constructor",			      type);		  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), NULL_PTR);	      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, 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))		{		  /* We have to ensure that the first argment to		     expand_virtual_init is in binfo's hierarchy.  */		  /* Is it the case that this is exactly the right binfo? */		  /* If it is ok, then fixup expand_virtual_init, to make		     it much simpler. */		  expand_virtual_init (get_binfo (TREE_VALUE (init_list), binfo, 0),				      addr);		  if (TREE_VALUE (init_list) == binfo		      && TYPE_USES_VIRTUAL_BASECLASSES (BINFO_TYPE (binfo)))		    expand_indirect_vtbls_init (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), NULL_PTR);	  expand_aggr_init_1 (binfo, true_exp, subexp, *init_ptr,			      alias_this && BINFO_OFFSET_ZEROP (TREE_VALUE (init_list)),			      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_indirect_vtbls_init (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))	cp_error ("unexpected argument to constructor `%T'", type);      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.  */intis_aggr_typedef (name, or_else)     tree name;     int or_else;{  tree type;  if (name == error_mark_node)    return 0;  if (IDENTIFIER_HAS_TYPE_VALUE (name))    type = IDENTIFIER_TYPE_VALUE (name);  else    {      if (or_else)	cp_error ("`%T' is not an aggregate typedef", name);      return 0;    }  if (! IS_AGGR_TYPE (type)      && TREE_CODE (type) != TEMPLATE_TYPE_PARM)    {      if (or_else)	cp_error ("`%T' is not an aggregate type", type);      return 0;    }  return 1;}/* Like is_aggr_typedef, but returns typedef if successful.  */treeget_aggr_from_typedef (name, or_else)     tree name;     int or_else;{  tree type;  if (name == error_mark_node)    return NULL_TREE;  if (IDENTIFIER_HAS_TYPE_VALUE (name))    type = IDENTIFIER_TYPE_VALUE (name);  else    {      if (or_else)	cp_error ("`%T' fails to be an aggregate typedef", name);      return NULL_TREE;    }  if (! IS_AGGR_TYPE (type)      && TREE_CODE (type) != TEMPLATE_TYPE_PARM)    {      if (or_else)	cp_error ("type `%T' is of non-aggregate type", type);      return NULL_TREE;    }  return type;

⌨️ 快捷键说明

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