diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 94c1237480b..b6502ec3727 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2017-12-15 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. + 2017-10-30 Paolo Carlini PR c++/82085 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 41734c402ee..327c093a953 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -2044,6 +2044,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. */ @@ -4361,12 +4400,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 d07efb8df61..8b4e034690f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2017-12-15 Jakub Jelinek + + Backported from mainline + 2017-11-20 Jakub Jelinek + + PR c++/82781 + * g++.dg/ext/constexpr-pr82781.C: New test. + 2017-12-15 Richard Biener Backport from mainline 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, "");