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

📄 c-typeck.c

📁 这是完整的gcc源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
	  && TYPE_PRECISION (dt0) > TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))	  && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0))))	{	  final_type = result_type;	  op0 = TREE_OPERAND (op0, 0);	  result_type = TREE_TYPE (op0);	}      break;    case TRUNC_MOD_EXPR:      if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)	shorten = 1;      break;    case TRUTH_ANDIF_EXPR:    case TRUTH_ORIF_EXPR:    case TRUTH_AND_EXPR:    case TRUTH_OR_EXPR:      if ((code0 == INTEGER_TYPE || code0 == POINTER_TYPE || code0 == REAL_TYPE)	  && (code1 == INTEGER_TYPE || code1 == POINTER_TYPE || code1 == REAL_TYPE))	{	  /* Result of these operations is always an int,	     but that does not mean the operands should be	     converted to ints!  */	  result_type = integer_type_node;	  op0 = truthvalue_conversion (op0);	  op1 = truthvalue_conversion (op1);	  converted = 1;	}      break;      /* Shift operations: result has same type as first operand;	 always convert second operand to int.	 Also set SHORT_SHIFT if shifting rightward.  */    case RSHIFT_EXPR:      if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)	{	  result_type = dt0;	  if (TREE_CODE (op1) == INTEGER_CST	      && TREE_INT_CST_LOW (op1) > 0)	    short_shift = 1;	  /* Convert the shift-count to an integer, regardless of	     size of value being shifted.  */	  if (TREE_TYPE (op1) != integer_type_node)	    op1 = convert (integer_type_node, op1);	}      break;    case LSHIFT_EXPR:      if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)	{	  result_type = dt0;	  if (TREE_CODE (op1) == INTEGER_CST	      && TREE_INT_CST_LOW (op1) < 0)	    short_shift = 1;	  /* Convert the shift-count to an integer, regardless of	     size of value being shifted.  */	  if (TREE_TYPE (op1) != integer_type_node)	    op1 = convert (integer_type_node, op1);	}      break;    case RROTATE_EXPR:    case LROTATE_EXPR:      if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)	{	  result_type = dt0;	  /* Convert the shift-count to an integer, regardless of	     size of value being shifted.  */	  if (TREE_TYPE (op1) != integer_type_node)	    op1 = convert (integer_type_node, op1);	}      break;    case EQ_EXPR:    case NE_EXPR:      /* Result of comparison is always int,	 but don't convert the args to int!  */      result_type = integer_type_node;      converted = 1;      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)	  && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))	short_compare = 1;      else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)	{	  register tree tt0 = TREE_TYPE (dt0);	  register tree tt1 = TREE_TYPE (dt1);	  /* Anything compares with void *.  void * compares with anything.	     Otherwise, the targets must be the same.  */	  if (comp_target_types (dt0, dt1))	    ;	  else if (TYPE_MAIN_VARIANT (tt0) == void_type_node)	    {	      if (pedantic && TREE_CODE (tt1) == FUNCTION_TYPE)		warning ("ANSI C forbids comparison of `void *' with function pointer");	    }	  else if (TYPE_MAIN_VARIANT (tt1) == void_type_node)	    {	      if (pedantic && TREE_CODE (tt0) == FUNCTION_TYPE)		warning ("ANSI C forbids comparison of `void *' with function pointer");	    }	  else	    warning ("comparison of distinct pointer types lacks a cast");	}      else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST		&& integer_zerop (op1))	op1 = null_pointer_node;      else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST		&& integer_zerop (op0))	op0 = null_pointer_node;      else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)	{	  if (! flag_traditional)	    warning ("comparison between pointer and integer");	  op1 = convert (TREE_TYPE (op0), op1);	}      else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)	{	  if (! flag_traditional)	    warning ("comparison between pointer and integer");	  op0 = convert (TREE_TYPE (op1), op0);	}      else	/* If args are not valid, clear out RESULT_TYPE	   to cause an error message later.  */	result_type = 0;      break;    case MAX_EXPR:    case MIN_EXPR:      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)	   && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))	shorten = 1;      else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)	{	  if (! comp_target_types (dt0, dt1))	    warning ("comparison of distinct pointer types lacks a cast");	  else if (pedantic 		   && TREE_CODE (TREE_TYPE (dt0)) == FUNCTION_TYPE)	    warning ("ANSI C forbids ordered comparisons of pointers to functions");	  result_type = commontype (dt0, dt1);	}      break;    case LE_EXPR:    case GE_EXPR:    case LT_EXPR:    case GT_EXPR:      if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)	   && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))	short_compare = 1;      else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE)	{	  if (! comp_target_types (dt0, dt1))	    warning ("comparison of distinct pointer types lacks a cast");	  else if (pedantic 		   && TREE_CODE (TREE_TYPE (dt0)) == FUNCTION_TYPE)	    warning ("ANSI C forbids ordered comparisons of pointers to functions");	  result_type = integer_type_node;	}      else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST		&& integer_zerop (op1))	{	  result_type = integer_type_node;	  op1 = null_pointer_node;	  if (! flag_traditional)	    warning ("ordered comparison of pointer with integer zero");	}      else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST		&& integer_zerop (op0))	{	  result_type = integer_type_node;	  op0 = null_pointer_node;	  if (pedantic)	    warning ("ordered comparison of pointer with integer zero");	}      else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)	{	  result_type = integer_type_node;	  if (! flag_traditional)	    warning ("comparison between pointer and integer");	  op1 = convert (TREE_TYPE (op0), op1);	}      else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)	{	  result_type = integer_type_node;	  if (! flag_traditional)	    warning ("comparison between pointer and integer");	  op0 = convert (TREE_TYPE (op1), op0);	}      converted = 1;      break;    }  if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE)      && (code1 == INTEGER_TYPE || code1 == REAL_TYPE))    {      if (shorten || common || short_compare)	result_type = commontype (dt0, dt1);      /* For certain operations (which identify themselves by shorten != 0)	 if both args were extended from the same smaller type,	 do the arithmetic in that type and then extend.	 shorten !=0 and !=1 indicates a bitwise operation.	 For them, this optimization is safe only if	 both args are zero-extended or both are sign-extended.	 Otherwise, we might change the result.	 Eg, (short)-1 | (unsigned short)-1 is (int)-1	 but calculated in (unsigned short) it would be (unsigned short)-1.  */      if (shorten)	{	  int unsigned0, unsigned1;	  tree arg0 = get_narrower (op0, &unsigned0);	  tree arg1 = get_narrower (op1, &unsigned1);	  /* UNS is 1 if the operation to be done is an unsigned one.  */	  int uns = TREE_UNSIGNED (result_type);	  tree type;	  final_type = result_type;	  /* Handle the case that OP0 does not *contain* a conversion	     but it *requires* conversion to FINAL_TYPE.  */	  if (op0 == arg0 && TREE_TYPE (op0) != final_type)	    unsigned0 = TREE_UNSIGNED (TREE_TYPE (op0));	  if (op1 == arg1 && TREE_TYPE (op1) != final_type)	    unsigned1 = TREE_UNSIGNED (TREE_TYPE (op1));	  /* Now UNSIGNED0 is 1 if ARG0 zero-extends to FINAL_TYPE.  */	  /* For bitwise operations, signedness of nominal type	     does not matter.  Consider only how operands were extended.  */	  if (shorten == -1)	    uns = unsigned0;	  /* Note that in all three cases below we refrain from optimizing	     an unsigned operation on sign-extended args.	     That would not be valid.  */	  /* Both args variable: if both extended in same way	     from same width, do it in that width.	     Do it unsigned if args were zero-extended.  */	  if ((TYPE_PRECISION (TREE_TYPE (arg0))	       < TYPE_PRECISION (result_type))	      && (TYPE_PRECISION (TREE_TYPE (arg1))		  == TYPE_PRECISION (TREE_TYPE (arg0)))	      && unsigned0 == unsigned1	      && (unsigned0 || !uns))	    result_type	      = signed_or_unsigned_type (unsigned0,					 commontype (TREE_TYPE (arg0), TREE_TYPE (arg1)));	  else if (TREE_CODE (arg0) == INTEGER_CST		   && (unsigned1 || !uns)		   && (TYPE_PRECISION (TREE_TYPE (arg1))		       < TYPE_PRECISION (result_type))		   && (type = signed_or_unsigned_type (unsigned1,						       TREE_TYPE (arg1)),		       int_fits_type_p (arg0, type)))	    result_type = type;	  else if (TREE_CODE (arg1) == INTEGER_CST		   && (unsigned0 || !uns)		   && (TYPE_PRECISION (TREE_TYPE (arg0))		       < TYPE_PRECISION (result_type))		   && (type = signed_or_unsigned_type (unsigned0,						       TREE_TYPE (arg0)),		       int_fits_type_p (arg1, type)))	    result_type = type;	}      /* Shifts can be shortened if shifting right.  */      if (short_shift)	{	  int unsigned_arg;	  tree arg0 = get_narrower (op0, &unsigned_arg);	  final_type = result_type;	  if (arg0 == op0 && final_type == TREE_TYPE (op0))	    unsigned_arg = TREE_UNSIGNED (TREE_TYPE (op0));	  if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)	      /* If arg is sign-extended and then unsigned-shifted,		 we can simulate this with a signed shift in arg's type		 only if the extended result is at least twice as wide		 as the arg.  Otherwise, the shift could use up all the		 ones made by sign-extension and bring in zeros.		 We can't optimize that case at all, but in most machines		 it never happens because available widths are 2**N.  */	      && (!TREE_UNSIGNED (final_type)		  || unsigned_arg		  || 2 * TYPE_PRECISION (TREE_TYPE (arg0)) <= TYPE_PRECISION (result_type)))	    {	      /* Do an unsigned shift if the operand was zero-extended.  */	      result_type		= signed_or_unsigned_type (unsigned_arg,					   TREE_TYPE (arg0));	      /* Convert value-to-be-shifted to that type.  */	      if (TREE_TYPE (op0) != result_type)		op0 = convert (result_type, op0);	      converted = 1;	    }	}      /* Comparison operations are shortened too but differently.	 They identify themselves by setting short_compare = 1.  */      if (short_compare)	{	  /* Don't write &op0, etc., because that would prevent op0	     from being kept in a register.	     Instead, make copies of the our local variables and	     pass the copies by reference, then copy them back afterward.  */	  tree xop0 = op0, xop1 = op1, xresult_type = result_type;	  enum tree_code xresultcode = resultcode;	  tree val 	    = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode);	  if (val != 0)	    return val;	  op0 = xop0, op1 = xop1, result_type = xresult_type;	  resultcode = xresultcode;	}    }  /* At this point, RESULT_TYPE must be nonzero to avoid an error message.     If CONVERTED is zero, both args will be converted to type RESULT_TYPE.     Then the expression will be built.     It will be given type FINAL_TYPE if that is nonzero;     otherwise, it will be given type RESULT_TYPE.  */  if (!result_type)    {      binary_op_error (error_code);      return error_mark_node;    }  if (! converted)    {      if (TREE_TYPE (op0) != result_type)	op0 = convert (result_type, op0);       if (TREE_TYPE (op1) != result_type)	op1 = convert (result_type, op1);     }  {    register tree result = build (resultcode, result_type, op0, op1);    register tree folded;    folded = fold (result);    if (folded == result)      TREE_LITERAL (folded) = TREE_LITERAL (op0) & TREE_LITERAL (op1);    if (final_type != 0)      return convert (final_type, folded);    return folded;  }}/* Return a tree for the sum or difference (RESULTCODE says which)   of pointer PTROP and integer INTOP.  */static treepointer_int_sum (resultcode, ptrop, intop)     enum tree_code resultcode;     register tree ptrop, intop;{  tree size_exp;  register tree result;  register tree folded;  /* The result is a pointer of the same type that is being added.  */  register tree result_type = datatype (ptrop);  if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)    {      if (pedantic || warn_pointer_arith)	warning ("pointer of type `void *' used in arithmetic");      size_exp = integer_one_node;    }  else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE)    {      if (pedantic || warn_pointer_arith)	warning ("pointer to a function used in arithmetic");      size_exp = integer_one_node;    }  else    size_exp = c_sizeof (TREE_TYPE (result_type));  /* If what we are about to multiply by the size of the elements     contains a constant term, apply distributive law     and multiply that constant term separately.     This helps produce common subexpressions.  */  if ((TREE_CODE (intop) == PLUS_EXPR || TREE_CODE (intop) == MINUS_EXPR)      && ! TREE_LITERAL (intop)      && TREE_LITERAL (TREE_OPERAND (intop, 1))      && TREE_LITERAL (size_exp))    {      enum tree_code subcode = resultcode;      if (TREE_CODE (intop) == MINUS_EXPR)	subcode = (subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR);      ptrop = build_binary_op (subcode, ptrop, TREE_OPERAND (intop, 1));      intop = TREE_OPERAND (intop, 0);    }  /* Convert the integer argument to a type the same size as a pointer     so the multiply won't overflow spuriously.  */  if (TYPE_PRECISION (TREE_TYPE (intop)) != POINTER_SIZE)    intop = convert (type_for_size (POINTER_SIZE, 0), intop);  /* Replace the integer argument     with a suitable product by the object size.  */  intop = build_binary_op (MULT_EXPR, intop, size_exp);  /* Create the sum or difference.  */  result = build (resultcode, result_type, ptrop, intop);  folded = fold (result);  if (folded == result)    TREE_LITERAL (folded) = TREE_LITERAL (ptrop) & TREE_LITERAL (intop);  return folded;}/* Return a tree for the difference of pointers OP0 and OP1.

⌨️ 快捷键说明

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