cvt.c

来自「GCC编译器源代码」· C语言 代码 · 共 1,673 行 · 第 1/4 页

C
1,673
字号
	  *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);  parmlist = convert_arguments (NULL_TREE, TYPE_ARG_TYPES (fntype),				parmlist, NULL_TREE, LOOKUP_NORMAL);  result = build_call (function, TREE_TYPE (fntype), parmlist);  return result;}/* Call this when we know (for any reason) that expr is not, in fact,   zero.  This routine is like convert_pointer_to, but it pays   attention to which specific instance of what type we want to   convert to.  This routine should eventually become   convert_to_pointer after all references to convert_to_pointer   are removed.  */treeconvert_pointer_to_real (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;    }  else    {      type = binfo;      binfo = NULL_TREE;    }  ptr_type = cp_build_type_variant (type, TYPE_READONLY (TREE_TYPE (intype)),				    TYPE_VOLATILE (TREE_TYPE (intype)));  ptr_type = build_pointer_type (ptr_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 (TREE_CODE (type) == RECORD_TYPE      && TREE_CODE (TREE_TYPE (intype)) == RECORD_TYPE      && type != TYPE_MAIN_VARIANT (TREE_TYPE (intype)))    {      tree path;      int distance	= get_base_distance (binfo, 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)	{	  cp_error ("cannot convert a pointer of type `%T' to a pointer of type `%T'",		    TREE_TYPE (intype), type);	  if (distance == -2)	    cp_error ("because `%T' is an ambiguous base class", type);	  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;}/* Call this when we know (for any reason) that expr is   not, in fact, zero.  This routine gets a type out of the first   argument and uses it to search for the type to convert to.  If there   is more than one instance of that type in the expr, the conversion is   ambiguous.  This routine should eventually go away, and all   callers should use convert_to_pointer_real.  */treeconvert_pointer_to (binfo, expr)     tree binfo, expr;{  tree type;  if (TREE_CODE (binfo) == TREE_VEC)    type = BINFO_TYPE (binfo);  else if (IS_AGGR_TYPE (binfo))      type = binfo;  else      type = binfo;  return convert_pointer_to_real (type, expr);}/* C++ conversions, preference to static cast conversions.  */treecp_convert (type, expr)     tree type, expr;{  return ocp_convert (type, expr, CONV_OLD_CONVERT, LOOKUP_NORMAL);}/* Conversion...   FLAGS indicates how we should behave.  */treeocp_convert (type, expr, convtype, flags)     tree type, expr;     int convtype, flags;{  register tree e = expr;  register enum tree_code code = TREE_CODE (type);  if (e == error_mark_node      || TREE_TYPE (e) == error_mark_node)    return error_mark_node;  if (IS_AGGR_TYPE (type) && (convtype & CONV_FORCE_TEMP))    /* We need a new temporary; don't take this shortcut.  */;  else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (e)))    /* Trivial conversion: cv-qualifiers do not matter on rvalues.  */    return fold (build1 (NOP_EXPR, type, e));    if (code == VOID_TYPE && (convtype & CONV_STATIC))    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 (e) == NOP_EXPR)    return cp_convert (type, TREE_OPERAND (e, 0));#endif  /* Just convert to the type of the member.  */  if (code == OFFSET_TYPE)    {      type = TREE_TYPE (type);      code = TREE_CODE (type);    }#if 0  if (code == REFERENCE_TYPE)    return fold (convert_to_reference (type, e, convtype, flags, NULL_TREE));  else if (TREE_CODE (TREE_TYPE (e)) == REFERENCE_TYPE)    e = convert_from_reference (e);#endif  if (TREE_CODE (e) == OFFSET_REF)    e = resolve_offset_ref (e);  if (TREE_READONLY_DECL_P (e))    e = decl_constant_value (e);  if (INTEGRAL_CODE_P (code))    {      tree intype = TREE_TYPE (e);      /* enum = enum, enum = int, enum = float, (enum)pointer are all         errors.  */      if (flag_int_enum_equivalence == 0	  && TREE_CODE (type) == ENUMERAL_TYPE	  && ((ARITHMETIC_TYPE_P (intype) && ! (convtype & CONV_STATIC))	      || (TREE_CODE (intype) == POINTER_TYPE)))	{	  cp_pedwarn ("conversion from `%#T' to `%#T'", intype, type);	  if (flag_pedantic_errors)	    return error_mark_node;	}      if (IS_AGGR_TYPE (intype))	{	  tree rval;	  rval = build_type_conversion (CONVERT_EXPR, type, e, 1);	  if (rval)	    return rval;	  if (flags & LOOKUP_COMPLAIN)	    cp_error ("`%#T' used where a `%T' was expected", intype, type);	  if (flags & LOOKUP_SPECULATIVELY)	    return NULL_TREE;	  return error_mark_node;	}      if (code == BOOLEAN_TYPE)	{	  /* Common Ada/Pascal programmer's mistake.  We always warn             about this since it is so bad.  */	  if (TREE_CODE (expr) == FUNCTION_DECL)	    cp_warning ("the address of `%D', will always be `true'", expr);	  return truthvalue_conversion (e);	}      return fold (convert_to_integer (type, e));    }  if (code == POINTER_TYPE || code == REFERENCE_TYPE      || TYPE_PTRMEMFUNC_P (type))    return fold (cp_convert_to_pointer (type, e));  if (code == REAL_TYPE || code == COMPLEX_TYPE)    {      if (IS_AGGR_TYPE (TREE_TYPE (e)))	{	  tree rval;	  rval = build_type_conversion (CONVERT_EXPR, type, e, 1);	  if (rval)	    return rval;	  else	    if (flags & LOOKUP_COMPLAIN)	      cp_error ("`%#T' used where a floating point value was expected",			TREE_TYPE (e));	}      if (code == REAL_TYPE)	return fold (convert_to_real (type, e));      else if (code == COMPLEX_TYPE)	return fold (convert_to_complex (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);      tree ctor = NULL_TREE;      tree conversion = NULL_TREE;      dtype = TYPE_MAIN_VARIANT (dtype);      /* Conversion of object pointers or signature pointers/references	 to signature pointers/references.  */      if (TYPE_LANG_SPECIFIC (type)	  && (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type)))	{	  tree constructor = build_signature_pointer_constructor (type, expr);	  tree sig_ty = SIGNATURE_TYPE (type);	  tree sig_ptr;	  if (constructor == error_mark_node)	    return error_mark_node;	  sig_ptr = get_temp_name (type, 1);	  DECL_INITIAL (sig_ptr) = constructor;	  CLEAR_SIGNATURE (sig_ty);	  cp_finish_decl (sig_ptr, constructor, NULL_TREE, 0, 0);	  SET_SIGNATURE (sig_ty);	  TREE_READONLY (sig_ptr) = 1;	  return sig_ptr;	}      /* 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 (flag_ansi_overloading)	{	  ctor = e;	  	  if ((flags & LOOKUP_ONLYCONVERTING)	      && ! (IS_AGGR_TYPE (dtype) && DERIVED_FROM_P (type, dtype)))	    {	      ctor = build_user_type_conversion (type, ctor, flags);	      flags |= LOOKUP_NO_CONVERSION;	    }	  if (ctor)	    ctor = build_method_call (NULL_TREE, ctor_identifier,				      build_expr_list (NULL_TREE, ctor),				      TYPE_BINFO (type), flags);	  if (ctor)	    return build_cplus_new (type, ctor);	}      else	{	  if (IS_AGGR_TYPE (dtype) && ! DERIVED_FROM_P (type, dtype)	      && TYPE_HAS_CONVERSION (dtype))	    conversion = build_type_conversion (CONVERT_EXPR, type, e, 1);	  if (conversion == error_mark_node)	    {	      if (flags & LOOKUP_COMPLAIN)		error ("ambiguous pointer conversion");	      return conversion;	    }	  if (TYPE_HAS_CONSTRUCTOR (complete_type (type)))	    ctor = build_method_call (NULL_TREE, ctor_identifier,				      build_expr_list (NULL_TREE, e),				      TYPE_BINFO (type),				      (flags & LOOKUP_NORMAL)				      | LOOKUP_SPECULATIVELY				      | (flags & LOOKUP_ONLYCONVERTING)				      | (flags & LOOKUP_NO_CONVERSION)				      | (conversion ? LOOKUP_NO_CONVERSION : 0));	  if (ctor == error_mark_node)	    {	      if (flags & LOOKUP_COMPLAIN)		cp_error ("in conversion to type `%T'", type);	      if (flags & LOOKUP_SPECULATIVELY)		return NULL_TREE;	      return error_mark_node;	    }      	  if (conversion && ctor)	    {	      if (flags & LOOKUP_COMPLAIN)		error ("both constructor and type conversion operator apply");	      if (flags & LOOKUP_SPECULATIVELY)		return NULL_TREE;	      return error_mark_node;	    }	  else if (conversion)	    return conversion;	  else if (ctor)	    {	      ctor = build_cplus_new (type, ctor);	      return ctor;	    }	}    }  /* If TYPE or TREE_TYPE (E) 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 (e)) == TREE_TYPE (type)      && index_type_equal (TYPE_DOMAIN (TREE_TYPE (e)), TYPE_DOMAIN (type)))    return e;  if (flags & LOOKUP_COMPLAIN)    cp_error ("conversion from `%T' to non-scalar type `%T' requested",	      TREE_TYPE (expr), type);  if (flags & LOOKUP_SPECULATIVELY)    return NULL_TREE;  return error_mark_node;}/* 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.   Most of this routine is from build_reinterpret_cast.   The backend cannot call cp_convert (what was convert) because   conversions to/from basetypes may involve memory references   (vbases) and adding or subtracting small values (multiple   inheritance), but it calls convert from the constant folding code   on subtrees of already build trees after it has ripped them apart.   Also, if we ever support range variables, we'll probably also have to   do a little bit more work.  */treeconvert (type, expr)     tree type, expr;{  tree intype;  if (type == error_mark_node || expr == error_mark_node)    return error_mark_node;  intype = TREE_TYPE (expr);  if (POINTER_TYPE_P (type) && POINTER_TYPE_P (intype))    {      if (TREE_READONLY_DECL_P (expr))	expr = decl_constant_value (expr);      return fold (build1 (NOP_EXPR, type, expr));    }  return ocp_convert (type, expr, CONV_OLD_CONVERT,		      LOOKUP_NORMAL|LOOKUP_NO_CONVERSION);}/* Like cp_convert, except permit conversions to take place which   are not normally allowed due to access restrictions   (such as conversion from sub-type to private super-type).  */treeconvert_force (type, expr, convtype)     tree type;     tree expr;     int convtype;{  register tree e = expr;  register enum tree_code code = TREE_CODE (type);  if (code == REFERENCE_TYPE)    return fold (convert_to_reference (type, e, CONV_C_CAST, LOOKUP_COMPLAIN,				       NULL_TREE));  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));  /* From typeck.c convert_for_assignment */  if (((TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (e) == ADDR_EXPR	&& TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE	&& TREE_CODE (TREE_TYPE (TREE_TYPE (e))) == METHOD_TYPE)

⌨️ 快捷键说明

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