From 07298ffd6f7c2d2623272bba009a23750db12397 Mon Sep 17 00:00:00 2001 From: Marc Glisse Date: Sun, 14 Jul 2013 10:36:47 +0200 Subject: [PATCH] call.c (build_conditional_expr_1): Handle the case with 1 vector and 2 scalars. 2013-07-14 Marc Glisse 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. From-SVN: r200947 --- gcc/cp/ChangeLog | 6 +++++ gcc/cp/call.c | 54 ++++++++++++++++++++++++++++++++++--- gcc/cp/typeck.c | 27 ++++++++++++++----- gcc/testsuite/ChangeLog | 5 ++++ gcc/testsuite/g++.dg/ext/vector19.C | 3 +-- gcc/testsuite/g++.dg/ext/vector23.C | 24 +++++++++++++++++ 6 files changed, 107 insertions(+), 12 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/vector23.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 3cf5e77..b7de099 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,9 @@ +2013-07-14 Marc Glisse + + * 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. + 2013-07-13 Lubos Lunak PR c++/55203 diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 02daf82..3bb90ef 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4405,10 +4405,54 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree 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) @@ -4424,6 +4468,7 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3, 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); @@ -4431,6 +4476,7 @@ build_conditional_expr_1 (location_t loc, tree arg1, tree arg2, tree arg3, } 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); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 1d504ad..ef781a3 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -4535,23 +4535,38 @@ cp_build_binary_op (location_t location, 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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 41cea55..8f2d5a9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-07-14 Marc Glisse + + * g++.dg/ext/vector19.C: Adapt. + * g++.dg/ext/vector23.C: New testcase. + 2013-07-12 Michael Matz PR middle-end/55771 diff --git a/gcc/testsuite/g++.dg/ext/vector19.C b/gcc/testsuite/g++.dg/ext/vector19.C index ace1c64..4fd937f 100644 --- a/gcc/testsuite/g++.dg/ext/vector19.C +++ b/gcc/testsuite/g++.dg/ext/vector19.C @@ -37,8 +37,7 @@ 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 diff --git a/gcc/testsuite/g++.dg/ext/vector23.C b/gcc/testsuite/g++.dg/ext/vector23.C new file mode 100644 index 0000000..4e18427 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/vector23.C @@ -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" } +} -- 2.7.4