Patchwork vector conditional expression with scalar arguments

login
register
mail settings
Submitter Marc Glisse
Date July 13, 2013, 7:19 p.m.
Message ID <alpine.DEB.2.02.1307132114160.18427@stedding.saclay.inria.fr>
Download mbox | patch
Permalink /patch/258837/
State New
Headers show

Comments

Marc Glisse - July 13, 2013, 7:19 p.m.
On Mon, 8 Jul 2013, Jason Merrill wrote:

> On 07/08/2013 05:28 PM, Marc Glisse wrote:
>> Perhaps the most conservative rule would be to only accept the case
>> where the sizes match and reject the others for now, so whatever is
>> decided later for other cases is unlikely to require a breaking change.
>> Though I would like the general case to be accepted eventually, whatever
>> it ends up meaning :)
>
> Makes sense to me.

Here it is then.

Bootstrap+testsuite on x86_64-unknown-linux-gnu.

2013-07-14  Marc Glisse  <marc.glisse@inria.fr>

gcc/cp/
 	* call.c (build_conditional_expr_1): Handle the case with 1 vector
 	and 2 scalars. Call save_expr before building a vector.
 	* typeck.c (cp_build_binary_op): Check complain before complaining.

gcc/testsuite/
 	* g++.dg/ext/vector19.C: Adapt.
 	* g++.dg/ext/vector23.C: New testcase.
Jason Merrill - July 13, 2013, 9:56 p.m.
OK.

Jason
Gerald Pfeifer - Aug. 4, 2013, 4:51 p.m.
On Sat, 13 Jul 2013, Marc Glisse wrote:
> 2013-07-14  Marc Glisse  <marc.glisse@inria.fr>
> 
> gcc/cp/
> 	* call.c (build_conditional_expr_1): Handle the case with 1 vector
> 	and 2 scalars. Call save_expr before building a vector.
> 	* typeck.c (cp_build_binary_op): Check complain before complaining.

Shouldn't this be documented somewhere (gcc/doc/*.texi and our 
web based release notes)?

Gerald

Patch

Index: testsuite/g++.dg/ext/vector19.C

===================================================================
--- testsuite/g++.dg/ext/vector19.C	(revision 200936)

+++ testsuite/g++.dg/ext/vector19.C	(working copy)

@@ -30,22 +30,21 @@  void i2 (vec2 *x, vec2 *y, vec2u *z)

 {
   *x = *y ? *x : *y;
   *y = *z ? *x : *y;
 }
 
 void j (vec2 *x, vec2 *y, vec2 *z, vec *t)
 {
   *x = (*y < *z) ? *x : 4.2; /* { dg-error "" } */
   *y = (*x < *z) ? 2.5 : *y; /* { dg-error "" } */
   *t = *t ? *t : *t; /* { dg-error "" } */
-  *z = (*x < *z) ? '1' : '0'; /* { dg-error "" } */

-  // The last one may eventually be accepted.

+  *z = (*x < *z) ? '1' : '0';

 }
 
 template <class A, class B>
 auto k (A *a, B b) -> decltype (*a ? *a : b);
 
 void k (...) {}
 
 void l (vec2 *v, double x)
 {
   k (v, x);
Index: testsuite/g++.dg/ext/vector23.C

===================================================================
--- testsuite/g++.dg/ext/vector23.C	(revision 0)

+++ testsuite/g++.dg/ext/vector23.C	(revision 0)

@@ -0,0 +1,24 @@ 

+/* { dg-do compile } */

+/* { dg-options "-std=gnu++1y -Wsign-conversion" } */

+

+typedef double vecd __attribute__((vector_size(4*sizeof(double))));

+typedef float vecf __attribute__((vector_size(8*sizeof(float))));

+typedef long vecl __attribute__((vector_size(4*sizeof(long))));

+typedef short vecs __attribute__((vector_size(8*sizeof(short))));

+typedef char vecc __attribute__((vector_size(16*sizeof(char))));

+

+auto f(vecf*a,float d,long long i){

+  return (*a<0)?d:i; // { dg-error "truncation" }

+}

+auto g(vecc*a){

+  return (*a<0)?3LL:42UL; // { dg-error "inferred scalar type" }

+}

+auto h(vecd*a){

+  return (*a<0)?'a':'c'; // { dg-error "inferred scalar type \[^\\n\]*double" }

+}

+auto i(vecc*a){

+  return (*a<0)?1:0.; // { dg-error "inferred scalar type" }

+}

+auto j(vecl*a,long i,unsigned long k){

+  return (*a<0)?i:k; // { dg-warning "may change the sign" }

+}


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

Index: cp/typeck.c

===================================================================
--- cp/typeck.c	(revision 200936)

+++ cp/typeck.c	(working copy)

@@ -4528,37 +4528,52 @@  cp_build_binary_op (location_t location,

 	    warning (OPT_Waddress, "comparison with string literal results in unspecified behaviour");
 	}
 
       if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE)
 	{
 	vector_compare:
 	  tree intt;
 	  if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (type0),
 							  TREE_TYPE (type1)))
 	    {
-	      error_at (location, "comparing vectors with different "

-				  "element types");

-	      inform (location, "operand types are %qT and %qT", type0, type1);

+	      if (complain & tf_error)

+		{

+		  error_at (location, "comparing vectors with different "

+				      "element types");

+		  inform (location, "operand types are %qT and %qT",

+			  type0, type1);

+		}

 	      return error_mark_node;
 	    }
 
 	  if (TYPE_VECTOR_SUBPARTS (type0) != TYPE_VECTOR_SUBPARTS (type1))
 	    {
-	      error_at (location, "comparing vectors with different "

-				  "number of elements");

-	      inform (location, "operand types are %qT and %qT", type0, type1);

+	      if (complain & tf_error)

+		{

+		  error_at (location, "comparing vectors with different "

+				      "number of elements");

+		  inform (location, "operand types are %qT and %qT",

+			  type0, type1);

+		}

 	      return error_mark_node;
 	    }
 
 	  /* Always construct signed integer vector type.  */
 	  intt = c_common_type_for_size (GET_MODE_BITSIZE
 					   (TYPE_MODE (TREE_TYPE (type0))), 0);
