Bug 91705 - [9 Regression] operator++ broken in constexpr floating point code
Summary: [9 Regression] operator++ broken in constexpr floating point code
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 9.1.0
: P3 normal
Target Milestone: 9.3
Assignee: Marek Polacek
URL:
Keywords: rejects-valid
: 91792 (view as bug list)
Depends on:
Blocks:
 
Reported: 2019-09-09 07:12 UTC by John Maddock
Modified: 2019-09-17 08:11 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2019-09-09 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description John Maddock 2019-09-09 07:12:12 UTC
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.
Comment 1 John Maddock 2019-09-09 09:34:31 UTC
Forgot to add: this effects operators ++ and -- in both prefix and postfix versions.  The standard selected (14,17,2a) makes no difference.
Comment 2 Marek Polacek 2019-09-09 18:58:36 UTC
Looks like it started with r269078.
Comment 3 Marek Polacek 2019-09-09 21:20:33 UTC
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));
Comment 4 Marek Polacek 2019-09-09 21:48:13 UTC
Nevermind, that doesn't work.
Comment 5 Marek Polacek 2019-09-09 21:57:14 UTC
But using fold_simple instead does seem to work, so I'll go with that.
Comment 6 Jakub Jelinek 2019-09-10 08:49:16 UTC
#c3 looks right to me, what doesn't work?  The testcase certainly works fine with that change.
Comment 7 Marek Polacek 2019-09-10 15:09:50 UTC
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);
Comment 8 Jakub Jelinek 2019-09-10 15:14:46 UTC
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.
Comment 9 Marek Polacek 2019-09-10 21:05:04 UTC
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
Comment 10 Marek Polacek 2019-09-10 21:06:31 UTC
Fixed on trunk so far.
Comment 11 Marek Polacek 2019-09-10 22:40:17 UTC
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
Comment 12 Marek Polacek 2019-09-11 01:34:45 UTC
Fixed.
Comment 13 Andrew Pinski 2019-09-17 08:11:30 UTC
*** Bug 91792 has been marked as a duplicate of this bug. ***