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

📄 cp-cvt.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
    case INIT_EXPR:      {	tree real_reference = build_up_reference (type, TREE_OPERAND (targ, 0),						  LOOKUP_PROTECT, checkconst);	rval = build (COMPOUND_EXPR, type, arg, real_reference);	TREE_CONSTANT (rval) = staticp (TREE_OPERAND (targ, 0));	return rval;      }    case COND_EXPR:      return build (COND_EXPR, type,		    TREE_OPERAND (targ, 0),		    build_up_reference (type, TREE_OPERAND (targ, 1),					LOOKUP_PROTECT, checkconst),		    build_up_reference (type, TREE_OPERAND (targ, 2),					LOOKUP_PROTECT, checkconst));    case WITH_CLEANUP_EXPR:      return build (WITH_CLEANUP_EXPR, type,		    build_up_reference (type, TREE_OPERAND (targ, 0),					LOOKUP_PROTECT, checkconst),		    0, TREE_OPERAND (targ, 2));    case BIND_EXPR:      arg = TREE_OPERAND (targ, 1);      if (arg == NULL_TREE)	{	  compiler_error ("({ ... }) expression not expanded when needed for reference");	  return error_mark_node;	}      rval = build1 (ADDR_EXPR, type, arg);      TREE_REFERENCE_EXPR (rval) = 1;      return rval;    default:      break;    }  if (TREE_ADDRESSABLE (targ) == 0)    {      tree temp;      if (TREE_CODE (targ) == CALL_EXPR && IS_AGGR_TYPE (argtype))	{	  temp = build_cplus_new (argtype, targ, 1);	  rval = build1 (ADDR_EXPR, type, temp);	  goto done;	}      else	{	  temp = get_temp_name (argtype, 0);	  if (global_bindings_p ())	    {	      /* Give this new temp some rtl and initialize it.  */	      DECL_INITIAL (temp) = targ;	      TREE_STATIC (temp) = 1;	      finish_decl (temp, targ, NULL_TREE, 0);	      /* Do this after declaring it static.  */	      rval = build_unary_op (ADDR_EXPR, temp, 0);	      literal_flag = TREE_CONSTANT (rval);	      goto done;	    }	  else	    {	      rval = build_unary_op (ADDR_EXPR, temp, 0);	      /* Put a value into the rtl.  */	      if (IS_AGGR_TYPE (argtype))		{		  /* This may produce surprising results,		     since we commit to initializing the temp		     when the temp may not actually get used.  */		  expand_aggr_init (temp, targ, 0);		  TREE_TYPE (rval) = type;		  literal_flag = TREE_CONSTANT (rval);		  goto done;		}	      else		{		  if (binfo && !BINFO_OFFSET_ZEROP (binfo))		    rval = convert_pointer_to (target_type, rval);		  else		    TREE_TYPE (rval) = type;		  return build (COMPOUND_EXPR, type,				build (MODIFY_EXPR, argtype, temp, arg), rval);		}	    }	}    }  else    {      if (TREE_CODE (arg) == SAVE_EXPR)	my_friendly_abort (5);      rval = build1 (ADDR_EXPR, type, arg);    } done_but_maybe_warn:  if (checkconst && TREE_READONLY (arg) && ! TYPE_READONLY (target_type))    readonly_warning_or_error (arg, "conversion to reference"); done:  if (TYPE_USES_COMPLEX_INHERITANCE (argtype))    {      TREE_TYPE (rval) = TYPE_POINTER_TO (argtype);      rval = convert_pointer_to (target_type, rval);      TREE_TYPE (rval) = type;    }  TREE_CONSTANT (rval) = literal_flag;  return rval;}/* For C++: Only need to do one-level references, but cannot   get tripped up on signed/unsigned differences.   If DECL is NULL_TREE it means convert as though casting (by force).   If it is ERROR_MARK_NODE, it means the conversion is implicit,   and that temporaries may be created.   Make sure the use of user-defined conversion operators is un-ambiguous.   Otherwise, DECL is a _DECL node which can be used in error reporting.   FNDECL, PARMNUM, and ERRTYPE are only used when checking for use of   volatile or const references where they aren't desired.  */treeconvert_to_reference (decl, reftype, expr, fndecl, parmnum,		      errtype, strict, flags)     tree decl;     tree reftype, expr;     tree fndecl;     int parmnum;     char *errtype;     int strict, flags;{  register tree type = TYPE_MAIN_VARIANT (TREE_TYPE (reftype));  register tree intype = TREE_TYPE (expr);  register enum tree_code form = TREE_CODE (intype);  tree rval = NULL_TREE;  if (form == REFERENCE_TYPE)    intype = TREE_TYPE (intype);  intype = TYPE_MAIN_VARIANT (intype);  /* @@ Probably need to have a check for X(X&) here.  */  if (IS_AGGR_TYPE (intype))    {      rval = build_type_conversion (CONVERT_EXPR, reftype, expr, 1);      if (rval)	{	  if (rval == error_mark_node)	    error ("ambiguous pointer conversion");	  return rval;	}      else if (type != intype	       && (rval = build_type_conversion (CONVERT_EXPR, type, expr, 1)))	{	  if (rval == error_mark_node)	    return rval;	  if (TYPE_NEEDS_DESTRUCTOR (type))	    {	      rval = convert_to_reference (NULL_TREE, reftype, rval, NULL_TREE, -1, (char *)NULL, strict, flags);	    }	  else	    {	      decl = get_temp_name (type, 0);	      rval = build (INIT_EXPR, type, decl, rval);	      rval = build (COMPOUND_EXPR, reftype, rval,			    convert_to_reference (NULL_TREE, reftype, decl,						  NULL_TREE, -1, (char *)NULL,						  strict, flags));	    }	}      if (form == REFERENCE_TYPE	  && type != intype	  && TYPE_USES_COMPLEX_INHERITANCE (intype))	{	  /* If it may move around, build a fresh reference.  */	  expr = convert_from_reference (expr);	  form = TREE_CODE (TREE_TYPE (expr));	}    }  /* @@ Perhaps this should try to go through a constructor first     @@ for proper initialization, but I am not sure when that     @@ is needed or desirable.     @@ The second disjunct is provided to make references behave     @@ as some people think they should, i.e., an interconvertability     @@ between references to builtin types (such as short and     @@ unsigned short).  There should be no conversion between     @@ types whose codes are different, or whose sizes are different.  */  if (((IS_AGGR_TYPE (type) || IS_AGGR_TYPE (intype))       && comptypes (type, intype, strict))      || (!IS_AGGR_TYPE (type)	  && TREE_CODE (type) == TREE_CODE (intype)	  && int_size_in_bytes (type) == int_size_in_bytes (intype)))    {      /* Section 13.  */      /* Since convert_for_initialization didn't call convert_for_assignment,	 we have to do this checking here.  XXX We should have a common	 routine between here and convert_for_assignment.  */      if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE)	{	  register tree ttl = TREE_TYPE (reftype);	  register tree ttr = TREE_TYPE (TREE_TYPE (expr));	  if (! TYPE_READONLY (ttl) && TYPE_READONLY (ttr))	    warn_for_assignment ("%s of non-`const &' reference from `const &'",				 "reference to const given for argument %d of `%s'",				 errtype, fndecl, parmnum, pedantic);	  if (! TYPE_VOLATILE (ttl) && TYPE_VOLATILE (ttr))	    warn_for_assignment ("%s of non-`volatile &' reference from `volatile &'",				 "reference to volatile given for argument %d of `%s'",				 errtype, fndecl, parmnum, pedantic);	}      /* If EXPR is of aggregate type, and is really a CALL_EXPR,	 then we don't need to convert it to reference type if	 it is only being used to initialize DECL which is also	 of the same aggregate type.  */      if (form == REFERENCE_TYPE	  || (decl != NULL_TREE && decl != error_mark_node	      && IS_AGGR_TYPE (type)	      && TREE_CODE (expr) == CALL_EXPR	      && TYPE_MAIN_VARIANT (type) == intype))	{	  if (decl && decl != error_mark_node)	    {	      tree e1 = build (INIT_EXPR, void_type_node, decl, expr);	      tree e2;	      TREE_SIDE_EFFECTS (e1) = 1;	      if (form == REFERENCE_TYPE)		e2 = build1 (NOP_EXPR, reftype, decl);	      else		{		  e2 = build_unary_op (ADDR_EXPR, decl, 0);		  TREE_TYPE (e2) = reftype;		  TREE_REFERENCE_EXPR (e2) = 1;		}	      return build_compound_expr (tree_cons (NULL_TREE, e1,						     build_tree_list (NULL_TREE, e2)));	    }	  expr = copy_node (expr);	  TREE_TYPE (expr) = reftype;	  return expr;	}      if (decl == error_mark_node)	flags |= LOOKUP_PROTECTED_OK;      return build_up_reference (reftype, expr, flags, decl!=NULL_TREE);    }  /* Definitely need to go through a constructor here.  */  if (TYPE_HAS_CONSTRUCTOR (type))    {      tree init = build_method_call (NULL_TREE, constructor_name (type),				     build_tree_list (NULL_TREE, expr),				     TYPE_BINFO (type), LOOKUP_NO_CONVERSION);      tree rval1;      if (init != error_mark_node)	if (rval)	  {	    error ("both constructor and type conversion operator apply");	    return error_mark_node;	  }      init = build_method_call (NULL_TREE, constructor_name (type),				build_tree_list (NULL_TREE, expr),				TYPE_BINFO (type), LOOKUP_NORMAL);      if (init == error_mark_node)	return error_mark_node;      rval = build_cplus_new (type, init, 1);      if (decl == error_mark_node)	flags |= LOOKUP_PROTECTED_OK;      return build_up_reference (reftype, rval, flags, decl!=NULL_TREE);    }  if (rval)    {      /* If we found a way to convert earlier, then use it. */      return rval;    }  my_friendly_assert (form != OFFSET_TYPE, 189);  /* This is in two pieces for now, because pointer to first becomes     invalid once type_as_string is called again. */  error ("cannot convert type `%s'", type_as_string (intype));  error ("       to type `%s'", type_as_string (reftype));  return error_mark_node;}/* We are using a reference VAL for its value. Bash that reference all the   way down to its lowest form. */treeconvert_from_reference (val)     tree val;{  tree type = TREE_TYPE (val);  if (TREE_CODE (type) == OFFSET_TYPE)    type = TREE_TYPE (type); if (TREE_CODE (type) == REFERENCE_TYPE)    {      tree target_type = TREE_TYPE (type);      /* This can happen if we cast to a reference type.  */      if (TREE_CODE (val) == ADDR_EXPR)	{	  val = build1 (NOP_EXPR, build_pointer_type (target_type), val);	  val = build_indirect_ref (val, 0);	  return val;	}      val = build1 (INDIRECT_REF, TYPE_MAIN_VARIANT (target_type), val);      TREE_THIS_VOLATILE (val) = TYPE_VOLATILE (target_type);      TREE_SIDE_EFFECTS (val) = TYPE_VOLATILE (target_type);      TREE_READONLY (val) = TYPE_READONLY (target_type);    }  return val;}static treeconvert_to_real (type, expr)     tree type, expr;{  register enum tree_code form = TREE_CODE (TREE_TYPE (expr));  if (form == REAL_TYPE)    return build1 (flag_float_store ? CONVERT_EXPR : NOP_EXPR,		  type, expr);  if (form == INTEGER_TYPE || form == ENUMERAL_TYPE)    return build1 (FLOAT_EXPR, type, expr);  my_friendly_assert (form != OFFSET_TYPE, 190);  if (form == POINTER_TYPE)    error ("pointer value used where a floating point value was expected");  /* C++: check to see if we can convert this aggregate type     into the required scalar type.  */  else if (IS_AGGR_TYPE (TREE_TYPE (expr)))    {      tree rval;      rval = build_type_conversion (CONVERT_EXPR, type, expr, 1);      if (rval)	return rval;      else	error ("aggregate value used where a floating point value was expected");    }  {    register tree tem = make_node (REAL_CST);    TREE_TYPE (tem) = type;    TREE_REAL_CST (tem) = REAL_VALUE_ATOF ("0.0");    return tem;  }}/* The result of this is always supposed to be a newly created tree node   not in use in any existing structure.  */static treeconvert_to_integer (type, expr)     tree type, expr;{  register tree intype = TREE_TYPE (expr);  register enum tree_code form = TREE_CODE (intype);  extern tree build_binary_op_nodefault ();  extern tree build_unary_op ();  if (form == POINTER_TYPE)    {      if (integer_zerop (expr))	expr = integer_zero_node;      else	expr = fold (build1 (CONVERT_EXPR,			     type_for_size (POINTER_SIZE, 0), expr));      intype = TREE_TYPE (expr);      form = TREE_CODE (intype);      if (intype == type)	return expr;    }  if (form == INTEGER_TYPE || form == ENUMERAL_TYPE)    {      register unsigned outprec = TYPE_PRECISION (type);      register unsigned inprec = TYPE_PRECISION (intype);      register enum tree_code ex_form = TREE_CODE (expr);      if (flag_int_enum_equivalence == 0	  && TREE_CODE (type) == ENUMERAL_TYPE	  && form == INTEGER_TYPE)	{	  if (pedantic)	    pedwarn ("anachronistic conversion from integer type to enumeral type `%s'",		     TYPE_NAME_STRING (type));	  if (flag_pedantic_errors)	    return error_mark_node;	}      /* If we are widening the type, put in an explicit conversion.	 Similarly if we are not changing the width.  However, if this is	 a logical operation that just returns 0 or 1, we can change the	 type of the expression (see below).  */      if (TREE_CODE_CLASS (ex_form) == '<'	  || ex_form == TRUTH_AND_EXPR || ex_form == TRUTH_ANDIF_EXPR	  || ex_form == TRUTH_OR_EXPR || ex_form == TRUTH_ORIF_EXPR	  || ex_form == TRUTH_NOT_EXPR)	{	  TREE_TYPE (expr) = type;	  return expr;	}      else if (outprec >= inprec)	return build1 (NOP_EXPR, type, expr);/* Here detect when we can distribute the truncation down past some arithmetic.

⌨️ 快捷键说明

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