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

📄 init.c

📁 gcc库的原代码,对编程有很大帮助.
💻 C
📖 第 1 页 / 共 5 页
字号:
/* If NAME is a viable field name for the aggregate DECL,   and PARMS is a viable parameter list, then expand an _EXPR   which describes this initialization.   Note that we do not need to chase through the class's base classes   to look for NAME, because if it's in that list, it will be handled   by the constructor for that base class.   We do not yet have a fixed-point finder to instantiate types   being fed to overloaded constructors.  If there is a unique   constructor, then argument types can be got from that one.   If INIT is non-NULL, then it the initialization should   be placed in `current_base_init_list', where it will be processed   by `emit_base_init'.  */voidexpand_member_init (exp, name, init)     tree exp, name, init;{  extern tree ptr_type_node;	/* should be in tree.h */  tree basetype = NULL_TREE, field;  tree parm;  tree rval, type;  tree actual_name;  if (exp == NULL_TREE)    return;			/* complain about this later */  type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));  if (name == NULL_TREE && IS_AGGR_TYPE (type))    switch (CLASSTYPE_N_BASECLASSES (type))      {      case 0:	error ("base class initializer specified, but no base class to initialize");	return;      case 1:	basetype = TYPE_BINFO_BASETYPE (type, 0);	break;      default:	error ("initializer for unnamed base class ambiguous");	cp_error ("(type `%T' uses multiple inheritance)", type);	return;      }  if (init)    {      /* The grammar should not allow fields which have names	 that are TYPENAMEs.  Therefore, if the field has	 a non-NULL TREE_TYPE, we may assume that this is an	 attempt to initialize a base class member of the current	 type.  Otherwise, it is an attempt to initialize a	 member field.  */      if (init == void_type_node)	init = NULL_TREE;      if (name == NULL_TREE || IDENTIFIER_HAS_TYPE_VALUE (name))	{	  tree base_init;	  if (name == NULL_TREE)	    {/*	      if (basetype)		name = TYPE_IDENTIFIER (basetype);	      else		{		  error ("no base class to initialize");		  return;		}*/	    }	  else	    {	      basetype = IDENTIFIER_TYPE_VALUE (name);	      if (basetype != type		  && ! binfo_member (basetype, TYPE_BINFO (type))		  && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type)))		{		  if (IDENTIFIER_CLASS_VALUE (name))		    goto try_member;		  if (TYPE_USES_VIRTUAL_BASECLASSES (type))		    error ("type `%s' is not an immediate or virtual basetype for `%s'",			   IDENTIFIER_POINTER (name),			   TYPE_NAME_STRING (type));		  else		    error ("type `%s' is not an immediate basetype for `%s'",			   IDENTIFIER_POINTER (name),			   TYPE_NAME_STRING (type));		  return;		}	    }	  if (purpose_member (name, current_base_init_list))	    {	      error ("base class `%s' already initialized",		     IDENTIFIER_POINTER (name));	      return;	    }	  base_init = build_tree_list (name, init);	  TREE_TYPE (base_init) = basetype;	  current_base_init_list = chainon (current_base_init_list, base_init);	}      else	{	  tree member_init;	try_member:	  field = lookup_field (type, name, 1, 0);	  if (! member_init_ok_or_else (field, type, IDENTIFIER_POINTER (name)))	    return;	  if (purpose_member (name, current_member_init_list))	    {	      error ("field `%s' already initialized", IDENTIFIER_POINTER (name));	      return;	    }	  member_init = build_tree_list (name, init);	  TREE_TYPE (member_init) = TREE_TYPE (field);	  current_member_init_list = chainon (current_member_init_list, member_init);	}      return;    }  else if (name == NULL_TREE)    {      compiler_error ("expand_member_init: name == NULL_TREE");      return;    }  basetype = type;  field = lookup_field (basetype, name, 0, 0);  if (! member_init_ok_or_else (field, basetype, IDENTIFIER_POINTER (name)))    return;  /* now see if there is a constructor for this type     which will take these args. */  if (TYPE_HAS_CONSTRUCTOR (TREE_TYPE (field)))    {      tree parmtypes, fndecl;      if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)	{	  /* just know that we've seen something for this node */	  DECL_INITIAL (exp) = error_mark_node;	  TREE_USED (exp) = 1;	}      type = TYPE_MAIN_VARIANT (TREE_TYPE (field));      actual_name = TYPE_IDENTIFIER (type);      parm = build_component_ref (exp, name, 0, 0);      /* Now get to the constructor.  */      fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0);      /* Get past destructor, if any.  */      if (TYPE_HAS_DESTRUCTOR (type))	fndecl = DECL_CHAIN (fndecl);      if (fndecl)	my_friendly_assert (TREE_CODE (fndecl) == FUNCTION_DECL, 209);      /* If the field is unique, we can use the parameter	 types to guide possible type instantiation.  */      if (DECL_CHAIN (fndecl) == NULL_TREE)	{	  /* There was a confusion here between	     FIELD and FNDECL.  The following code	     should be correct, but abort is here	     to make sure.  */	  my_friendly_abort (48);	  parmtypes = FUNCTION_ARG_CHAIN (fndecl);	}      else	{	  parmtypes = NULL_TREE;	  fndecl = NULL_TREE;	}      init = convert_arguments (parm, parmtypes, NULL_TREE, fndecl, LOOKUP_NORMAL);      if (init == NULL_TREE || TREE_TYPE (init) != error_mark_node)	rval = build_method_call (NULL_TREE, actual_name, init, NULL_TREE, LOOKUP_NORMAL);      else	return;      if (rval != error_mark_node)	{	  /* Now, fill in the first parm with our guy */	  TREE_VALUE (TREE_OPERAND (rval, 1))	    = build_unary_op (ADDR_EXPR, parm, 0);	  TREE_TYPE (rval) = ptr_type_node;	  TREE_SIDE_EFFECTS (rval) = 1;	}    }  else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))    {      parm = build_component_ref (exp, name, 0, 0);      expand_aggr_init (parm, NULL_TREE, 0, 0);      rval = error_mark_node;    }  /* Now initialize the member.  It does not have to     be of aggregate type to receive initialization.  */  if (rval != error_mark_node)    expand_expr_stmt (rval);}/* This is like `expand_member_init', only it stores one aggregate   value into another.   INIT comes in two flavors: it is either a value which   is to be stored in EXP, or it is a parameter list   to go to a constructor, which will operate on EXP.   If INIT is not a parameter list for a constructor, then set   LOOKUP_ONLYCONVERTING.   If FLAGS is LOOKUP_ONLYCONVERTING then it is the = init form of   the initializer, if FLAGS is 0, then it is the (init) form.   If `init' is a CONSTRUCTOR, then we emit a warning message,   explaining that such initializations are invalid.   ALIAS_THIS is nonzero iff we are initializing something which is   essentially an alias for C_C_D.  In this case, the base constructor   may move it on us, and we must keep track of such deviations.   If INIT resolves to a CALL_EXPR which happens to return   something of the type we are looking for, then we know   that we can safely use that call to perform the   initialization.   The virtual function table pointer cannot be set up here, because   we do not really know its type.   Virtual baseclass pointers are also set up here.   This never calls operator=().   When initializing, nothing is CONST.   A default copy constructor may have to be used to perform the   initialization.   A constructor or a conversion operator may have to be used to   perform the initialization, but not both, as it would be ambiguous.   */voidexpand_aggr_init (exp, init, alias_this, flags)     tree exp, init;     int alias_this;     int flags;{  tree type = TREE_TYPE (exp);  int was_const = TREE_READONLY (exp);  int was_volatile = TREE_THIS_VOLATILE (exp);  if (init == error_mark_node)    return;  TREE_READONLY (exp) = 0;  TREE_THIS_VOLATILE (exp) = 0;  if (init && TREE_CODE (init) != TREE_LIST)    flags |= LOOKUP_ONLYCONVERTING;  if (TREE_CODE (type) == ARRAY_TYPE)    {      /* Must arrange to initialize each element of EXP	 from elements of INIT.  */      tree itype = init ? TREE_TYPE (init) : NULL_TREE;      if (TYPE_READONLY (TREE_TYPE (type)) || TYPE_VOLATILE (TREE_TYPE (type)))	{	  TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);	  if (init)	    TREE_TYPE (init) = TYPE_MAIN_VARIANT (itype);	}      if (init && TREE_TYPE (init) == NULL_TREE)	{	  /* Handle bad initializers like:	     class COMPLEX {	     public:	       double re, im;	       COMPLEX(double r = 0.0, double i = 0.0) {re = r; im = i;};	       ~COMPLEX() {};	     };	     int main(int argc, char **argv) {	       COMPLEX zees(1.0, 0.0)[10];	     }	  */	  error ("bad array initializer");	  return;	}      expand_vec_init (exp, exp, array_type_nelts (type), init,		       init && comptypes (TREE_TYPE (init), TREE_TYPE (exp), 1));      TREE_READONLY (exp) = was_const;      TREE_THIS_VOLATILE (exp) = was_volatile;      TREE_TYPE (exp) = type;      if (init)	TREE_TYPE (init) = itype;      return;    }  if (TREE_CODE (exp) == VAR_DECL || TREE_CODE (exp) == PARM_DECL)    /* just know that we've seen something for this node */    TREE_USED (exp) = 1;#if 0  /* If initializing from a GNU C CONSTRUCTOR, consider the elts in the     constructor as parameters to an implicit GNU C++ constructor.  */  if (init && TREE_CODE (init) == CONSTRUCTOR      && TYPE_HAS_CONSTRUCTOR (type)      && TREE_TYPE (init) == type)    init = CONSTRUCTOR_ELTS (init);#endif  TREE_TYPE (exp) = TYPE_MAIN_VARIANT (type);  expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,		      init, alias_this, LOOKUP_NORMAL|flags);  TREE_TYPE (exp) = type;  TREE_READONLY (exp) = was_const;  TREE_THIS_VOLATILE (exp) = was_volatile;}static voidexpand_default_init (binfo, true_exp, exp, type, init, alias_this, flags)     tree binfo;     tree true_exp, exp;     tree type;     tree init;     int alias_this;     int flags;{  /* It fails because there may not be a constructor which takes     its own type as the first (or only parameter), but which does     take other types via a conversion.  So, if the thing initializing     the expression is a unit element of type X, first try X(X&),     followed by initialization by X.  If neither of these work     out, then look hard.  */  tree rval;  tree parms;  if (init == NULL_TREE      || (TREE_CODE (init) == TREE_LIST && ! TREE_TYPE (init)))    {      parms = init;      if (parms)	init = TREE_VALUE (parms);    }  else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init)	   && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (init)))    {      rval = convert_for_initialization (exp, type, init, 0, 0, 0, 0);      TREE_USED (rval) = 1;      expand_expr_stmt (rval);      return;    }  else    parms = build_tree_list (NULL_TREE, init);  if (TYPE_USES_VIRTUAL_BASECLASSES (type))    {      if (true_exp == exp)	parms = tree_cons (NULL_TREE, integer_one_node, parms);      else	parms = tree_cons (NULL_TREE, integer_zero_node, parms);      flags |= LOOKUP_HAS_IN_CHARGE;    }  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, constructor_name_full (type),				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_decl);	      expand_assignment (current_class_decl, 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.

⌨️ 快捷键说明

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