c++: Fix non-constant TARGET_EXPR constexpr handing [PR93998]
authorJakub Jelinek <jakub@redhat.com>
Tue, 3 Mar 2020 18:49:12 +0000 (19:49 +0100)
committerJakub Jelinek <jakub@redhat.com>
Tue, 3 Mar 2020 18:49:12 +0000 (19:49 +0100)
commit0e0ffbfc23ba98ac40cbc6330e2750a6448b79d9
treeb1bc62617e2fc04e62a6766ddbae192fab2f4563
parent6b9ce2b4eb49e3c930730c3721323349e2136b1a
c++: Fix non-constant TARGET_EXPR constexpr handing [PR93998]

We ICE on the following testcase since I've added the SAVE_EXPR-like
constexpr handling where the TARGET_EXPR initializer (and cleanup) is
evaluated only once (because it might have side-effects like new or delete
expressions in it).
The problem is if the TARGET_EXPR (but I guess in theory SAVE_EXPR too)
initializer is *non_constant_p.  We still remember the result, but already
not that it is *non_constant_p.  Normally that wouldn't be a big problem,
if something is *non_constant_p, we only or into it and so the whole
expression will be non-constant too.  Except in the builtins handling,
we try to evaluate the arguments with non_constant_p pointing into a dummy1
bool which we ignore.  This is because some builtins might fold into a
constant even if they don't have a constexpr argument.  Unfortunately if
we evaluate the TARGET_EXPR first in the argument of such a builtin and then
once again, we don't set *non_constant_p.

So, either we don't remember the TARGET_EXPR/SAVE_EXPR result if it wasn't
constant, like the following patch does, or we could remember it, but in
some way that would make it clear that it is non-constant (e.g. by
pushing into the global->values SAVE_EXPR, SAVE_EXPR entry and perhaps
for TARGET_EXPR don't remember it on TARGET_EXPR_SLOT, but the TARGET_EXPR
itself and similarly push TARGET_EXPR, TARGET_EXPR and if we see those
after the lookup, diagnose + set *non_constant_p.  Or we could perhaps
during the builtin argument evaluation push expressions into a different
save_expr vec and undo them afterwards.

2020-03-03  Jakub Jelinek  <jakub@redhat.com>

PR c++/93998
* constexpr.c (cxx_eval_constant_expression)
<case TARGET_EXPR, case SAVE_EXPR>: Don't record anything if
*non_constant_p is true.

* g++.dg/ext/pr93998.C: New test.
gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/ext/pr93998.C [new file with mode: 0644]