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

📄 init.c

📁 GCC编译器源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
      int pos;      if (TREE_VIA_VIRTUAL (base_binfo))	continue;      for (x = current_base_init_list, pos = 0; x; x = TREE_CHAIN (x), ++pos)	{	  tree binfo = TREE_PURPOSE (x);	  if (binfo == NULL_TREE)	    continue;	  if (binfo == base_binfo)	    {	      if (warn_reorder)		{		  if (pos < last_pos)		    {		      cp_warning_at ("base initializers for `%#T'", last_base);		      cp_warning_at ("  and `%#T'", BINFO_TYPE (binfo));		      warning ("  will be re-ordered to match inheritance order");		    }		  last_pos = pos;		  last_base = BINFO_TYPE (binfo);		}	      /* Make sure we won't try to work on this init again.  */	      TREE_PURPOSE (x) = NULL_TREE;	      x = build_tree_list (binfo, TREE_VALUE (x));	      goto got_it;	    }	}      /* If we didn't find BASE_BINFO in the list, create a dummy entry	 so the two lists (RBASES and the list of bases) will be	 symmetrical.  */      x = build_tree_list (NULL_TREE, NULL_TREE);    got_it:      rbases = chainon (rbases, x);    }  *rbase_ptr = rbases;  *vbase_ptr = vbases;}/* Perform partial cleanups for a base for exception handling.  */static treebuild_partial_cleanup_for (binfo)     tree binfo;{  return build_scoped_method_call    (current_class_ref, binfo, dtor_identifier,     build_expr_list (NULL_TREE, integer_zero_node));}/* Perform whatever initializations have yet to be done on the base   class of the class variable.  These actions are in the global   variable CURRENT_BASE_INIT_LIST.  Such an action could be   NULL_TREE, meaning that the user has explicitly called the base   class constructor with no arguments.   If there is a need for a call to a constructor, we must surround   that call with a pushlevel/poplevel pair, since we are technically   at the PARM level of scope.   Argument IMMEDIATELY, if zero, forces a new sequence to be   generated to contain these new insns, so it can be emitted later.   This sequence is saved in the global variable BASE_INIT_EXPR.   Otherwise, the insns are emitted into the current sequence.   Note that emit_base_init does *not* initialize virtual base   classes.  That is done specially, elsewhere.  */extern tree base_init_expr, rtl_expr_chain;voidemit_base_init (t, immediately)     tree t;     int immediately;{  tree member;  tree mem_init_list;  tree rbase_init_list, vbase_init_list;  tree t_binfo = TYPE_BINFO (t);  tree binfos = BINFO_BASETYPES (t_binfo);  int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;  tree expr = NULL_TREE;  if (! immediately)    {      int momentary;      do_pending_stack_adjust ();      /* Make the RTL_EXPR node temporary, not momentary,	 so that rtl_expr_chain doesn't become garbage.  */      momentary = suspend_momentary ();      expr = make_node (RTL_EXPR);      resume_momentary (momentary);      start_sequence_for_rtl_expr (expr);     }  if (write_symbols == NO_DEBUG)    /* As a matter of principle, `start_sequence' should do this.  */    emit_note (0, -1);  else    /* Always emit a line number note so we can step into constructors.  */    emit_line_note_force (DECL_SOURCE_FILE (current_function_decl),			  DECL_SOURCE_LINE (current_function_decl));  mem_init_list = sort_member_init (t);  current_member_init_list = NULL_TREE;  sort_base_init (t, &rbase_init_list, &vbase_init_list);  current_base_init_list = NULL_TREE;  if (TYPE_USES_VIRTUAL_BASECLASSES (t))    {      tree first_arg = TREE_CHAIN (DECL_ARGUMENTS (current_function_decl));      expand_start_cond (first_arg, 0);      expand_aggr_vbase_init (t_binfo, current_class_ref, current_class_ptr,			      vbase_init_list);      expand_end_cond ();    }  /* Now, perform initialization of non-virtual base classes.  */  for (i = 0; i < n_baseclasses; i++)    {      tree base_binfo = TREE_VEC_ELT (binfos, i);      tree init = void_list_node;      if (TREE_VIA_VIRTUAL (base_binfo))	continue;#if 0 /* Once unsharing happens soon enough.  */      my_friendly_assert (BINFO_INHERITANCE_CHAIN (base_binfo) == t_binfo, 999);#else      BINFO_INHERITANCE_CHAIN (base_binfo) = t_binfo;#endif      if (TREE_PURPOSE (rbase_init_list))	init = TREE_VALUE (rbase_init_list);      else if (TYPE_NEEDS_CONSTRUCTING (BINFO_TYPE (base_binfo)))	{	  init = NULL_TREE;	  if (extra_warnings && copy_args_p (current_function_decl))	    cp_warning ("base class `%#T' should be explicitly initialized in the copy constructor",			BINFO_TYPE (base_binfo));	}      if (init != void_list_node)	{	  expand_start_target_temps ();	  member = convert_pointer_to_real (base_binfo, current_class_ptr);	  expand_aggr_init_1 (base_binfo, NULL_TREE,			      build_indirect_ref (member, NULL_PTR), init,			      BINFO_OFFSET_ZEROP (base_binfo), LOOKUP_NORMAL);	  expand_end_target_temps ();	  free_temp_slots ();	}      if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (base_binfo)))	{	  tree expr;	  /* All cleanups must be on the function_obstack.  */	  push_obstacks_nochange ();	  resume_temporary_allocation ();	  expr = build_partial_cleanup_for (base_binfo);	  pop_obstacks ();	  add_partial_entry (expr);	}      rbase_init_list = TREE_CHAIN (rbase_init_list);    }  /* Initialize all the virtual function table fields that     do come from virtual base classes.  */  if (TYPE_USES_VIRTUAL_BASECLASSES (t))    expand_indirect_vtbls_init (t_binfo, current_class_ref, current_class_ptr);  /* Initialize all the virtual function table fields that     do not come from virtual base classes.  */  expand_direct_vtbls_init (t_binfo, t_binfo, 1, 1, current_class_ptr);  for (member = TYPE_FIELDS (t); member; member = TREE_CHAIN (member))    {      tree init, name;      int from_init_list;      /* member could be, for example, a CONST_DECL for an enumerated	 tag; we don't want to try to initialize that, since it already	 has a value.  */      if (TREE_CODE (member) != FIELD_DECL || !DECL_NAME (member))	continue;      /* See if we had a user-specified member initialization.  */      if (TREE_PURPOSE (mem_init_list))	{	  name = TREE_PURPOSE (mem_init_list);	  init = TREE_VALUE (mem_init_list);	  from_init_list = 1;#if 0	  if (TREE_CODE (name) == COMPONENT_REF)	    name = DECL_NAME (TREE_OPERAND (name, 1));#else	  /* Also see if it's ever a COMPONENT_REF here.  If it is, we	     need to do `expand_assignment (name, init, 0, 0);' and	     a continue.  */	  my_friendly_assert (TREE_CODE (name) != COMPONENT_REF, 349);#endif	}      else	{	  name = DECL_NAME (member);	  init = DECL_INITIAL (member);	  from_init_list = 0;	  /* Effective C++ rule 12.  */	  if (warn_ecpp && init == NULL_TREE	      && !DECL_ARTIFICIAL (member)	      && TREE_CODE (TREE_TYPE (member)) != ARRAY_TYPE)	    cp_warning ("`%D' should be initialized in the member initialization list", member);	    	}      perform_member_init (member, name, init, from_init_list);      mem_init_list = TREE_CHAIN (mem_init_list);    }  /* Now initialize any members from our bases.  */  while (mem_init_list)    {      tree name, init, field;      if (TREE_PURPOSE (mem_init_list))	{	  name = TREE_PURPOSE (mem_init_list);	  init = TREE_VALUE (mem_init_list);	  /* XXX: this may need the COMPONENT_REF operand 0 check if	     it turns out we actually get them.  */	  field = IDENTIFIER_CLASS_VALUE (name);	  /* 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)		cp_error ("field `%D' not in immediate context", field);	    }#if 0	  /* It turns out if you have an anonymous union in the	     class, a member from it can end up not being on the	     list of fields (rather, the type is), and therefore	     won't be seen by the for loop above.  */	  /* The code in this for loop is derived from a general loop	     which had this check in it.  Theoretically, we've hit	     every initialization for the list of members in T, so	     we shouldn't have anything but these left in this list.  */	  my_friendly_assert (DECL_FIELD_CONTEXT (field) != t, 351);#endif	  perform_member_init (field, name, init, 1);	}      mem_init_list = TREE_CHAIN (mem_init_list);    }  if (! immediately)    {      do_pending_stack_adjust ();      my_friendly_assert (base_init_expr == 0, 207);      base_init_expr = expr;      TREE_TYPE (expr) = void_type_node;      RTL_EXPR_RTL (expr) = const0_rtx;      RTL_EXPR_SEQUENCE (expr) = get_insns ();      rtl_expr_chain = tree_cons (NULL_TREE, expr, rtl_expr_chain);      end_sequence ();      TREE_SIDE_EFFECTS (expr) = 1;    }  /* 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))      cp_error ("field `%D' used before initialized (after assignment to `this')",		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.  */static voidexpand_virtual_init (binfo, decl)     tree binfo, decl;{  tree type = BINFO_TYPE (binfo);  tree vtbl, vtbl_ptr;  tree vtype, vtype_binfo;  /* This code is crusty.  Should be simple, like:     vtbl = BINFO_VTABLE (binfo);     */  vtype = DECL_CONTEXT (CLASSTYPE_VFIELD (type));  vtype_binfo = get_binfo (vtype, TREE_TYPE (TREE_TYPE (decl)), 0);  vtbl = BINFO_VTABLE (binfo_value (DECL_FIELD_CONTEXT (CLASSTYPE_VFIELD (type)), binfo));  assemble_external (vtbl);  TREE_USED (vtbl) = 1;  vtbl = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (vtbl)), vtbl);  decl = convert_pointer_to_real (vtype_binfo, decl);  vtbl_ptr = build_vfield_ref (build_indirect_ref (decl, NULL_PTR), vtype);  if (vtbl_ptr == error_mark_node)    return;  /* Have to convert VTBL since array sizes may be different.  */  vtbl = convert_force (TREE_TYPE (vtbl_ptr), vtbl, 0);  expand_expr_stmt (build_modify_expr (vtbl_ptr, NOP_EXPR, 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 = purpose_member (binfo, init_list);  tree ref = build_indirect_ref (addr, NULL_PTR);  expand_start_target_temps ();  if (init)    init = TREE_VALUE (init);  /* Call constructors, but don't set up vtables.  */  expand_aggr_init_1 (binfo, exp, ref, init, 0, LOOKUP_COMPLAIN);  expand_end_target_temps ();  free_temp_slots ();}/* 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));      for (vbases = CLASSTYPE_VBASECLASSES (type); vbases;	   vbases = TREE_CHAIN (vbases))	{	  tree tmp = purpose_member (vbases, result);	  expand_aggr_vbase_init_1 (vbases, exp,				    TREE_OPERAND (TREE_VALUE (tmp), 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_ptr);  expand_member_init (build_indirect_ref (base, NULL_PTR), name, init);}/* Find the context in which this FIELD can be initialized.  */static treeinitializing_context (field)     tree field;{  tree t = DECL_CONTEXT (field);  /* Anonymous union members can be initialized in the first enclosing     non-anonymous union context.  */  while (t && ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))    t = TYPE_CONTEXT (t);  return t;}/* 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.

⌨️ 快捷键说明

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