The following short program was accepted by gcc-8, but results in an error with gcc-9.1: template <class T> constexpr T test_increment(T t) { return ++t; } int main() { constexpr double t = test_increment(2.0f); static_assert(t == 3); } With: /home/john/t.cpp: In function ‘int main()’: /home/john/t.cpp:15:38: in ‘constexpr’ expansion of ‘test_increment<float>(2.0e+0f)’ /home/john/t.cpp:15:43: error: ‘((float)1 + 2.0e+0f)’ is not a constant expression 15 | constexpr double t = test_increment(2.0f); | ^ /home/john/t.cpp:16:19: error: non-constant condition for static assertion 16 | static_assert(t == 3); The problem is present for all floating point types (float, double, long double and __float128), but not integers. Replacing ++t with t+1 fixes the problem.
Forgot to add: this effects operators ++ and -- in both prefix and postfix versions. The standard selected (14,17,2a) makes no difference.
Looks like it started with r269078.
Candidate fix: --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -4162,7 +4162,6 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, tree type = TREE_TYPE (t); tree op = TREE_OPERAND (t, 0); tree offset = TREE_OPERAND (t, 1); - gcc_assert (TREE_CONSTANT (offset)); /* The operand as an lvalue. */ op = cxx_eval_constant_expression (ctx, op, true, @@ -4172,6 +4171,11 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, tree val = cxx_eval_constant_expression (ctx, op, false, non_constant_p, overflow_p); + + offset = cxx_eval_constant_expression (ctx, offset, false, + non_constant_p, overflow_p); + VERIFY_CONSTANT (offset); + /* Don't VERIFY_CONSTANT if this might be dealing with a pointer to a local array in a constexpr function. */ bool ptr = INDIRECT_TYPE_P (TREE_TYPE (val));
Nevermind, that doesn't work.
But using fold_simple instead does seem to work, so I'll go with that.
#c3 looks right to me, what doesn't work? The testcase certainly works fine with that change.
Stuff like (int *) 4 is invalid in constexpr, but that's what OFFSET can be. Comes from 6442 inc = cp_convert (argtype, inc, complain); in cp_build_unary_op. E.g., int array[4]; constexpr int *foo (int *p) { return ++p; } constexpr int *p = foo(array);
Ah, you're right. Perhaps it could be done by doing the constexpr evaluation only if not CONSTANT_CLASS_P (offset) or similar, TREE_CONSTANT is probably not good enough as that is likely set already on the unfolded FLOAT_EXPR.
Author: mpolacek Date: Tue Sep 10 21:04:33 2019 New Revision: 275613 URL: https://gcc.gnu.org/viewcvs?rev=275613&root=gcc&view=rev Log: PR c++/91705 - constexpr evaluation rejects ++/-- on floats. * constexpr.c (cxx_eval_increment_expression): Call fold_simple on the offset. * g++.dg/cpp1y/constexpr-incr2.C: New test. Added: trunk/gcc/testsuite/g++.dg/cpp1y/constexpr-incr2.C Modified: trunk/gcc/cp/ChangeLog trunk/gcc/cp/constexpr.c trunk/gcc/testsuite/ChangeLog
Fixed on trunk so far.
Author: mpolacek Date: Tue Sep 10 22:39:46 2019 New Revision: 275615 URL: https://gcc.gnu.org/viewcvs?rev=275615&root=gcc&view=rev Log: PR c++/91705 - constexpr evaluation rejects ++/-- on floats. * constexpr.c (cxx_eval_increment_expression): Call fold_simple on the offset. * g++.dg/cpp1y/constexpr-incr2.C: New test. Added: branches/gcc-9-branch/gcc/testsuite/g++.dg/cpp1y/constexpr-incr2.C Modified: branches/gcc-9-branch/gcc/cp/ChangeLog branches/gcc-9-branch/gcc/cp/constexpr.c
Fixed.
*** Bug 91792 has been marked as a duplicate of this bug. ***