diff mbox

[C++] Mixed scalar-vector operations

Message ID alpine.DEB.2.02.1210081738130.3232@stedding.saclay.inria.fr
State New
Headers show

Commit Message

Marc Glisse Oct. 8, 2012, 3:53 p.m. UTC
On Fri, 5 Oct 2012, Jason Merrill wrote:

>> +		error_at (loc, "conversion of scalar to vector "
>> +			       "involves truncation");
>
> These errors should print the types involved.  They also need to be 
> suppressed when !(complain & tf_error).

Hello,

here is a new version of the patch. Differences with the previous one 
should only be comments, testsuite, printing types and inhibiting error 
messages.

Passes bootstrap+testsuite. scal-to-vec1.c was failing but then Joseph 
showed me the \[^\\n\]* trick and I retested with:
make check-gcc 'RUNTESTFLAGS=dg.exp=scal-to-vec1.c'

2012-09-22  Marc Glisse  <marc.glisse@inria.fr>

         PR c++/54427

c/
         * c-typeck.c: Include c-common.h.
         (enum stv_conv): Moved to c-common.h.
         (scalar_to_vector): Moved to c-common.c.
 	(build_binary_op): Adapt to scalar_to_vector's new prototype.
         * Make-lang.in: c-typeck.c depends on c-common.h.

c-family/
         * c-common.c (scalar_to_vector): Moved from c-typeck.c. Support
         more operations. Make error messages optional.
         * c-common.h (enum stv_conv): Moved from c-typeck.c.
         (scalar_to_vector): Declare.

cp/
         * typeck.c (cp_build_binary_op): Handle mixed scalar-vector
         operations.
         [LSHIFT_EXPR, RSHIFT_EXPR]: Likewise.

gcc/
         * fold-const.c (fold_binary_loc): Use build_zero_cst instead of
         build_int_cst for a potential vector.

testsuite/
         * c-c++-common/vector-scalar.c: New testcase.
         * g++.dg/ext/vector18.C: New testcase.
         * g++.dg/ext/vector5.C: This is not an error anymore.
         * gcc.dg/init-vec-1.c: Move ...
         * c-c++-common/init-vec-1.c: ... here. Adapt error message.
         * gcc.c-torture/execute/vector-shift1.c: Move ...
         * c-c++-common/torture/vector-shift1.c: ... here.
         * gcc.dg/scal-to-vec1.c: Move ...
         * c-c++-common/scal-to-vec1.c: ... here. Avoid narrowing for
         C++11. Adapt error messages.
         * gcc.dg/convert-vec-1.c: Move ...
         * c-c++-common/convert-vec-1.c: ... here.
         * gcc.dg/scal-to-vec2.c: Move ...
         * c-c++-common/scal-to-vec2.c: ... here.

Comments

Jason Merrill Oct. 8, 2012, 5:49 p.m. UTC | #1
OK.

Jason
Mike Stump Oct. 8, 2012, 6:13 p.m. UTC | #2
On Oct 8, 2012, at 8:53 AM, Marc Glisse <marc.glisse@inria.fr> wrote:
> On Fri, 5 Oct 2012, Jason Merrill wrote:
> 
>>> +		error_at (loc, "conversion of scalar to vector "
>>> +			       "involves truncation");
>> 
>> These errors should print the types involved.  They also need to be suppressed when !(complain & tf_error).
> 
> Hello,
> 
> here is a new version of the patch.

All I can say is thank you for pressing forward and not being discouraged.  In the end, it feels like we'll have better vector support in C++.  :-)
diff mbox

Patch

Index: testsuite/g++.dg/ext/vector18.C
===================================================================
--- testsuite/g++.dg/ext/vector18.C	(revision 0)
+++ testsuite/g++.dg/ext/vector18.C	(revision 0)
@@ -0,0 +1,14 @@ 
+/* { dg-do compile } */
+/* { dg-options "-std=c++11" } */
+
+typedef signed char __attribute__((vector_size(128) )) vec;
+
+template <class A, class B>
+auto f (A *a, B b) -> decltype (*a + b);
+
+void f (...) {}
+
+void g (vec *v, long long l)
+{
+  f (v, l);
+}

Property changes on: testsuite/g++.dg/ext/vector18.C
___________________________________________________________________
Added: svn:eol-style
   + native
Added: svn:keywords
   + Author Date Id Revision URL

