From: Jakub Jelinek Date: Mon, 25 Jun 2018 16:47:39 +0000 (+0200) Subject: backport: re PR c++/82781 (Vector extension operators return wrong result in constexpr) X-Git-Tag: releases/gcc-6.5.0~252 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4f408a9a24eeaec92bf6852b17d33b0b7a8db6fe;p=thirdparty%2Fgcc.git backport: re PR c++/82781 (Vector extension operators return wrong result in constexpr) Backported from mainline 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. * g++.dg/ext/constexpr-pr82781.C: New test. From-SVN: r262031 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 220130b1ff44..8f7ffacdf716 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2018-06-25 Jakub Jelinek + + Backported from mainline + 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. + 2018-03-29 Ville Voutilainen Backport from mainline diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index e105f6611c14..76da3645a36a 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1919,6 +1919,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. */ @@ -4031,12 +4070,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 e52f2fcf1600..a9629a6e0c4e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,6 +1,11 @@ 2018-06-25 Jakub Jelinek Backported from mainline + 2017-11-20 Jakub Jelinek + + PR c++/82781 + * g++.dg/ext/constexpr-pr82781.C: New test. + 2017-10-12 Jakub Jelinek PR c++/82159 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 000000000000..eee0159351c8 --- /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, "");