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

📄 init.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      MEMBER_NAME is the name of the member.  */static intmember_init_ok_or_else (field, type, member_name)     tree field;     tree type;     char *member_name;{  if (field == error_mark_node)    return 0;  if (field == NULL_TREE || initializing_context (field) != type)    {      cp_error ("class `%T' does not have any field named `%s'", type,		member_name);      return 0;    }  if (TREE_STATIC (field))    {      cp_error ("field `%#D' is static; only point of initialization is its declaration",		field);      return 0;    }  return 1;}/* 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;  if (exp == NULL_TREE)    return;			/* complain about this later */  type = TYPE_MAIN_VARIANT (TREE_TYPE (exp));  if (name && TREE_CODE (name) == TYPE_DECL)    {      basetype = TREE_TYPE (name);      name = DECL_NAME (name);    }  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 || basetype)	{	  tree base_init;	  if (name == NULL_TREE)	    {#if 0	      if (basetype)		name = TYPE_IDENTIFIER (basetype);	      else		{		  error ("no base class to initialize");		  return;		}#endif	    }	  else if (basetype != type		   && ! current_template_parms		   && ! vec_binfo_member (basetype,					  TYPE_BINFO_BASETYPES (type))		   && ! binfo_member (basetype, CLASSTYPE_VBASECLASSES (type)))	    {	      if (IDENTIFIER_CLASS_VALUE (name))		goto try_member;	      if (TYPE_USES_VIRTUAL_BASECLASSES (type))		cp_error ("type `%T' is not an immediate or virtual basetype for `%T'",			  basetype, type);	      else		cp_error ("type `%T' is not an immediate basetype for `%T'",			  basetype, type);	      return;	    }	  if (purpose_member (basetype, current_base_init_list))	    {	      cp_error ("base class `%T' already initialized", basetype);	      return;	    }	  if (warn_reorder && current_member_init_list)	    {	      cp_warning ("base initializer for `%T'", basetype);	      warning ("   will be re-ordered to precede member initializations");	    }	  base_init = build_tree_list (basetype, init);	  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))	    {	      cp_error ("field `%D' already initialized", field);	      return;	    }	  member_init = build_tree_list (name, init);	  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));      parm = build_component_ref (exp, name, NULL_TREE, 0);      /* Now get to the constructors.  */      fndecl = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), 0);      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, ctor_identifier, init,				  TYPE_BINFO (type), 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, NULL_TREE, 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 current_class_ref.  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, init, alias_this, flags)     tree binfo;     tree true_exp, exp;     tree init;     int alias_this;     int flags;{  tree type = TREE_TYPE (exp);  /* 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 (flag_ansi_overloading && init && TREE_CODE (init) != TREE_LIST      && (flags & LOOKUP_ONLYCONVERTING))    {      /* Base subobjects should only get direct-initialization.  */      if (true_exp != exp)	abort ();      /* We special-case TARGET_EXPRs here to avoid an error about	 private copy constructors for temporaries bound to reference vars.	 If the TARGET_EXPR represents a call to a function that has	 permission to create such objects, a reference can bind directly	 to the return value.  An object variable must be initialized	 via the copy constructor, even if the call is elided.  */      if (! (TREE_CODE (exp) == VAR_DECL && DECL_ARTIFICIAL (exp)	     && TREE_CODE (init) == TARGET_EXPR && TREE_TYPE (init) == type))	init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);      if (TREE_CODE (init) == TRY_CATCH_EXPR)	/* We need to protect the initialization of a catch parm	   with a call to terminate(), which shows up as a TRY_CATCH_EXPR	   around the TARGET_EXPR for the copy constructor.  See	   expand_start_catch_block.  */	TREE_OPERAND (init, 0) = build (INIT_EXPR, TREE_TYPE (exp), exp,					TREE_OPERAND (init, 0));      else	init = build (INIT_EXPR, TREE_TYPE (exp), exp, init);      TREE_SIDE_EFFECTS (init) = 1;      expand_expr_stmt (init);      return;    }  if (init == NULL_TREE      || (TREE_CODE (init) == TREE_LIST && ! TREE_TYPE (init)))    {      parms = init;      if (parms)	init = TREE_VALUE (parms);    }  else if (! flag_ansi_overloading	   && 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_expr_list (NULL_TREE, init);  if (TYPE_USES_VIRTUAL_BASECLASSES (type))    {      if (true_exp == exp)	parms = expr_tree_cons (NULL_TREE, integer_one_node, parms);      else	parms = expr_tree_cons (NULL_TREE, integer_zero_node, parms);      flags |= LOOKUP_HAS_IN_CHARGE;    }  if (flag_ansi_overloading)    {      rval = build_method_call (exp, ctor_identifier,				parms, binfo, flags);

⌨️ 快捷键说明

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