+	  if (!intt)

+	    {

+	      if (complain & tf_error)

+		error_at (location, "could not find an integer type "

+			  "of the same size as %qT", TREE_TYPE (type0));

+	      return error_mark_node;

+	    }

 	  result_type = build_opaque_vector_type (intt,
 						  TYPE_VECTOR_SUBPARTS (type0));
 	  converted = 1;
 	  break;
 	}
       build_type = boolean_type_node;
       if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
 	   || code0 == ENUMERAL_TYPE)
 	   && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
 	       || code1 == ENUMERAL_TYPE))
Index: cp/call.c

===================================================================
--- cp/call.c	(revision 200936)

+++ cp/call.c	(working copy)

@@ -4398,46 +4398,92 @@  build_conditional_expr_1 (location_t loc

       arg2 = force_rvalue (arg2, complain);
       arg3 = force_rvalue (arg3, complain);
 
       tree arg1_type = TREE_TYPE (arg1);
       arg2_type = TREE_TYPE (arg2);
       arg3_type = TREE_TYPE (arg3);
 
       if (TREE_CODE (arg2_type) != VECTOR_TYPE
 	  && TREE_CODE (arg3_type) != VECTOR_TYPE)
 	{
-	  if (complain & tf_error)

-	    error_at (loc, "at least one operand of a vector conditional "

-		      "operator must be a vector");

-	  return error_mark_node;

+	  /* Rely on the error messages of the scalar version.  */

+	  tree scal = build_conditional_expr_1 (loc, integer_one_node,

+						orig_arg2, orig_arg3, complain);

+	  if (scal == error_mark_node)

+	    return error_mark_node;

+	  tree stype = TREE_TYPE (scal);

+	  tree ctype = TREE_TYPE (arg1_type);

+	  if (TYPE_SIZE (stype) != TYPE_SIZE (ctype)

+	      || (!INTEGRAL_TYPE_P (stype) && !SCALAR_FLOAT_TYPE_P (stype)))

+	    {

+	      if (complain & tf_error)

+		error_at (loc, "inferred scalar type %qT is not an integer or "

+			  "floating point type of the same size as %qT", stype,

+			  COMPARISON_CLASS_P (arg1)

+			  ? TREE_TYPE (TREE_TYPE (TREE_OPERAND (arg1, 0)))

+			  : ctype);

+	      return error_mark_node;

+	    }

+

+	  tree vtype = build_opaque_vector_type (stype,

+			 TYPE_VECTOR_SUBPARTS (arg1_type));

+	  /* We could pass complain & tf_warning to unsafe_conversion_p,

+	     but the warnings (like Wsign-conversion) have already been

+	     given by the scalar build_conditional_expr_1. We still check

+	     unsafe_conversion_p to forbid truncating long long -> float.  */

+	  if (unsafe_conversion_p (stype, arg2, false))

+	    {

+	      if (complain & tf_error)

+		error_at (loc, "conversion of scalar %qT to vector %qT "

+			       "involves truncation", arg2_type, vtype);

+	      return error_mark_node;

+	    }

+	  if (unsafe_conversion_p (stype, arg3, false))

+	    {

+	      if (complain & tf_error)

+		error_at (loc, "conversion of scalar %qT to vector %qT "

+			       "involves truncation", arg3_type, vtype);

+	      return error_mark_node;

+	    }

+

+	  arg2 = cp_convert (stype, arg2, complain);

+	  arg2 = save_expr (arg2);

+	  arg2 = build_vector_from_val (vtype, arg2);

+	  arg2_type = vtype;

+	  arg3 = cp_convert (stype, arg3, complain);

+	  arg3 = save_expr (arg3);

+	  arg3 = build_vector_from_val (vtype, arg3);

+	  arg3_type = vtype;

 	}
 
       if ((TREE_CODE (arg2_type) == VECTOR_TYPE)
 	  != (TREE_CODE (arg3_type) == VECTOR_TYPE))
 	{
 	  enum stv_conv convert_flag =
 	    scalar_to_vector (loc, VEC_COND_EXPR, arg2, arg3,
 			      complain & tf_error);
 
 	  switch (convert_flag)
 	    {
 	      case stv_error:
 		return error_mark_node;
 	      case stv_firstarg:
 		{
+		  arg2 = save_expr (arg2);

 		  arg2 = convert (TREE_TYPE (arg3_type), arg2);
 		  arg2 = build_vector_from_val (arg3_type, arg2);
 		  arg2_type = TREE_TYPE (arg2);
 		  break;
 		}
 	      case stv_secondarg:
 		{
+		  arg3 = save_expr (arg3);

 		  arg3 = convert (TREE_TYPE (arg2_type), arg3);
 		  arg3 = build_vector_from_val (arg2_type, arg3);
 		  arg3_type = TREE_TYPE (arg3);
 		  break;
 		}
 	      default:
 		break;
 	    }
 	}