diff options
author | glisse <glisse@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-10-25 13:02:42 +0000 |
---|---|---|
committer | glisse <glisse@138bc75d-0d04-0410-961f-82ee72b054a4> | 2012-10-25 13:02:42 +0000 |
commit | 7b463b19dc03823c76901c991cd2d193a947c363 (patch) | |
tree | c59298c0a1950703d2a7fcb4db22f59f20b81981 /gcc/cp/call.c | |
parent | 3998d451cbb0459f9afa961336b1862566678a0a (diff) | |
download | gcc-7b463b19dc03823c76901c991cd2d193a947c363.tar.gz |
2012-10-25 Marc Glisse <marc.glisse@inria.fr>
PR c++/54427
gcc/
* tree.c (signed_or_unsigned_type_for): Handle vectors.
gcc/cp/
* typeck.c (build_x_conditional_expr): Handle VEC_COND_EXPR.
* call.c (build_conditional_expr_1): Likewise.
gcc/c-family/
* c-common.c (scalar_to_vector): Handle VEC_COND_EXPR.
gcc/testsuite/
* g++.dg/ext/vector19.C: New testcase.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@192808 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cp/call.c')
-rw-r--r-- | gcc/cp/call.c | 86 |
1 files changed, 78 insertions, 8 deletions
diff --git a/gcc/cp/call.c b/gcc/cp/call.c index e21049b8e64..df241056d2e 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -4373,18 +4373,90 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3, arg2 = arg1 = save_expr (arg1); } + /* If something has already gone wrong, just pass that fact up the + tree. */ + if (error_operand_p (arg1) + || error_operand_p (arg2) + || error_operand_p (arg3)) + return error_mark_node; + + orig_arg2 = arg2; + orig_arg3 = arg3; + + if (VECTOR_INTEGER_TYPE_P (TREE_TYPE (arg1))) + { + arg1 = force_rvalue (arg1, complain); + 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 least one operand of a vector conditional operator " + "must be a vector"); + return error_mark_node; + } + + if ((TREE_CODE (arg2_type) == VECTOR_TYPE) + != (TREE_CODE (arg3_type) == VECTOR_TYPE)) + { + enum stv_conv convert_flag = + scalar_to_vector (input_location, VEC_COND_EXPR, arg2, arg3, + complain & tf_error); + + switch (convert_flag) + { + case stv_error: + return error_mark_node; + case stv_firstarg: + { + 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 = convert (TREE_TYPE (arg2_type), arg3); + arg3 = build_vector_from_val (arg2_type, arg3); + arg3_type = TREE_TYPE (arg3); + break; + } + default: + break; + } + } + + if (!same_type_p (arg2_type, arg3_type) + || TYPE_VECTOR_SUBPARTS (arg1_type) + != TYPE_VECTOR_SUBPARTS (arg2_type) + || TYPE_SIZE (arg1_type) != TYPE_SIZE (arg2_type)) + { + if (complain & tf_error) + error ("incompatible vector types in conditional expression: " + "%qT, %qT and %qT", TREE_TYPE (arg1), TREE_TYPE (orig_arg2), + TREE_TYPE (orig_arg3)); + return error_mark_node; + } + + if (!COMPARISON_CLASS_P (arg1)) + arg1 = build2 (NE_EXPR, signed_type_for (arg1_type), arg1, + build_zero_cst (arg1_type)); + return build3 (VEC_COND_EXPR, arg2_type, arg1, arg2, arg3); + } + /* [expr.cond] The first expression is implicitly converted to bool (clause _conv_). */ arg1 = perform_implicit_conversion_flags (boolean_type_node, arg1, complain, LOOKUP_NORMAL); - - /* If something has already gone wrong, just pass that fact up the - tree. */ - if (error_operand_p (arg1) - || error_operand_p (arg2) - || error_operand_p (arg3)) + if (error_operand_p (arg1)) return error_mark_node; /* [expr.cond] @@ -4394,8 +4466,6 @@ build_conditional_expr_1 (tree arg1, tree arg2, tree arg3, array-to-pointer (_conv.array_), and function-to-pointer (_conv.func_) standard conversions are performed on the second and third operands. */ - orig_arg2 = arg2; - orig_arg3 = arg3; arg2_type = unlowered_expr_type (arg2); arg3_type = unlowered_expr_type (arg3); if (VOID_TYPE_P (arg2_type) || VOID_TYPE_P (arg3_type)) |