Index: testsuite/g++.dg/ext/vector5.C
===================================================================
--- testsuite/g++.dg/ext/vector5.C	(revision 192153)
+++ testsuite/g++.dg/ext/vector5.C	(working copy)
@@ -1,8 +1,8 @@ 
 // PR c++/30022
 // { dg-do compile }
 
 void foo()
 {
   int __attribute__((vector_size(8))) v;
-  v = 1/v;  // { dg-error "invalid operands of types" }
+  v = 1/v;
 }
Index: testsuite/c-c++-common/init-vec-1.c
===================================================================
--- testsuite/c-c++-common/init-vec-1.c	(revision 191610)
+++ testsuite/c-c++-common/init-vec-1.c	(working copy)
@@ -1,4 +1,4 @@ 
 /* Don't ICE or emit spurious errors when init a vector with a scalar.  */
 /* { dg-do compile } */
 typedef float v2sf __attribute__ ((vector_size (8)));
-v2sf a = 0.0;  /* { dg-error "incompatible types" } */
+v2sf a = 0.0;  /* { dg-error "incompatible types|cannot convert" } */
Index: testsuite/c-c++-common/torture/vector-shift1.c
===================================================================
--- testsuite/c-c++-common/torture/vector-shift1.c	(revision 191610)
+++ testsuite/c-c++-common/torture/vector-shift1.c	(working copy)
@@ -1,10 +1,11 @@ 
+/* { dg-do run } */
 #define vector __attribute__((vector_size(8*sizeof(short))))
 
 int main (int argc, char *argv[]) {
   vector short v0 = {argc,2,3,4,5,6,7};
   vector short v1 = {2,2,2,2,2,2,2};
   vector short r1,r2,r3,r4;
   int i = 8;
 
   r1 = v0 << 1;
   r2 = v0 >> 1;
Index: testsuite/c-c++-common/scal-to-vec1.c
===================================================================
--- testsuite/c-c++-common/scal-to-vec1.c	(revision 191610)
+++ testsuite/c-c++-common/scal-to-vec1.c	(working copy)
@@ -6,38 +6,38 @@ 
 __attribute__((vector_size((elcount)*sizeof(type)))) type
 
 #define vidx(type, vec, idx) (*((type *) &(vec) + idx))
 
 
 extern float sfl;
 extern int   sint;
 extern long long sll;
 
 int main (int argc, char *argv[]) {
-    vector(8, short) v0 = {argc, 1,2,3,4,5,6,7};
+    vector(8, short) v0 = {(short)argc, 1,2,3,4,5,6,7};
     vector(8, short) v1;
 
     vector(4, float) f0 = {1., 2., 3., 4.};
     vector(4, float) f1, f2;
 
     vector(4, int) i0 = {1,2,3,4};
     vector(4, int) i1, i2;
 
     
     int     i = 12;
     double  d = 3.;
 
-    v1 = i + v0;        /* { dg-error "conversion of scalar to vector" } */
-    v1 = 99999 + v0;    /* { dg-error "conversion of scalar to vector" } */
+    v1 = i + v0;        /* { dg-error "conversion of scalar \[^\\n\]* to vector" } */
+    v1 = 99999 + v0;    /* { dg-error "conversion of scalar \[^\\n\]* to vector" } */
 
-    f1 = d + f0;        /* { dg-error "conversion of scalar to vector" } */
-    f1 = 1.3 + f0;      /* { dg-error "conversion of scalar to vector" } */
-    f1 = sll + f0;      /* { dg-error "conversion of scalar to vector" } */
-    f1 = ((int)998769576) + f0; /* { dg-error "conversion of scalar to vector" } */
+    f1 = d + f0;        /* { dg-error "conversion of scalar \[^\\n\]* to vector" } */
+    f1 = 1.3 + f0;      /* { dg-error "conversion of scalar \[^\\n\]* to vector" } */
+    f1 = sll + f0;      /* { dg-error "conversion of scalar \[^\\n\]* to vector" } */
+    f1 = ((int)998769576) + f0; /* { dg-error "conversion of scalar \[^\\n\]* to vector" } */
 
     /* convert.c should take care of this.  */
-    i1 = sfl + i0;      /* { dg-error "can't convert value to a vector" } */
-    i1 = 1.5 + i0;      /* { dg-error "can't convert value to a vector" } */
-    v1 = d + v0;        /* { dg-error "can't convert value to a vector" } */
+    i1 = sfl + i0;      /* { dg-error "can't convert value to a vector|invalid operands" } */
+    i1 = 1.5 + i0;      /* { dg-error "can't convert value to a vector|invalid operands" } */
+    v1 = d + v0;        /* { dg-error "can't convert value to a vector|invalid operands" } */
 
     return 0;
 }
Index: testsuite/c-c++-common/vector-scalar.c
===================================================================
--- testsuite/c-c++-common/vector-scalar.c	(revision 0)
+++ testsuite/c-c++-common/vector-scalar.c	(revision 0)
@@ -0,0 +1,10 @@ 
+/* { dg-do compile } */
+
+typedef float vecf __attribute__ ((vector_size (4 * sizeof (float))));
+typedef short veci __attribute__ ((vector_size (8 * sizeof (short))));
+
+void f (vecf *d, veci *i)
+{
+  (void) ((*d *= 2) < 0);
+  (void) ((((*i - 1) >> 2) != 0) | *i);
+}

Property changes on: testsuite/c-c++-common/vector-scalar.c
___________________________________________________________________
Added: svn:keywords
   + Author Date Id Revision URL
Added: svn:eol-style
   + native

Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 192153)
+++ cp/typeck.c	(working copy)
@@ -3855,20 +3855,54 @@  cp_build_binary_op (location_t location,
 	  || (!null_ptr_cst_p (orig_op1) 
 	      && !TYPE_PTR_OR_PTRMEM_P (type1)))
       && (complain & tf_warning))
     {
       source_location loc =
 	expansion_point_location_if_in_system_header (input_location);
 
       warning_at (loc, OPT_Wpointer_arith, "NULL used in arithmetic");
     }
 
