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

📄 cp-init.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
expand_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");	error_with_aggr_type (type, "(type `%s' uses multiple inheritance)");	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);      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 a CONSTRUCTOR, then we emit a warning message,   explaining that such initializations are illegal.   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)     tree exp, init;     int alias_this;{  tree type = TREE_TYPE (exp);  int was_const = TREE_READONLY (exp);  if (init == error_mark_node)    return;  TREE_READONLY (exp) = 0;  if (TREE_CODE (type) == ARRAY_TYPE)    {      /* Must arrange to initialize each element of EXP	 from elements of INIT.  */      int was_const_elts = TYPE_READONLY (TREE_TYPE (type));      tree itype = init ? TREE_TYPE (init) : NULL_TREE;      if (was_const_elts)	{	  tree atype = build_cplus_array_type (TYPE_MAIN_VARIANT (TREE_TYPE (type)),					       TYPE_DOMAIN (type));	  if (init && (TREE_TYPE (exp) == TREE_TYPE (init)))	    TREE_TYPE (init) = atype;	  TREE_TYPE (exp) = atype;	}      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_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 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);  expand_aggr_init_1 (TYPE_BINFO (type), exp, exp,		      init, alias_this, LOOKUP_NORMAL);  TREE_READONLY (exp) = was_const;}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;  int xxref_init_possible;  if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST)    {      parms = init;      if (parms) init = TREE_VALUE (parms);    }  else if (TREE_CODE (init) == INDIRECT_REF && TREE_HAS_CONSTRUCTOR (init))    {      convert_for_initialization (exp, type, init, 0, 0, 0, 0);      expand_expr_stmt (TREE_OPERAND (init, 0));      return;    }  else parms = build_tree_list (NULL_TREE, init);  if (TYPE_HAS_INIT_REF (type)      || init == NULL_TREE      || TREE_CHAIN (parms) != NULL_TREE)    xxref_init_possible = 0;  else    {      xxref_init_possible = LOOKUP_SPECULATIVELY;      flags &= ~LOOKUP_COMPLAIN;    }  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;    }  /* ARM $7.1.1: "[register] may be ignored and in most implementations     it will be ignored if the address of the variable is taken."     Since we're likely to do just that in the ctor call, clear this.  */  DECL_REGISTER (exp) = 0;  rval = build_method_call (exp, constructor_name (type),			    parms, binfo, flags|xxref_init_possible);  if (rval == NULL_TREE && xxref_init_possible)    {      /* It is an error to implement a default copy constructor if	 (see ARM 12.8 for details) ... one case being if another	 copy constructor already exists. */      tree init_type = TREE_TYPE (init);      if (TREE_CODE (init_type) == REFERENCE_TYPE)	init_type = TREE_TYPE (init_type);      if (TYPE_MAIN_VARIANT (init_type) == TYPE_MAIN_VARIANT (type)	  || (IS_AGGR_TYPE (init_type)	      && UNIQUELY_DERIVED_FROM_P (type, init_type)))	{	  if (type == BINFO_TYPE (binfo)	      && TYPE_USES_VIRTUAL_BASECLASSES (type))	    {	      tree addr = build_unary_op (ADDR_EXPR, exp, 0);	      expand_aggr_vbase_init (binfo, exp, addr, NULL_TREE);	      expand_expr_stmt (build_vbase_vtables_init (binfo, binfo,							  exp, addr, 1));	    }	  expand_expr_stmt (build_modify_expr (exp, INIT_EXPR, init));	  return;	}      else	rval = build_method_call (exp, constructor_name (type), parms,				  binfo, flags);    }  /* Private, protected, or otherwise unavailable.  */  if (rval == error_mark_node && (flags&LOOKUP_COMPLAIN))    error_with_aggr_type (binfo, "in base initialization for class `%s'");  /* A valid initialization using constructor.  */  else if (rval != error_mark_node && rval != NULL_TREE)    {      /* 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);    }  else if (parms && TREE_CHAIN (parms) == NULL_TREE)    {      /* If we are initializing one aggregate value	 from another, and though there are constructors,	 and none accept the initializer, just do a bitwise	 copy.	 The above sounds wrong, ``If a class has any copy	 constructor defined, the default copy constructor will	 not be generated.'' 12.8 Copying Class Objects  (mrs)	 @@ This should reject initializer which a constructor	 @@ rejected on visibility gounds, but there is	 @@ no way right now to recognize that case with	 @@ just `error_mark_node'.  */      tree itype;      init = TREE_VALUE (parms);      itype = TREE_TYPE (init);      if (TREE_CODE (itype) == REFERENCE_TYPE)	{	  init = convert_from_reference (init);	  itype = TREE_TYPE (init);	}      itype = TYPE_MAIN_VARIANT (itype);      /* This is currently how the default X(X&) constructor	 is implemented.  */      if (comptypes (TYPE_MAIN_VARIANT (type), itype, 0))	{#if 0	  warning ("bitwise copy in initialization of type `%s'",		   TYPE_NAME_STRING (type));#endif	  rval = build (INIT_EXPR, type, exp, init);	  expand_expr_stmt (rval);	}      else	{

⌨️ 快捷键说明

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