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

📄 cp-cvt.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
    if (! can_be_private)      {	if (msgp)	  *msgp = TREE_PRIVATE (fndecl)	    ? "conversion to type `%s' is private"	    : "conversion to type `%s' is from private base class";	return error_mark_node;      }  if (visibility == visibility_protected)    if (! can_be_protected)      {	if (msgp)	  *msgp = TREE_PRIVATE (fndecl)	    ? "conversion to type `%s' is protected"	    : "conversion to type `%s' is from protected base class";	return error_mark_node;      }  function = fndecl; found_and_ok:  /* It will convert, but we don't do anything about it yet.  */  if (msgp == 0)    return NULL_TREE;  fntype = TREE_TYPE (function);  if (DECL_INLINE (function) && TREE_CODE (function) == FUNCTION_DECL)    function = build1 (ADDR_EXPR, build_pointer_type (fntype), function);  else    function = default_conversion (function);  result = build_nt (CALL_EXPR, function,		     convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),					parmlist, NULL_TREE, LOOKUP_NORMAL),		     NULL_TREE);  TREE_TYPE (result) = TREE_TYPE (fntype);  TREE_SIDE_EFFECTS (result) = 1;  TREE_RAISES (result) = !! TYPE_RAISES_EXCEPTIONS (fntype);  return result;}/* Call this when we know (for any reason) that expr is   not, in fact, zero.  */treeconvert_pointer_to (binfo, expr)     tree binfo, expr;{  register tree intype = TREE_TYPE (expr);  tree ptr_type;  tree type, rval;  if (TREE_CODE (binfo) == TREE_VEC)    type = BINFO_TYPE (binfo);  else if (IS_AGGR_TYPE (binfo))    {      type = binfo;      binfo = TYPE_BINFO (binfo);    }  else    {      type = binfo;      binfo = NULL_TREE;    }  ptr_type = build_pointer_type (type);  if (ptr_type == TYPE_MAIN_VARIANT (intype))    return expr;  if (intype == error_mark_node)    return error_mark_node;  my_friendly_assert (!integer_zerop (expr), 191);  if (IS_AGGR_TYPE (type)      && IS_AGGR_TYPE (TREE_TYPE (intype))      && type != TYPE_MAIN_VARIANT (TREE_TYPE (intype)))    {      tree path;      int distance = get_base_distance (type, TYPE_MAIN_VARIANT (TREE_TYPE (intype)), 0, &path);      /* This function shouldn't be called with unqualified arguments	 but if it is, give them an error message that they can read.	 */      if (distance < 0)	{	  error ("cannot convert a pointer of type `%s'",		 TYPE_NAME_STRING (TREE_TYPE (intype)));	  error_with_aggr_type (type, "to a pointer of type `%s'");	  return error_mark_node;	}      return build_vbase_path (PLUS_EXPR, ptr_type, expr, path, 1);    }  rval = build1 (NOP_EXPR, ptr_type,		 TREE_CODE (expr) == NOP_EXPR ? TREE_OPERAND (expr, 0) : expr);  TREE_CONSTANT (rval) = TREE_CONSTANT (expr);  return rval;}/* Same as above, but don't abort if we get an "ambiguous" baseclass.   There's only one virtual baseclass we are looking for, and once   we find one such virtual baseclass, we have found them all.  */treeconvert_pointer_to_vbase (binfo, expr)     tree binfo;     tree expr;{  tree intype = TREE_TYPE (TREE_TYPE (expr));  tree binfos = TYPE_BINFO_BASETYPES (intype);  int i;  for (i = TREE_VEC_LENGTH (binfos)-1; i >= 0; i--)    {      tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));      if (BINFO_TYPE (binfo) == basetype)	return convert_pointer_to (binfo, expr);      if (binfo_member (BINFO_TYPE (binfo), CLASSTYPE_VBASECLASSES (basetype)))	return convert_pointer_to_vbase (binfo, convert_pointer_to (basetype, expr));    }  my_friendly_abort (6);  /* NOTREACHED */  return NULL_TREE;}/* Create an expression whose value is that of EXPR,   converted to type TYPE.  The TREE_TYPE of the value   is always TYPE.  This function implements all reasonable   conversions; callers should filter out those that are   not permitted by the language being compiled.  */treeconvert (type, expr)     tree type, expr;{  register tree e = expr;  register enum tree_code code = TREE_CODE (type);  if (type == TREE_TYPE (expr)      || TREE_CODE (expr) == ERROR_MARK)    return expr;  if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr)))    return fold (build1 (NOP_EXPR, type, expr));  if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)    return error_mark_node;  if (TREE_CODE (TREE_TYPE (expr)) == VOID_TYPE)    {      error ("void value not ignored as it ought to be");      return error_mark_node;    }  if (code == VOID_TYPE)    {      tree rval = build_type_conversion (NOP_EXPR, type, e, 0);      /* If we can convert to void type via a type conversion, do so.  */      if (rval)	return rval;      return build1 (CONVERT_EXPR, type, e);    }#if 0  /* This is incorrect.  A truncation can't be stripped this way.     Extensions will be stripped by the use of get_unwidened.  */  if (TREE_CODE (expr) == NOP_EXPR)    return convert (type, TREE_OPERAND (expr, 0));#endif  /* Just convert to the type of the member.  */  if (code == OFFSET_TYPE)    {      type = TREE_TYPE (type);      code = TREE_CODE (type);    }  /* C++ */  if (code == REFERENCE_TYPE)    return fold (convert_to_reference (error_mark_node,				       type, e,				       NULL_TREE, -1, (char *)NULL,				       -1, LOOKUP_NORMAL));  else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)    e = convert_from_reference (e);  if (code == INTEGER_TYPE || code == ENUMERAL_TYPE)    return fold (convert_to_integer (type, e));  if (code == POINTER_TYPE)    return fold (convert_to_pointer (type, e));  if (code == REAL_TYPE)    return fold (convert_to_real (type, e));  /* New C++ semantics:  since assignment is now based on     memberwise copying,  if the rhs type is derived from the     lhs type, then we may still do a conversion.  */  if (IS_AGGR_TYPE_CODE (code))    {      tree dtype = TREE_TYPE (e);      if (TREE_CODE (dtype) == REFERENCE_TYPE)	{	  e = convert_from_reference (e);	  dtype = TREE_TYPE (e);	}      dtype = TYPE_MAIN_VARIANT (dtype);      /* Conversion between aggregate types.  New C++ semantics allow	 objects of derived type to be cast to objects of base type.	 Old semantics only allowed this between pointers.	 There may be some ambiguity between using a constructor	 vs. using a type conversion operator when both apply.  */      if (IS_AGGR_TYPE (dtype))	{	  tree binfo;	  tree conversion = TYPE_HAS_CONVERSION (dtype)	    ? build_type_conversion (CONVERT_EXPR, type, e, 1) : NULL_TREE;	  if (TYPE_HAS_CONSTRUCTOR (type))	    {	      tree rval = build_method_call (NULL_TREE, constructor_name (type),					     build_tree_list (NULL_TREE, e),					     TYPE_BINFO (type),					     conversion ? LOOKUP_NO_CONVERSION : 0);	      if (rval != error_mark_node)		{		  if (conversion)		    {		      error ("both constructor and type conversion operator apply");		      return error_mark_node;		    }		  /* call to constructor successful.  */		  rval = build_cplus_new (type, rval, 0);		  return rval;		}	    }	  /* Type conversion successful/applies.  */	  if (conversion)	    {	      if (conversion == error_mark_node)		error ("ambiguous pointer conversion");	      return conversion;	    }	  /* now try normal C++ assignment semantics.  */	  binfo = TYPE_BINFO (dtype);	  if (BINFO_TYPE (binfo) == type	      || (binfo = get_binfo (type, dtype, 1)))	    {	      if (binfo == error_mark_node)		return error_mark_node;	    }	  if (binfo != NULL_TREE)	    {	      if (lvalue_p (e))		{		  e = build_unary_op (ADDR_EXPR, e, 0);		  if (! BINFO_OFFSET_ZEROP (binfo))		    e = build (PLUS_EXPR, TYPE_POINTER_TO (type),			       e, BINFO_OFFSET (binfo));		  return build1 (INDIRECT_REF, type, e);		}	      sorry ("addressable aggregates");	      return error_mark_node;	    }	  error ("conversion between incompatible aggregate types requested");	  return error_mark_node;	}      /* conversion from non-aggregate to aggregate type requires constructor.  */      else if (TYPE_HAS_CONSTRUCTOR (type))	{	  tree rval;	  tree init = build_method_call (NULL_TREE, constructor_name (type),					 build_tree_list (NULL_TREE, e),					 TYPE_BINFO (type), LOOKUP_NORMAL);	  if (init == error_mark_node)	    {	      error_with_aggr_type (type, "in conversion to type `%s'");	      return error_mark_node;	    }	  rval = build_cplus_new (type, init, 0);	  return rval;	}    }  /* If TYPE or TREE_TYPE (EXPR) is not on the permanent_obstack,     then the it won't be hashed and hence compare as not equal,     even when it is.  */  if (code == ARRAY_TYPE      && TREE_TYPE (TREE_TYPE (expr)) == TREE_TYPE (type)      && index_type_equal (TYPE_DOMAIN (TREE_TYPE (expr)), TYPE_DOMAIN (type)))    return expr;  error ("conversion to non-scalar type requested");  return error_mark_node;}/* Like convert, except permit conversions to take place which   are not normally allowed due to visibility restrictions   (such as conversion from sub-type to private super-type).  */treeconvert_force (type, expr)     tree type;     tree expr;{  register tree e = expr;  register enum tree_code code = TREE_CODE (type);  if (code == REFERENCE_TYPE)    return fold (convert_to_reference (0, type, e,				       NULL_TREE, -1, (char *)NULL,				       -1, 0));  else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)    e = convert_from_reference (e);  if (code == POINTER_TYPE)    return fold (convert_to_pointer_force (type, e));  {    int old_equiv = flag_int_enum_equivalence;    flag_int_enum_equivalence = 1;    e = convert (type, e);    flag_int_enum_equivalence = old_equiv;  }  return e;}/* Subroutine of build_type_conversion.  */static treebuild_type_conversion_1 (xtype, basetype, expr, typename, for_sure)     tree xtype, basetype;     tree expr;     tree typename;     int for_sure;{  tree first_arg = expr;  tree rval;  int flags;  if (for_sure == 0)    {      if (! lvalue_p (expr))	first_arg = build1 (NOP_EXPR, TYPE_POINTER_TO (basetype), integer_zero_node);      flags = LOOKUP_PROTECT;    }  else    flags = LOOKUP_NORMAL;  rval = build_method_call (first_arg, constructor_name (typename),			    NULL_TREE, NULL_TREE, flags);  if (rval == error_mark_node)    {      if (for_sure == 0)	return NULL_TREE;      return error_mark_node;    }  if (first_arg != expr)    {      expr = build_up_reference (build_reference_type (TREE_TYPE (expr)), expr,				 LOOKUP_COMPLAIN, 1);      TREE_VALUE (TREE_OPERAND (rval, 1)) = build_unary_op (ADDR_EXPR, expr, 0);    }  if (TREE_CODE (TREE_TYPE (rval)) == REFERENCE_TYPE      && TREE_CODE (xtype) != REFERENCE_TYPE)    rval = default_conversion (rval);  if (pedantic      && TREE_TYPE (xtype)      && (TREE_READONLY (TREE_TYPE (TREE_TYPE (rval)))	  > TREE_READONLY (TREE_TYPE (xtype))))    pedwarn ("user-defined conversion casting away `const'");  return convert (xtype, rval);}/* Convert an aggregate EXPR to type XTYPE.  If a conversion   exists, return the attempted conversion.  This may   return ERROR_MARK_NODE if the conversion is not   allowed (references private members, etc).   If no conversion exists, NULL_TREE is returned.   If (FOR_SURE & 1) is non-zero, then we allow this type conversion   to take place immediately.  Otherwise, we build a SAVE_EXPR   which can be evaluated if the results are ever needed.   If FOR_SURE >= 2, then we only look for exact conversions.   TYPE may be a reference type, in which case we first look   for something that will convert to a reference type.  If   that fails, we will try to look for something of the   reference's target type, and then return a reference to that.  */treebuild_type_conversion (code, xtype, expr, for_sure)     enum tree_code code;     tree xtype, expr;     int for_sure;{  /* C++: check to see if we can convert this aggregate type     into the required scalar type.  */  tree type, type_default;  tree typename = build_typename_overload (xtype), *typenames;  int n_variants = 0;  tree basetype, save_basetype;  tree rval;  int exact_conversion = for_sure >= 2;  for_sure &= 1;  if (expr == error_mark_node)    return error_mark_node;  basetype = TREE_TYPE (expr);  if (TREE_CODE (basetype) == REFERENCE_TYPE)    basetype = TREE_TYPE (basetype);  basetype = TYPE_MAIN_VARIANT (basetype);  if (! TYPE_LANG_SPECIFIC (basetype) || ! TYPE_HAS_CONVERSION (basetype))    return 0;  if (TREE_CODE (xtype) == POINTER_TYPE      || TREE_CODE (xtype) == REFERENCE_TYPE)    {      /* Prepare to match a variant of this type.  */

⌨️ 快捷键说明

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