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.gli...@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.

--
Marc Glisse
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;
            }
        }
 

Reply via email to