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

📄 cp-init.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
  for (vbases = CLASSTYPE_VBASECLASSES (t); vbases; vbases = TREE_CHAIN (vbases))    CLEAR_BINFO_BASEINIT_MARKED (vbases);  /* Initialize all the virtual function table fields that     do not come from virtual base classes.  */  init_vfields (t, t, 0);  if (CLASSTYPE_NEEDS_VIRTUAL_REINIT (t)#ifdef SOS       || TYPE_DYNAMIC (t)#endif       )    expand_expr_stmt (build_virtual_init (TYPE_BINFO (t), t,					  current_class_decl));  /* Members we through expand_member_init.  We initialize all the members     needing initialization that did not get it so far.  */  for (; current_member_init_list;       current_member_init_list = TREE_CHAIN (current_member_init_list))    {      tree name = TREE_PURPOSE (current_member_init_list);      tree init = TREE_VALUE (current_member_init_list);      tree field = (TREE_CODE (name) == COMPONENT_REF		    ? TREE_OPERAND (name, 1) : IDENTIFIER_CLASS_VALUE (name));      tree type;            /* If one member shadows another, get the outermost one.  */      if (TREE_CODE (field) == TREE_LIST)	{	  field = TREE_VALUE (field);	  if (decl_type_context (field) != current_class_type)	    error ("field `%s' not in immediate context");	}      type = TREE_TYPE (field);      if (TREE_STATIC (field))	{	  error_with_aggr_type (DECL_FIELD_CONTEXT (field),				"field `%s::%s' is static; only point of initialization is its declaration", IDENTIFIER_POINTER (name));	  continue;	}      if (DECL_NAME (field))	{	  if (TREE_HAS_CONSTRUCTOR (field))	    error ("multiple initializations given for member `%s'",		   IDENTIFIER_POINTER (DECL_NAME (field)));	}      /* Mark this node as having been initialized.  */      TREE_HAS_CONSTRUCTOR (field) = 1;      if (DECL_FIELD_CONTEXT (field) != t)	fields_to_unmark = tree_cons (NULL_TREE, field, fields_to_unmark);      if (TREE_CODE (name) == COMPONENT_REF)	{	  /* Initialization of anonymous union.  */	  expand_assignment (name, init, 0, 0);	  continue;	}      decl = build_component_ref (C_C_D, name, 0, 1);      if (TYPE_NEEDS_CONSTRUCTING (type))	{	  if (TREE_CODE (type) == ARRAY_TYPE	      && TREE_CHAIN (init) == NULL_TREE	      && TREE_CODE (TREE_TYPE (TREE_VALUE (init))) == ARRAY_TYPE)	    {	      /* Initialization of one array from another.  */	      expand_vec_init (TREE_OPERAND (decl, 1), decl,			       array_type_nelts (type), TREE_VALUE (init), 1);	    }	  else	    expand_aggr_init (decl, init, 0);	}      else	{	  if (init == NULL_TREE)	    {	      error ("types without constructors must have complete initializers");	      init = error_mark_node;	    }	  else if (TREE_CHAIN (init))	    {	      warning ("initializer list treated as compound expression");	      init = build_compound_expr (init);	    }	  else	    init = TREE_VALUE (init);	  expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));	}      if (flag_handle_exceptions == 2 && TYPE_NEEDS_DESTRUCTOR (type))	{	  cplus_expand_start_try (1);	  push_exception_cleanup (build_unary_op (ADDR_EXPR, decl, 0));	}    }  for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))    {      /* All we care about is this unique member.  It contains	 all the information we need to know, and that right early.  */      tree type = TREE_TYPE (member);      tree init = TREE_HAS_CONSTRUCTOR (member)	? error_mark_node : DECL_INITIAL (member);      /* Unmark this field.  If it is from an anonymous union,         then unmark the field recursively.  */      TREE_HAS_CONSTRUCTOR (member) = 0;      if (TREE_ANON_UNION_ELEM (member))	emit_base_init (TREE_TYPE (member), 1);      /* Member had explicit initializer.  */      if (init == error_mark_node)	continue;      if (TREE_CODE (member) != FIELD_DECL)	continue;      if (type == error_mark_node)	continue;      if (TYPE_NEEDS_CONSTRUCTING (type))	{	  if (init)	    init = build_tree_list (NULL_TREE, init);	  decl = build_component_ref (C_C_D, DECL_NAME (member), 0, 0);	  expand_aggr_init (decl, init, 0);	}      else	{	  if (init)	    {	      decl = build_component_ref (C_C_D, DECL_NAME (member), 0, 0);	      expand_expr_stmt (build_modify_expr (decl, INIT_EXPR, init));	    }	  else if (TREE_CODE (TREE_TYPE (member)) == REFERENCE_TYPE)	    warning ("uninitialized reference member `%s'",		     IDENTIFIER_POINTER (DECL_NAME (member)));	}      if (flag_handle_exceptions == 2 && TYPE_NEEDS_DESTRUCTOR (type))	{	  cplus_expand_start_try (1);	  push_exception_cleanup (build_unary_op (ADDR_EXPR, decl, 0));	}    }  /* Unmark fields which are initialized for the base class.  */  while (fields_to_unmark)    {      TREE_HAS_CONSTRUCTOR (TREE_VALUE (fields_to_unmark)) = 0;      fields_to_unmark = TREE_CHAIN (fields_to_unmark);    }  /* It is possible for the initializers to need cleanups.     Expand those cleanups now that all the initialization     has been done.  */  expand_cleanups_to (NULL_TREE);  if (! immediately)    {      extern rtx base_init_insns;      do_pending_stack_adjust ();      my_friendly_assert (base_init_insns == 0, 207);      base_init_insns = get_insns ();      end_sequence ();    }  /* All the implicit try blocks we built up will be zapped     when we come to a real binding contour boundary.  */}/* Check that all fields are properly initialized after   an assignment to `this'.  */voidcheck_base_init (t)     tree t;{  tree member;  for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))    if (DECL_NAME (member) && TREE_USED (member))      error ("field `%s' used before initialized (after assignment to `this')",	     IDENTIFIER_POINTER (DECL_NAME (member)));}/* This code sets up the virtual function tables appropriate for   the pointer DECL.  It is a one-ply initialization.   BINFO is the exact type that DECL is supposed to be.  In   multiple inheritance, this might mean "C's A" if C : A, B.  */treebuild_virtual_init (main_binfo, binfo, decl)     tree main_binfo, binfo;     tree decl;{  tree type;  tree vtbl, vtbl_ptr;  tree vtype;  if (TREE_CODE (binfo) == TREE_VEC)    type = BINFO_TYPE (binfo);  else if (TREE_CODE (binfo) == RECORD_TYPE)    {      type = binfo;      binfo = TYPE_BINFO (type);    }  else    my_friendly_abort (46);  vtype = DECL_CONTEXT (CLASSTYPE_VFIELD (type));#if 0  /* This code suggests that it's time to rewrite how we handle     replicated baseclasses in G++.  */  if (get_base_distance (vtype, TREE_TYPE (TREE_TYPE (decl)), 0, 0) == -2)    {      tree binfos = TYPE_BINFO_BASETYPES (TREE_TYPE (TREE_TYPE (decl)));      int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;      tree result = NULL_TREE;      for (i = n_baselinks-1; i >= 0; i--)	{	  tree base_binfo = TREE_VEC_ELT (binfos, i);	  tree this_decl;	  if (get_base_distance (vtype, BINFO_TYPE (base_binfo), 0, 0) == -1)	    continue;	  if (TREE_VIA_VIRTUAL (base_binfo))	    this_decl = build_vbase_pointer (build_indirect_ref (decl), BINFO_TYPE (base_binfo));	  else if (BINFO_OFFSET_ZEROP (base_binfo))	    this_decl = build1 (NOP_EXPR, TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),				decl);	  else	    this_decl = build (PLUS_EXPR, TYPE_POINTER_TO (BINFO_TYPE (base_binfo)),			       decl, BINFO_OFFSET (base_binfo));	  result = tree_cons (NULL_TREE, build_virtual_init (main_binfo, base_binfo, this_decl), result);	}      return build_compound_expr (result);    }#endif#ifdef SOS  if (TYPE_DYNAMIC (type))    vtbl = build1 (NOP_EXPR, ptr_type_node, lookup_name (get_identifier (AUTO_VTABLE_NAME), 0));  else#endif    {#if 1      vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)),					BINFO_TYPE (main_binfo), 0));#else      my_friendly_assert (BINFO_TYPE (main_binfo) == BINFO_TYPE (binfo), 208);      vtbl = BINFO_VTABLE (main_binfo);#endif /* 1 */      assemble_external (vtbl);      TREE_USED (vtbl) = 1;      vtbl = build1 (ADDR_EXPR, TYPE_POINTER_TO (TREE_TYPE (vtbl)), vtbl);    }  decl = convert_pointer_to (vtype, decl);  vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, 0), vtype);  if (vtbl_ptr == error_mark_node)    return error_mark_node;  /* Have to convert VTBL since array sizes may be different.  */  return build_modify_expr (vtbl_ptr, NOP_EXPR,			    convert (TREE_TYPE (vtbl_ptr), vtbl));}/* Subroutine of `expand_aggr_vbase_init'.   BINFO is the binfo of the type that is being initialized.   INIT_LIST is the list of initializers for the virtual baseclass.  */static voidexpand_aggr_vbase_init_1 (binfo, exp, addr, init_list)     tree binfo, exp, addr, init_list;{  tree init = value_member (BINFO_TYPE (binfo), init_list);  tree ref = build_indirect_ref (addr, 0);  if (init)    init = TREE_PURPOSE (init);  /* Call constructors, but don't set up vtables.  */  expand_aggr_init_1 (binfo, exp, ref, init, 0,		      LOOKUP_PROTECTED_OK|LOOKUP_COMPLAIN|LOOKUP_SPECULATIVELY);  CLEAR_BINFO_VBASE_INIT_MARKED (binfo);}/* Initialize this object's virtual base class pointers.  This must be   done only at the top-level of the object being constructed.   INIT_LIST is list of initialization for constructor to perform.  */static voidexpand_aggr_vbase_init (binfo, exp, addr, init_list)     tree binfo;     tree exp;     tree addr;     tree init_list;{  tree type = BINFO_TYPE (binfo);  if (TYPE_USES_VIRTUAL_BASECLASSES (type))    {      tree result = init_vbase_pointers (type, addr);      tree vbases;      if (result)	expand_expr_stmt (build_compound_expr (result));      /* Mark everything as having an initializer	 (either explicit or default).  */      for (vbases = CLASSTYPE_VBASECLASSES (type);	   vbases; vbases = TREE_CHAIN (vbases))	SET_BINFO_VBASE_INIT_MARKED (vbases);      /* First, initialize baseclasses which could be baseclasses	 for other virtual baseclasses.  */      for (vbases = CLASSTYPE_VBASECLASSES (type);	   vbases; vbases = TREE_CHAIN (vbases))	/* Don't initialize twice.  */	if (BINFO_VBASE_INIT_MARKED (vbases))	  {	    tree tmp = result;	    while (BINFO_TYPE (vbases) != BINFO_TYPE (TREE_PURPOSE (tmp)))	      tmp = TREE_CHAIN (tmp);	    expand_aggr_vbase_init_1 (vbases, exp,				      TREE_OPERAND (TREE_VALUE (tmp), 0),				      init_list);	  }      /* Now initialize the baseclasses which don't have virtual baseclasses.  */      for (; result; result = TREE_CHAIN (result))	/* Don't initialize twice.  */	if (BINFO_VBASE_INIT_MARKED (TREE_PURPOSE (result)))	  {	    my_friendly_abort (47);	    expand_aggr_vbase_init_1 (TREE_PURPOSE (result), exp,				      TREE_OPERAND (TREE_VALUE (result), 0),				      init_list);	  }    }}/* Subroutine to perform parser actions for member initialization.   S_ID is the scoped identifier.   NAME is the name of the member.   INIT is the initializer, or `void_type_node' if none.  */voiddo_member_init (s_id, name, init)     tree s_id, name, init;{  tree binfo, base;  if (current_class_type == NULL_TREE      || ! is_aggr_typedef (s_id, 1))    return;  binfo = get_binfo (IDENTIFIER_TYPE_VALUE (s_id),			  current_class_type, 1);  if (binfo == error_mark_node)    return;  if (binfo == 0)    {      error_not_base_type (IDENTIFIER_TYPE_VALUE (s_id), current_class_type);      return;    }  base = convert_pointer_to (binfo, current_class_decl);  expand_member_init (build_indirect_ref (base), name, init);}/* Function to give error message if member initialization specification   is erroneous.  FIELD is the member we decided to initialize.   TYPE is the type for which the initialization is being performed.   FIELD must be a member of TYPE, or the base type from which FIELD   comes must not need a constructor.      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)    {      error_with_aggr_type (type, "class `%s' does not have any field named `%s'",			    member_name);      return 0;    }  if (DECL_CONTEXT (field) != type      && TYPE_NEEDS_CONSTRUCTOR (DECL_CONTEXT (field)))    {      error ("member `%s' comes from base class needing constructor", member_name);      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'.  */void

⌨️ 快捷键说明

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