This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PR c/43128


Bootstrapped and regression tested on x86_64-linux-gnu with -m32 and -m64.

OK?

2010-02-24  Manuel López-Ibáñez  <manu@gcc.gnu.org>

	PR c/43128
	* c-typeck.c (ep_convert_and_check): New.
	(build_conditional_expr): Use it.
	(build_binary_op): Likewise.
testsuite/	
	* c-c++-common/pr41779.c: Update.
Index: gcc/testsuite/c-c++-common/pr41779.c
===================================================================
--- gcc/testsuite/c-c++-common/pr41779.c	(revision 156985)
+++ gcc/testsuite/c-c++-common/pr41779.c	(working copy)
@@ -27,5 +27,30 @@ float f4(float x, unsigned char y)
 
 float f5(float x, int y)
 {
   return x * y; /* { dg-warning "conversion" } */
 }
+
+double c1(float x, unsigned short y, int z)
+{
+  return z ? x + x : y;
+}
+
+double c2(float x, short y, int z)
+{
+  return z ? x + x : y;
+}
+
+double c3(float x, char y, int z)
+{
+  return z ? x + x : y;
+}
+
+double c4(float x, unsigned char y, int z)
+{
+  return z ? x + x : y;
+}
+
+double c5(float x, int y, int z)
+{
+  return z ? x + x : y; /* { dg-warning "conversion" } */
+}
Index: gcc/c-typeck.c
===================================================================
--- gcc/c-typeck.c	(revision 156985)
+++ gcc/c-typeck.c	(working copy)
@@ -3895,10 +3895,38 @@ c_mark_addressable (tree exp)
       default:
 	return true;
     }
 }
 
+/* Convert EXPR to TYPE, warning about conversion problems with
+   constants.  SEMANTIC_TYPE is the type this conversion would use
+   without excess precision. If SEMANTIC_TYPE is NULL, this function
+   is equivalent to convert_and_check. This function is a wrapper that
+   handles conversions that may be different than
+   the usual ones because of excess precision.  */
+
+static tree
+ep_convert_and_check (tree type, tree expr, tree semantic_type)
+{
+  if (TREE_TYPE (expr) == type)
+    return expr;
+
+  if (!semantic_type)
+    return convert_and_check (type, expr);
+
+  if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+      && TREE_TYPE (expr) != semantic_type)
+    {
+      /* For integers, we need to check the real conversion, not
+	 the conversion to the excess precision type.  */
+      expr = convert_and_check (semantic_type, expr);
+    }
+  /* Result type is the excess precision type, which should be
+     large enough, so do not check.  */
+  return convert (type, expr);
+}
+
 /* Build and return a conditional expression IFEXP ? OP1 : OP2.  If
    IFEXP_BCP then the condition is a call to __builtin_constant_p, and
    if folded to an integer constant then the unselected half may
    contain arbitrary operations not normally permitted in constant
    expressions.  Set the location of the expression to LOC.  */
