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

📄 init.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      expand_expr_stmt (rval);      return;    }  if (init && TREE_CHAIN (parms) == NULL_TREE      && TYPE_HAS_TRIVIAL_INIT_REF (type)      && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init)))    {      rval = build (INIT_EXPR, type, exp, init);      TREE_SIDE_EFFECTS (rval) = 1;      expand_expr_stmt (rval);    }  else    {      if (flags & LOOKUP_ONLYCONVERTING)	flags |= LOOKUP_NO_CONVERSION;      rval = build_method_call (exp, ctor_identifier,				parms, binfo, flags);      /* Private, protected, or otherwise unavailable.  */      if (rval == error_mark_node)	{	  if (flags & LOOKUP_COMPLAIN)	    cp_error ("in base initialization for %sclass `%T'",		      TREE_VIA_VIRTUAL (binfo) ? "virtual base " : "",		      binfo);	}      else if (rval == NULL_TREE)	my_friendly_abort (361);      else	{	  /* p. 222: if the base class assigns to `this', then that	     value is used in the derived class.  */	  if ((flag_this_is_variable & 1) && alias_this)	    {	      TREE_TYPE (rval) = TREE_TYPE (current_class_ptr);	      expand_assignment (current_class_ptr, rval, 0, 0);	    }	  else	    expand_expr_stmt (rval);	}    }}/* 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;  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_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;    }  if (init && ! flag_ansi_overloading)    {      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 (init_type == error_mark_node)	    return;	  /* 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, VOIDmode, EXPAND_NORMAL);		  expand_expr_stmt (init);		  return;		}	    }	  if (init_type == type && TREE_CODE (init) == CALL_EXPR)	    {	      /* A CALL_EXPR is a legitimate form of initialization, so		 we should not print this warning message.  */	      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, EXPAND_NORMAL);	      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 (tmp && 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), NULL_TREE);	      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;	    }	}      /* 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 = cp_convert (type, build_compound_expr (init_list));	      if (init == error_mark_node)		return;	    }	  expand_assignment (exp, init, 0, 0);	  return;	}      /* If this is copy-initialization, see whether we can go through a	 type conversion operator.  */      if (TREE_CODE (init) != TREE_LIST && (flags & LOOKUP_ONLYCONVERTING))	{	  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, 1);	      if (rval)		{		  /* See if there is a constructor for``type'' that takes a		     ``ttype''-typed object.  */		  tree parms = build_expr_list (NULL_TREE, init);		  tree as_cons = NULL_TREE;		  if (TYPE_HAS_CONSTRUCTOR (type))		    as_cons = build_method_call (exp, ctor_identifier,						 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		    if (rval != error_mark_node)		      expand_aggr_init_1 (binfo, true_exp, exp, rval, alias_this, flags);		  return;		}	    }	}    }  /* We know that expand_default_init can handle everything we want     at this point.  */  expand_default_init (binfo, true_exp, exp, init, alias_this, flags);}/* 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;}/* Report an error if TYPE is not a user-defined, aggregate type.  If   OR_ELSE is nonzero, give an error message.  */intis_aggr_type (type, or_else)     tree type;     int or_else;{  if (type == error_mark_node)    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;}treeget_type_value (name)     tree name;{  if (name == error_mark_node)    return NULL_TREE;  if (IDENTIFIER_HAS_TYPE_VALUE (name))    return IDENTIFIER_TYPE_VALUE (name);  else    return NULL_TREE;}  /* This code could just as well go in `class.c', but is placed here for   modularity.  *//* For an expression of the form TYPE :: NAME (PARMLIST), build   the appropriate function call.  */treebuild_member_call (type, name, parmlist)     tree type, name, parmlist;{  tree t;  tree method_name;  int dtor = 0;  int dont_use_this = 0;  tree basetype_path, decl;  if (type == std_node)    return build_x_function_call (do_scoped_id (name, 0), parmlist,				  current_class_ref);  if (TREE_CODE (name) != TEMPLATE_ID_EXPR)    method_name = name;  else    method_name = TREE_OPERAND (name, 0);  if (TREE_CODE (method_name) == BIT_NOT_EXPR)    {      method_name = TREE_OPERAND (method_name, 0);      dtor = 1;    }  /* This shouldn't be here, and build_member_call shouldn't appear in     parse.y!  (mrs)  */  if (type && TREE_CODE (type) == IDENTIFIER_NODE      && get_aggr_from_typedef (type, 0) == 0)    {      tree ns = lookup_name (type, 0);      if (ns && TREE_CODE (ns) == NAMESPACE_DECL)	{	  return build_x_function_call (build_offset_ref (type, name), parmlist, current_class_ref);	}    }  if (type == NULL_TREE || ! is_aggr_type (type, 1))    return error_mark_node;  /* An operator we did not like.  */  if (name == NULL_TREE)    return error_mark_node;  if (dtor)    {      cp_error ("cannot call destructor `%T::~%T' without object", type,		method_name);      return error_mark_node;    }  /* No object?  Then just fake one up, and let build_method_call     figure out what to do.  */  if (current_class_type == 0      || get_base_distance (type, current_class_type, 0, &basetype_path) == -1)    dont_use_this = 1;  if (dont_use_this)    {      basetype_path = TYPE_BINFO (type);      decl = build1 (NOP_EXPR, build_pointer_type (type), error_mark_node);    }  else if (current_class_ptr == 0)

⌨️ 快捷键说明

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