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

📄 init.c

📁 gcc-2.95.3 Linux下最常用的C编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
     tree init;     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;  tree vlist = NULL_TREE;  tree orig_init = init;  if (init && TREE_CODE (init) != TREE_LIST      && (flags & LOOKUP_ONLYCONVERTING))    {      /* Base subobjects should only get direct-initialization.  */      if (true_exp != exp)	abort ();      if (flags & DIRECT_BIND)	/* Do nothing.  We hit this in two cases:  Reference initialization,	   where we aren't initializing a real variable, so we don't want	   to run a new constructor; and catching an exception, where we	   have already built up the constructor call so we could wrap it	   in an exception region.  */;      else	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    parms = build_expr_list (NULL_TREE, init);  if (TYPE_USES_VIRTUAL_BASECLASSES (type))    {      if (TYPE_USES_PVBASES (type))	{	  /* In compatibility mode, when not calling a base ctor,	     we do not pass the vlist argument.  */	  if (true_exp == exp)	    vlist = flag_vtable_thunks_compat? NULL_TREE : vlist_zero_node;	  else	    vlist = lookup_name (vlist_identifier, 0);	      	  if (vlist)	    {	      parms = expr_tree_cons (NULL_TREE, vlist, parms);	      flags |= LOOKUP_HAS_VLIST;	    }	}      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;    }  rval = build_method_call (exp, ctor_identifier,			    parms, binfo, flags);  if (vlist && true_exp != exp && flag_vtable_thunks_compat)    {      rval = no_vlist_base_init (rval, exp, orig_init, binfo, flags);    }  if (TREE_SIDE_EFFECTS (rval))    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.   FLAGS is just passes to `build_method_call'.  See that function for   its description.  */static voidexpand_aggr_init_1 (binfo, true_exp, exp, init, flags)     tree binfo;     tree true_exp, exp;     tree init;     int flags;{  tree type = TREE_TYPE (exp);  my_friendly_assert (init != error_mark_node && type != error_mark_node, 211);  /* Use a function returning the desired type to initialize EXP for us.     If the function is a constructor, and its first argument is     NULL_TREE, know that it was meant for us--just slide exp on     in and expand the constructor.  Constructors now come     as TARGET_EXPRs.  */  if (init && TREE_CODE (exp) == VAR_DECL      && TREE_CODE (init) == CONSTRUCTOR      && TREE_HAS_CONSTRUCTOR (init))    {      tree t = store_init_value (exp, init);      if (!t)	{	  expand_decl_init (exp);	  return;	}      t = build (INIT_EXPR, type, exp, init);      TREE_SIDE_EFFECTS (t) = 1;      expand_expr_stmt (t);      return;    }  /* We know that expand_default_init can handle everything we want     at this point.  */  expand_default_init (binfo, true_exp, exp, init, flags);}/* Report an error if NAME is not the name of a user-defined,   aggregate type.  If OR_ELSE is nonzero, give an error message.  */intis_aggr_typedef (name, or_else)     tree name;     int or_else;{  tree type;  if (name == error_mark_node)    return 0;  if (IDENTIFIER_HAS_TYPE_VALUE (name))    type = IDENTIFIER_TYPE_VALUE (name);  else    {      if (or_else)	cp_error ("`%T' is not an aggregate typedef", name);      return 0;    }  if (! IS_AGGR_TYPE (type)      && TREE_CODE (type) != TEMPLATE_TYPE_PARM      && TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM)    {      if (or_else)	cp_error ("`%T' is not an aggregate type", type);      return 0;    }  return 1;}/* Report an error if TYPE is not a user-defined, aggregate type.  If   OR_ELSE is nonzero, give an error message.  */intis_aggr_type (type, or_else)     tree type;     int or_else;{  if (type == error_mark_node)    return 0;  if (! IS_AGGR_TYPE (type)      && TREE_CODE (type) != TEMPLATE_TYPE_PARM      && TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM)    {      if (or_else)	cp_error ("`%T' is not an aggregate type", type);      return 0;    }  return 1;}/* Like is_aggr_typedef, but returns typedef if successful.  */treeget_aggr_from_typedef (name, or_else)     tree name;     int or_else;{  tree type;  if (name == error_mark_node)    return NULL_TREE;  if (IDENTIFIER_HAS_TYPE_VALUE (name))    type = IDENTIFIER_TYPE_VALUE (name);  else    {      if (or_else)	cp_error ("`%T' fails to be an aggregate typedef", name);      return NULL_TREE;    }  if (! IS_AGGR_TYPE (type)      && TREE_CODE (type) != TEMPLATE_TYPE_PARM      && TREE_CODE (type) != TEMPLATE_TEMPLATE_PARM)    {      if (or_else)	cp_error ("type `%T' is of non-aggregate type", type);      return NULL_TREE;    }  return type;}treeget_type_value (name)     tree name;{  if (name == error_mark_node)    return NULL_TREE;  if (IDENTIFIER_HAS_TYPE_VALUE (name))    return IDENTIFIER_TYPE_VALUE (name);  else    return NULL_TREE;}  /* This code could just as well go in `class.c', but is placed here for   modularity.  *//* For an expression of the form TYPE :: NAME (PARMLIST), build   the appropriate function call.  */treebuild_member_call (type, name, parmlist)     tree type, name, parmlist;{  tree t;  tree method_name;  int dtor = 0;  tree basetype_path, decl;  if (TREE_CODE (name) == TEMPLATE_ID_EXPR      && TREE_CODE (type) == NAMESPACE_DECL)    {      /* 'name' already refers to the decls from the namespace, since we	 hit do_identifier for template_ids.  */      method_name = TREE_OPERAND (name, 0);      /* FIXME: Since we don't do independent names right yet, the	 name might also be a LOOKUP_EXPR. Once we resolve this to a	 real decl earlier, this can go. This may happen during	 tsubst'ing.  */      if (TREE_CODE (method_name) == LOOKUP_EXPR)	{	  method_name = lookup_namespace_name 	    (type, TREE_OPERAND (method_name, 0));	  TREE_OPERAND (name, 0) = method_name;	}      my_friendly_assert (is_overloaded_fn (method_name), 980519);      return build_x_function_call (name, parmlist, current_class_ref);    }  if (type == std_node)    return build_x_function_call (do_scoped_id (name, 0), parmlist,				  current_class_ref);  if (TREE_CODE (type) == NAMESPACE_DECL)    return build_x_function_call (lookup_namespace_name (type, name),				  parmlist, current_class_ref);  if (TREE_CODE (name) == TEMPLATE_ID_EXPR)    {      method_name = TREE_OPERAND (name, 0);      if (TREE_CODE (method_name) == COMPONENT_REF)	method_name = TREE_OPERAND (method_name, 1);      if (is_overloaded_fn (method_name))	method_name = DECL_NAME (OVL_CURRENT (method_name));      TREE_OPERAND (name, 0) = method_name;    }  else    method_name = name;  if (TREE_CODE (method_name) == BIT_NOT_EXPR)    {      method_name = TREE_OPERAND (method_name, 0);      dtor = 1;    }  /* This shouldn't be here, and build_member_call shouldn't appear in     parse.y!  (mrs)  */  if (type && TREE_CODE (type) == IDENTIFIER_NODE      && get_aggr_from_typedef (type, 0) == 0)    {      tree ns = lookup_name (type, 0);      if (ns && TREE_CODE (ns) == NAMESPACE_DECL)	{	  return build_x_function_call (build_offset_ref (type, name), parmlist, current_class_ref);	}    }  if (type == NULL_TREE || ! is_aggr_type (type, 1))    return error_mark_node;  /* An operator we did not like.  */  if (name == NULL_TREE)    return error_mark_node;  if (dtor)    {      cp_error ("cannot call destructor `%T::~%T' without object", type,		method_name);      return error_mark_node;    }  decl = maybe_dummy_object (type, &basetype_path);  /* Convert 'this' to the specified type to disambiguate conversion     to the function's context.  Apparently Standard C++ says that we     shouldn't do this.  */  if (decl == current_class_ref      && ! pedantic      && ACCESSIBLY_UNIQUELY_DERIVED_P (type, current_class_type))    {      tree olddecl = current_class_ptr;      tree oldtype = TREE_TYPE (TREE_TYPE (olddecl));      if (oldtype != type)	{	  tree newtype = build_qualified_type (type, TYPE_QUALS (oldtype));	  decl = convert_force (build_pointer_type (newtype), olddecl, 0);	  decl = build_indirect_ref (decl, NULL_PTR);	}    }  if (method_name == constructor_name (type)      || method_name == constructor_name_full (type))    return build_functional_cast (type, parmlist);  if (lookup_fnfields (basetype_path, method_name, 0))    return build_method_call (decl, 			      TREE_CODE (name) == TEMPLATE_ID_EXPR			      ? name : method_name,			      parmlist, basetype_path,			      LOOKUP_NORMAL|LOOKUP_NONVIRTUAL);  if (TREE_CODE (name) == IDENTIFIER_NODE      && ((t = lookup_field (TYPE_BINFO (type), name, 1, 0))))    {      if (t == error_mark_node)	return error_mark_node;      if (TREE_CODE (t) == FIELD_DECL)	{	  if (is_dummy_object (decl))	    {	      cp_error ("invalid use of non-static field `%D'", t);	      return error_mark_node;	    }	  decl = build (COMPONENT_REF, TREE_TYPE (t), decl, t);	}      else if (TREE_CODE (t) == VAR_DECL)	decl = t;      else	{	  cp_error ("invalid use of member `%D'", t);	  return error_mark_node;	}      if (TYPE_LANG_SPECIFIC (TREE_TYPE (decl)))	return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, decl,			       parmlist, NULL_TREE);      return build_function_call (decl, parmlist);    }  else    {      cp_error ("no method `%T::%D'", type, name);      return error_mark_node;    }}/* Build a reference to a member of an aggregate.  This is not a   C++ `&', but really something which can have its address taken,   and then act as a pointer to member, for example TYPE :: FIELD   can have its address taken by saying & TYPE :: FIELD.   @@ Prints out lousy diagnostics for operator <typename>   @@ fields.   @@ This function should be rewritten and placed in search.c.  */treebuild_offset_ref (type, name)     tree type, name;{  tree decl, t = error_mark_node;  tree member;  tree basebinfo = NULL_TREE;  tree orig_name = name;  /* class templates can come in as TEMPLATE_DECLs here.  */  if (TREE_CODE (name) == TEMPLATE_DECL)    return name;  if (type == std_node)    return do_scoped_id (name, 0);  if (processing_template_decl || uses_template_parms (type))    return build_min_nt (SCOPE_REF, type, name);  /* Handle namespace names fully here.  */  if (TREE_CODE (type) == NAMESPACE_DECL)    {      t = lookup_namespace_name (type, name);      if (t != error_mark_node && ! type_unknown_p (t))	{	  mark_used (t);

⌨️ 快捷键说明

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