diff options
author | Jakub Jelinek <jakub@redhat.com> | 2017-11-20 13:57:50 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2017-11-20 13:57:50 +0100 |
commit | f370e36dc9aba0a5cafa4e6fac893b49acbfb6e8 (patch) | |
tree | e033191b795202233509a9f5a4c1100f881dfdc6 /gcc/cp/constexpr.c | |
parent | 1ebafce0bc9072f9aabd0692bbb1aeda672f6b60 (diff) | |
download | gcc-f370e36dc9aba0a5cafa4e6fac893b49acbfb6e8.zip gcc-f370e36dc9aba0a5cafa4e6fac893b49acbfb6e8.tar.gz gcc-f370e36dc9aba0a5cafa4e6fac893b49acbfb6e8.tar.bz2 |
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) <case VEC_COND_EXPR>: Use it instead
of cxx_eval_conditional_expression.
* g++.dg/ext/constexpr-pr82781.C: New test.
From-SVN: r254952
Diffstat (limited to 'gcc/cp/constexpr.c')
-rw-r--r-- | gcc/cp/constexpr.c | 45 |
1 files changed, 43 insertions, 2 deletions
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index d6b6843..5eac64b 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)) |