From: Jakub Jelinek Date: Mon, 20 Nov 2017 12:57:50 +0000 (+0100) Subject: re PR c++/82781 (Vector extension operators return wrong result in constexpr) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f370e36dc9aba0a5cafa4e6fac893b49acbfb6e8;p=gcc.git re PR c++/82781 (Vector extension operators return wrong result in constexpr) PR c++/82781 * constexpr.c (cxx_eval_vector_conditional_expression): New function. (cxx_eval_constant_expression) : Use it instead of cxx_eval_conditional_expression. * g++.dg/ext/constexpr-pr82781.C: New test. From-SVN: r254952 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 410b18b42fd..6f4d30e1dfb 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2017-11-20 Jakub Jelinek + + PR c++/82781 + * constexpr.c (cxx_eval_vector_conditional_expression): New function. + (cxx_eval_constant_expression) : Use it instead + of cxx_eval_conditional_expression. + 2017-11-19 Jakub Jelinek PR c/66618 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index d6b6843e804..5eac64bd8a3 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -2086,6 +2086,45 @@ cxx_eval_conditional_expression (const constexpr_ctx *ctx, tree t, jump_target); } +/* Subroutine of cxx_eval_constant_expression. + Attempt to evaluate vector condition expressions. Unlike + cxx_eval_conditional_expression, VEC_COND_EXPR acts like a normal + ternary arithmetics operation, where all 3 arguments have to be + evaluated as constants and then folding computes the result from + them. */ + +static tree +cxx_eval_vector_conditional_expression (const constexpr_ctx *ctx, tree t, + bool *non_constant_p, bool *overflow_p) +{ + tree arg1 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), + /*lval*/false, + non_constant_p, overflow_p); + VERIFY_CONSTANT (arg1); + tree arg2 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), + /*lval*/false, + non_constant_p, overflow_p); + VERIFY_CONSTANT (arg2); + tree arg3 = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 2), + /*lval*/false, + non_constant_p, overflow_p); + VERIFY_CONSTANT (arg3); + location_t loc = EXPR_LOCATION (t); + tree type = TREE_TYPE (t); + tree r = fold_ternary_loc (loc, VEC_COND_EXPR, type, arg1, arg2, arg3); + if (r == NULL_TREE) + { + if (arg1 == TREE_OPERAND (t, 0) + && arg2 == TREE_OPERAND (t, 1) + && arg3 == TREE_OPERAND (t, 2)) + r = t; + else + r = build3_loc (loc, VEC_COND_EXPR, type, arg1, arg2, arg3); + } + VERIFY_CONSTANT (r); + return r; +} + /* Returns less than, equal to, or greater than zero if KEY is found to be less than, to match, or to be greater than the constructor_elt's INDEX. */ @@ -4398,12 +4437,14 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, jump_target); break; } - /* FALLTHRU */ - case VEC_COND_EXPR: r = cxx_eval_conditional_expression (ctx, t, lval, non_constant_p, overflow_p, jump_target); break; + case VEC_COND_EXPR: + r = cxx_eval_vector_conditional_expression (ctx, t, non_constant_p, + overflow_p); + break; case CONSTRUCTOR: if (TREE_CONSTANT (t)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c6b860c6ce9..6148d4b5384 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2017-11-20 Jakub Jelinek + + PR c++/82781 + * g++.dg/ext/constexpr-pr82781.C: New test. + 2017-11-20 Christophe Lyon * gcc.target/arm/pr69180.c: Use -: for no column in expected diff --git a/gcc/testsuite/g++.dg/ext/constexpr-pr82781.C b/gcc/testsuite/g++.dg/ext/constexpr-pr82781.C new file mode 100644 index 00000000000..eee0159351c --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/constexpr-pr82781.C @@ -0,0 +1,12 @@ +// PR c++/82781 +// { dg-do compile { target c++11 } } + +typedef int V __attribute__ ((vector_size (16))); +constexpr V b1 = { 0, 1, 10, 20 }; +constexpr V b2 = { 0, 2, 10, 0 }; +constexpr V b3 = b1 == b2; + +static_assert (b3[0] == -1, ""); +static_assert (b3[1] == 0, ""); +static_assert (b3[2] == -1, ""); +static_assert (b3[3] == 0, "");