@@ -3911,11 +3939,11 @@ build_conditional_expr (location_t colon
   tree type1;
   tree type2;
   enum tree_code code1;
   enum tree_code code2;
   tree result_type = NULL;
-  tree ep_result_type = NULL;
+  tree semantic_result_type = NULL;
   tree orig_op1 = op1, orig_op2 = op2;
   bool int_const, op1_int_operands, op2_int_operands, int_operands;
   bool ifexp_int_operands;
   tree ret;
   bool objc_ok;
@@ -3962,11 +3990,11 @@ build_conditional_expr (location_t colon
       && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
 	  || code1 == COMPLEX_TYPE)
       && (code2 == INTEGER_TYPE || code2 == REAL_TYPE
 	  || code2 == COMPLEX_TYPE))
     {
-      ep_result_type = c_common_type (type1, type2);
+      semantic_result_type = c_common_type (type1, type2);
       if (TREE_CODE (op1) == EXCESS_PRECISION_EXPR)
 	{
 	  op1 = TREE_OPERAND (op1, 0);
 	  type1 = TREE_TYPE (op1);
 	  gcc_assert (TREE_CODE (type1) == code1);
@@ -4167,14 +4195,12 @@ build_conditional_expr (location_t colon
   result_type
     = build_type_variant (result_type,
 			  TYPE_READONLY (type1) || TYPE_READONLY (type2),
 			  TYPE_VOLATILE (type1) || TYPE_VOLATILE (type2));
 
-  if (result_type != type1)
-    op1 = convert_and_check (result_type, op1);
-  if (result_type != type2)
-    op2 = convert_and_check (result_type, op2);
+  op1 = ep_convert_and_check (result_type, op1, semantic_result_type);
+  op2 = ep_convert_and_check (result_type, op2, semantic_result_type);
 
   if (ifexp_bcp && ifexp == truthvalue_true_node)
     {
       op2_int_operands = true;
       op1 = c_fully_fold (op1, require_constant_value, NULL);
@@ -4202,12 +4228,12 @@ build_conditional_expr (location_t colon
     {
       ret = build3 (COND_EXPR, result_type, ifexp, op1, op2);
       if (int_operands)
 	ret = note_integer_operands (ret);
     }
-  if (ep_result_type)
-    ret = build1 (EXCESS_PRECISION_EXPR, ep_result_type, ret);
+  if (semantic_result_type)
+    ret = build1 (EXCESS_PRECISION_EXPR, semantic_result_type, ret);
 
   protected_set_expr_location (ret, colon_loc);
   return ret;
 }
 
@@ -9021,11 +9047,11 @@ build_binary_op (location_t location, en
      In the simplest cases this is the common type of the arguments.  */
   tree result_type = NULL;
 
   /* When the computation is in excess precision, the type of the
      final EXCESS_PRECISION_EXPR.  */
-  tree real_result_type = NULL;
+  tree semantic_result_type = NULL;
 
   /* Nonzero means operands have already been type-converted
      in whatever way is necessary.
      Zero means they need to be converted to RESULT_TYPE.  */
   int converted = 0;
@@ -9600,11 +9626,11 @@ build_binary_op (location_t location, en
 	  tree real_type = TREE_TYPE (result_type);
 	  tree real, imag;
 	  if (type0 != orig_type0 || type1 != orig_type1)
 	    {
 	      gcc_assert (may_need_excess_precision && common);
-	      real_result_type = c_common_type (orig_type0, orig_type1);
+	      semantic_result_type = c_common_type (orig_type0, orig_type1);
 	    }
 	  if (first_complex)
 	    {
 	      if (TREE_TYPE (op0) != result_type)
 		op0 = convert_and_check (result_type, op0);
@@ -9797,33 +9823,31 @@ build_binary_op (location_t location, en
     {
       binary_op_error (location, code, TREE_TYPE (op0), TREE_TYPE (op1));
       return error_mark_node;
     }
 
-  if (!converted)
-    {
-      if (TREE_TYPE (op0) != result_type)
-	op0 = convert_and_check (result_type, op0);
-      if (TREE_TYPE (op1) != result_type)
-	op1 = convert_and_check (result_type, op1);
-
-      /* This can happen if one operand has a vector type, and the other
-	 has a different type.  */
-      if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK)
-	return error_mark_node;
-    }
-
   if (build_type == NULL_TREE)
     {
       build_type = result_type;
       if (type0 != orig_type0 || type1 != orig_type1)
 	{
 	  gcc_assert (may_need_excess_precision && common);
-	  real_result_type = c_common_type (orig_type0, orig_type1);
+	  semantic_result_type = c_common_type (orig_type0, orig_type1);
 	}
     }
 
+  if (!converted)
+    {
+      op0 = ep_convert_and_check (result_type, op0, semantic_result_type);
+      op1 = ep_convert_and_check (result_type, op1, semantic_result_type);
+
+      /* This can happen if one operand has a vector type, and the other
+	 has a different type.  */
+      if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK)
+	return error_mark_node;
+    }
+
   /* Treat expressions in initializers specially as they can't trap.  */
   if (int_const_or_overflow)
     ret = (require_constant_value
 	   ? fold_build2_initializer_loc (location, resultcode, build_type,
 					  op0, op1)
@@ -9840,12 +9864,12 @@ build_binary_op (location_t location, en
 	   ? note_integer_operands (ret)
 	   : build1 (NOP_EXPR, TREE_TYPE (ret), ret));
   else if (TREE_CODE (ret) != INTEGER_CST && int_operands
 	   && !in_late_binary_op)
     ret = note_integer_operands (ret);
-  if (real_result_type)
-    ret = build1 (EXCESS_PRECISION_EXPR, real_result_type, ret);
+  if (semantic_result_type)
+    ret = build1 (EXCESS_PRECISION_EXPR, semantic_result_type, ret);
   protected_set_expr_location (ret, location);
   return ret;
 }
 
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]