diff options
author | Jakub Jelinek <jakub@redhat.com> | 2020-03-03 19:49:12 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2020-03-03 19:49:12 +0100 |
commit | 0e0ffbfc23ba98ac40cbc6330e2750a6448b79d9 (patch) | |
tree | b1bc62617e2fc04e62a6766ddbae192fab2f4563 | |
parent | 6b9ce2b4eb49e3c930730c3721323349e2136b1a (diff) | |
download | gcc-0e0ffbfc23ba98ac40cbc6330e2750a6448b79d9.zip gcc-0e0ffbfc23ba98ac40cbc6330e2750a6448b79d9.tar.gz gcc-0e0ffbfc23ba98ac40cbc6330e2750a6448b79d9.tar.bz2 |
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.
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/constexpr.c | 9 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/ext/pr93998.C | 14 |
4 files changed, 33 insertions, 4 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index edc088e..e776110 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,4 +1,11 @@ -2020-03-03 Jun Ma <JunMa@linux.alibaba.com> +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. + +2020-03-03 Jun Ma <JunMa@linux.alibaba.com> * coroutines.cc (finish_co_await_expr): Build co_await_expr with unknown_type_node. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 3da1609..c2d4460 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -5474,9 +5474,10 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 1), false, non_constant_p, overflow_p); - if (!*non_constant_p) - /* Adjust the type of the result to the type of the temporary. */ - r = adjust_temp_type (TREE_TYPE (t), r); + if (*non_constant_p) + break; + /* Adjust the type of the result to the type of the temporary. */ + r = adjust_temp_type (TREE_TYPE (t), r); if (TARGET_EXPR_CLEANUP (t) && !CLEANUP_EH_ONLY (t)) ctx->global->cleanups->safe_push (TARGET_EXPR_CLEANUP (t)); r = unshare_constructor (r); @@ -5528,6 +5529,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, { r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), false, non_constant_p, overflow_p); + if (*non_constant_p) + break; ctx->global->values.put (t, r); if (ctx->save_exprs) ctx->save_exprs->safe_push (t); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5b174bb..db579e3 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2020-03-03 Jakub Jelinek <jakub@redhat.com> + + PR c++/93998 + * g++.dg/ext/pr93998.C: New test. + 2020-03-03 Dennis Zhang <dennis.zhang@arm.com> * gcc.target/arm/simd/bf16_cvt_1.c: New test. diff --git a/gcc/testsuite/g++.dg/ext/pr93998.C b/gcc/testsuite/g++.dg/ext/pr93998.C new file mode 100644 index 0000000..766c331 --- /dev/null +++ b/gcc/testsuite/g++.dg/ext/pr93998.C @@ -0,0 +1,14 @@ +// PR c++/93998 +// { dg-do compile { target c++11 } } + +struct C +{ + constexpr bool operator== (C x) const noexcept { return v == x.v; } + int v; +}; + +int +foo (const C a, const C b, bool c) +{ + return __builtin_expect (!!(a == b || c), 1) ? 0 : 1; +} |