+  /* In case when one of the operands of the binary operation is
+     a vector and another is a scalar -- convert scalar to vector.  */
+  if ((code0 == VECTOR_TYPE) != (code1 == VECTOR_TYPE))
+    {
+      enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1,
+						     complain & tf_error);
+
+      switch (convert_flag)
+        {
+          case stv_error:
+            return error_mark_node;
+          case stv_firstarg:
+            {
+              op0 = convert (TREE_TYPE (type1), op0);
+              op0 = build_vector_from_val (type1, op0);
+              type0 = TREE_TYPE (op0);
+              code0 = TREE_CODE (type0);
+              converted = 1;
+              break;
+            }
+          case stv_secondarg:
+            {
+              op1 = convert (TREE_TYPE (type0), op1);
+              op1 = build_vector_from_val (type0, op1);
+              type1 = TREE_TYPE (op1);
+              code1 = TREE_CODE (type1);
+              converted = 1;
+              break;
+            }
+          default:
+            break;
+        }
+    }
+
   switch (code)
     {
     case MINUS_EXPR:
       /* Subtraction of two similar pointers.
 	 We must subtract them as integers, then divide by object size.  */
       if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
 	  && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0),
 							TREE_TYPE (type1)))
 	return pointer_diff (op0, op1, common_pointer_type (type0, type1),
 			     complain);
@@ -3978,21 +4012,27 @@  cp_build_binary_op (location_t location,
     case TRUTH_AND_EXPR:
     case TRUTH_OR_EXPR:
       result_type = boolean_type_node;
       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 == VECTOR_TYPE && code1 == VECTOR_TYPE
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
 	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
 	  && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
 	  && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
 	{
 	  result_type = type0;
 	  converted = 1;
 	}
       else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
 	{
 	  result_type = type0;
@@ -4015,21 +4055,27 @@  cp_build_binary_op (location_t location,
 	  /* Convert the shift-count to an integer, regardless of
 	     size of value being shifted.  */
 	  if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node)
 	    op1 = cp_convert (integer_type_node, op1, complain);
 	  /* Avoid converting op1 to result_type later.  */
 	  converted = 1;
 	}
       break;
 
     case LSHIFT_EXPR:
-      if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+      if (code0 == VECTOR_TYPE && code1 == INTEGER_TYPE
+          && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE)
+        {
+          result_type = type0;
+          converted = 1;
+        }
+      else if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
 	  && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
 	  && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE
 	  && TYPE_VECTOR_SUBPARTS (type0) == TYPE_VECTOR_SUBPARTS (type1))
 	{
 	  result_type = type0;
 	  converted = 1;
 	}
       else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
 	{
 	  result_type = type0;
Index: c-family/c-common.c
===================================================================
--- c-family/c-common.c	(revision 192153)
+++ c-family/c-common.c	(working copy)
@@ -11147,11 +11147,114 @@  convert_vector_to_pointer_for_subscript
 
       c_common_mark_addressable_vec (*vecp);
       type = build_qualified_type (TREE_TYPE (type), TYPE_QUALS (type));
       type = build_pointer_type (type);
       type1 = build_pointer_type (TREE_TYPE (*vecp));
       *vecp = build1 (ADDR_EXPR, type1, *vecp);
       *vecp = convert (type, *vecp);
     }
 }
 
+/* Determine which of the operands, if any, is a scalar that needs to be
+   converted to a vector, for the range of operations.  */
+enum stv_conv
+scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1,
+		  bool complain)
+{
+  tree type0 = TREE_TYPE (op0);
+  tree type1 = TREE_TYPE (op1);
+  bool integer_only_op = false;
+  enum stv_conv ret = stv_firstarg;
+
+  gcc_assert (TREE_CODE (type0) == VECTOR_TYPE
+	      || TREE_CODE (type1) == VECTOR_TYPE);
+  switch (code)
+    {
+      /* Most GENERIC binary expressions require homogeneous arguments.
+	 LSHIFT_EXPR and RSHIFT_EXPR are exceptions and accept a first
+	 argument that is a vector and a second one that is a scalar, so
+	 we never return stv_secondarg for them.  */
+      case RSHIFT_EXPR:
+      case LSHIFT_EXPR:
+	if (TREE_CODE (type0) == INTEGER_TYPE
+	    && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+	  {
+	    if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+	      {
+		if (complain)
+		  error_at (loc, "conversion of scalar %qT to vector %qT "
+			    "involves truncation", type0, type1);
+		return stv_error;
+	      }
+	    else
+	      return stv_firstarg;
+	  }
+	break;
+
+      case BIT_IOR_EXPR:
+      case BIT_XOR_EXPR:
+      case BIT_AND_EXPR:
+	integer_only_op = true;
+	/* ... fall through ...  */
+
+      case PLUS_EXPR:
+      case MINUS_EXPR:
+      case MULT_EXPR:
+      case TRUNC_DIV_EXPR:
+      case CEIL_DIV_EXPR:
+      case FLOOR_DIV_EXPR:
+      case ROUND_DIV_EXPR:
+      case EXACT_DIV_EXPR:
+      case TRUNC_MOD_EXPR:
+      case FLOOR_MOD_EXPR:
+      case RDIV_EXPR:
+      case EQ_EXPR:
+      case NE_EXPR:
+      case LE_EXPR:
+      case GE_EXPR:
+      case LT_EXPR:
+      case GT_EXPR:
+      /* What about UNLT_EXPR?  */
+	if (TREE_CODE (type0) == VECTOR_TYPE)
+	  {
+	    tree tmp;
+	    ret = stv_secondarg;
+	    /* Swap TYPE0 with TYPE1 and OP0 with OP1  */
+	    tmp = type0; type0 = type1; type1 = tmp;
+	    tmp = op0; op0 = op1; op1 = tmp;
+	  }
+
+	if (TREE_CODE (type0) == INTEGER_TYPE
+	    && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+	  {
+	    if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+	      {
+		if (complain)
+		  error_at (loc, "conversion of scalar %qT to vector %qT "
+			    "involves truncation", type0, type1);
+		return stv_error;
+	      }
+	    return ret;
+	  }
+	else if (!integer_only_op
+		    /* Allow integer --> real conversion if safe.  */
+		 && (TREE_CODE (type0) == REAL_TYPE
+		     || TREE_CODE (type0) == INTEGER_TYPE)
+		 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (type1)))
+	  {
+	    if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+	      {
+		if (complain)
+		  error_at (loc, "conversion of scalar %qT to vector %qT "
+			    "involves truncation", type0, type1);
+		return stv_error;
+	      }
+	    return ret;
+	  }
+      default:
+	break;
+    }
+
+  return stv_nothing;
+}
+
 #include "gt-c-family-c-common.h"
Index: c-family/c-common.h
===================================================================
--- c-family/c-common.h	(revision 192153)
+++ c-family/c-common.h	(working copy)
@@ -1115,11 +1115,22 @@  struct GTY(()) tree_userdef_literal {
 #define USERDEF_LITERAL_NUM_STRING(NODE) \
   (((struct tree_userdef_literal *)USERDEF_LITERAL_CHECK (NODE))->num_string)
 
 #define USERDEF_LITERAL_TYPE(NODE) \
   (TREE_TYPE (USERDEF_LITERAL_VALUE (NODE)))
 
 extern tree build_userdef_literal (tree suffix_id, tree value, tree num_string);
 
 extern void convert_vector_to_pointer_for_subscript (location_t, tree*, tree);
 
+/* Possibe cases of scalar_to_vector conversion.  */
+enum stv_conv {
+  stv_error,        /* Error occured.  */
+  stv_nothing,      /* Nothing happened.  */
+  stv_firstarg,     /* First argument must be expanded.  */
+  stv_secondarg     /* Second argument must be expanded.  */
+};
+
+extern enum stv_conv scalar_to_vector (location_t loc, enum tree_code code,
+				       tree op0, tree op1, bool);
+
 #endif /* ! GCC_C_COMMON_H */
Index: fold-const.c
===================================================================
--- fold-const.c	(revision 192153)
+++ fold-const.c	(working copy)
@@ -12850,21 +12850,21 @@  fold_binary_loc (location_t loc,
 	  if (TREE_INT_CST_HIGH (arg01) == 0
 	      && TREE_INT_CST_LOW (arg01)
 		 == (unsigned HOST_WIDE_INT) (TYPE_PRECISION (itype) - 1))
 	    {
 	      if (TYPE_UNSIGNED (itype))
 		{
 		  itype = signed_type_for (itype);
 		  arg00 = fold_convert_loc (loc, itype, arg00);
 		}
 	      return fold_build2_loc (loc, code == EQ_EXPR ? GE_EXPR : LT_EXPR,
-				  type, arg00, build_int_cst (itype, 0));
+				  type, arg00, build_zero_cst (itype));
 	    }
 	}
 
       /* (X ^ Y) == 0 becomes X == Y, and (X ^ Y) != 0 becomes X != Y.  */
       if (integer_zerop (arg1)
 	  && TREE_CODE (arg0) == BIT_XOR_EXPR)
 	return fold_build2_loc (loc, code, type, TREE_OPERAND (arg0, 0),
 			    TREE_OPERAND (arg0, 1));
 
       /* (X ^ Y) == Y becomes X == 0.  We know that Y has no side-effects.  */
Index: c/c-typeck.c
===================================================================
--- c/c-typeck.c	(revision 192153)
+++ c/c-typeck.c	(working copy)
@@ -33,38 +33,31 @@  along with GCC; see the file COPYING3.
 #include "langhooks.h"
 #include "c-tree.h"
 #include "c-lang.h"
 #include "flags.h"
 #include "intl.h"
 #include "target.h"
 #include "tree-iterator.h"
 #include "bitmap.h"
 #include "gimple.h"
 #include "c-family/c-objc.h"
+#include "c-family/c-common.h"
 
 /* Possible cases of implicit bad conversions.  Used to select
    diagnostic messages in convert_for_assignment.  */
 enum impl_conv {
   ic_argpass,
   ic_assign,
   ic_init,
   ic_return
 };
 
-/* Possibe cases of scalar_to_vector conversion.  */
-enum stv_conv {
-  stv_error,        /* Error occured.  */
-  stv_nothing,      /* Nothing happened.  */
-  stv_firstarg,     /* First argument must be expanded.  */
-  stv_secondarg     /* Second argument must be expanded.  */
-};
-
 /* The level of nesting inside "__alignof__".  */
 int in_alignof;
 
 /* The level of nesting inside "sizeof".  */
 int in_sizeof;
 
 /* The level of nesting inside "typeof".  */
 int in_typeof;
 
 /* The argument of last parsed sizeof expression, only to be tested
@@ -9368,102 +9361,20 @@  push_cleanup (tree decl, tree cleanup, b
   bool stmt_expr;
 
   code = eh_only ? TRY_CATCH_EXPR : TRY_FINALLY_EXPR;
   stmt = build_stmt (DECL_SOURCE_LOCATION (decl), code, NULL, cleanup);
   add_stmt (stmt);
   stmt_expr = STATEMENT_LIST_STMT_EXPR (cur_stmt_list);
   list = push_stmt_list ();
   TREE_OPERAND (stmt, 0) = list;
   STATEMENT_LIST_STMT_EXPR (list) = stmt_expr;
 }
-
-/* Convert scalar to vector for the range of operations.  */
-static enum stv_conv
-scalar_to_vector (location_t loc, enum tree_code code, tree op0, tree op1)
-{
-  tree type0 = TREE_TYPE (op0);
-  tree type1 = TREE_TYPE (op1);
-  bool integer_only_op = false;
-  enum stv_conv ret = stv_firstarg;
-
-  gcc_assert (TREE_CODE (type0) == VECTOR_TYPE
-	      || TREE_CODE (type1) == VECTOR_TYPE);
-  switch (code)
-    {
-      case RSHIFT_EXPR:
-      case LSHIFT_EXPR:
-	if (TREE_CODE (type0) == INTEGER_TYPE
-	    && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
-	  {
-	    if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
-	      {
-		error_at (loc, "conversion of scalar to vector "
-			       "involves truncation");
-		return stv_error;
-	      }
-	    else
-	      return stv_firstarg;
-	  }
-	break;
-
-      case BIT_IOR_EXPR:
-      case BIT_XOR_EXPR:
-      case BIT_AND_EXPR:
-	integer_only_op = true;
-	/* ... fall through ...  */
-
-      case PLUS_EXPR:
-      case MINUS_EXPR:
-      case MULT_EXPR:
-      case TRUNC_DIV_EXPR:
-      case TRUNC_MOD_EXPR:
-      case RDIV_EXPR:
-	if (TREE_CODE (type0) == VECTOR_TYPE)
-	  {
-	    tree tmp;
-	    ret = stv_secondarg;
-	    /* Swap TYPE0 with TYPE1 and OP0 with OP1  */
-	    tmp = type0; type0 = type1; type1 = tmp;
-	    tmp = op0; op0 = op1; op1 = tmp;
-	  }
-
-	if (TREE_CODE (type0) == INTEGER_TYPE
-	    && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
-	  {
-	    if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
-	      {
-		error_at (loc, "conversion of scalar to vector "
-			       "involves truncation");
-		return stv_error;
-	      }
-	    return ret;
-	  }
-	else if (!integer_only_op
-		    /* Allow integer --> real conversion if safe.  */
-		 && (TREE_CODE (type0) == REAL_TYPE
-		     || TREE_CODE (type0) == INTEGER_TYPE)
-		 && SCALAR_FLOAT_TYPE_P (TREE_TYPE (type1)))
-	  {
-	    if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
-	      {
-		error_at (loc, "conversion of scalar to vector "
-			       "involves truncation");
-		return stv_error;
-	      }
-	    return ret;
-	  }
-      default:
-	break;
-    }
-
-  return stv_nothing;
-}
 
 /* Build a binary-operation expression without default conversions.
    CODE is the kind of expression to build.
    LOCATION is the operator's location.
    This function differs from `build' in several ways:
    the data type of the result is computed and recorded in it,
    warnings are generated if arg data types are invalid,
    special handling for addition and subtraction of pointers is known,
    and some optimization is done (operations on narrow ints
    are done in the narrower type when that gives the same result).
@@ -9640,21 +9551,22 @@  build_binary_op (location_t location, en
       type1 = eptype;
       op1 = convert (eptype, op1);
     }
 
   objc_ok = objc_compare_types (type0, type1, -3, NULL_TREE);
 
   /* In case when one of the operands of the binary operation is
      a vector and another is a scalar -- convert scalar to vector.  */
   if ((code0 == VECTOR_TYPE) != (code1 == VECTOR_TYPE))
     {
-      enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1);
+      enum stv_conv convert_flag = scalar_to_vector (location, code, op0, op1,
+						     true);
 
       switch (convert_flag)
 	{
 	  case stv_error:
 	    return error_mark_node;
 	  case stv_firstarg:
 	    {
               bool maybe_const = true;
               tree sc;
               sc = c_fully_fold (op0, false, &maybe_const);
Index: c/Make-lang.in
===================================================================
--- c/Make-lang.in	(revision 192153)
+++ c/Make-lang.in	(working copy)
@@ -185,12 +185,12 @@  c/c-objc-common.o : c/c-objc-common.c c/
 c/c-parser.o : c/c-parser.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
 	$(TM_H) $(TREE_H) $(C_TREE_H) $(C_COMMON_H) $(C_PRAGMA_H) $(CPPLIB_H) \
 	$(GGC_H) $(TIMEVAR_H) $(INPUT_H) $(FLAGS_H) \
 	gt-c-c-parser.h langhooks.h \
 	$(VEC_H) $(TARGET_H) $(CGRAPH_H) $(PLUGIN_H) \
 	c-family/c-objc.h
 
 c/c-typeck.o : c/c-typeck.c c/c-lang.h $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
 	$(TREE_H) $(C_TREE_H) $(TARGET_H) $(FLAGS_H) intl.h \
 	langhooks.h tree-iterator.h $(BITMAP_H) $(GIMPLE_H) \
-	c-family/c-objc.h
+	c-family/c-objc.h c-family/c-common.h