aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-cfg.cc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2024-04-10 10:08:12 +0200
committerJakub Jelinek <jakub@redhat.com>2024-04-10 10:19:04 +0200
commit4be1cc5f50578fafcdcbd09160235066d76a3f86 (patch)
treea763e327dd8ec081d05b7299de58c38efd149b00 /gcc/tree-cfg.cc
parent4923ed49b93352bcf9e43cafac38345e4a54c3f8 (diff)
downloadgcc-4be1cc5f50578fafcdcbd09160235066d76a3f86.zip
gcc-4be1cc5f50578fafcdcbd09160235066d76a3f86.tar.gz
gcc-4be1cc5f50578fafcdcbd09160235066d76a3f86.tar.bz2
c++: Implement C++26 P2809R3 - Trivial infinite loops are not Undefined Behavior
The following patch attempts to implement P2809R3, which has been voted in as a DR. The middle-end has its behavior documented: '-ffinite-loops' Assume that a loop with an exit will eventually take the exit and not loop indefinitely. This allows the compiler to remove loops that otherwise have no side-effects, not considering eventual endless looping as such. This option is enabled by default at '-O2' for C++ with -std=c++11 or higher. So, the following patch attempts to detect trivial infinite loops by detecting trivially empty loops, if their condition is not INTEGER_CST (that case is handled by the middle-end right already) trying to constant evaluate with mce=true their condition and if it evaluates to true (and -ffinite-loops and not processing_template_decl) wraps the condition into an ANNOTATE_EXPR which tells the middle-end that the loop shouldn't be loop->finite_p despite -ffinite-loops). Furthermore, the patch adds -Wtautological-compare warnings for loop conditions containing std::is_constant_evaluated(), either if those always evaluate to true, or always evaluate to false, or will evaluate to true just when checking if it is trivial infinite loop (and if in non-constexpr function also say that it will evaluate to false otherwise). The user is doing something weird in all those cases. 2024-04-10 Jakub Jelinek <jakub@redhat.com> PR c++/114462 gcc/ * tree-core.h (enum annot_expr_kind): Add annot_expr_maybe_infinite_kind enumerator. * gimplify.cc (gimple_boolify): Handle annot_expr_maybe_infinite_kind. * tree-cfg.cc (replace_loop_annotate_in_block): Likewise. (replace_loop_annotate): Likewise. Move loop->finite_p initialization before the replace_loop_annotate_in_block calls. * tree-pretty-print.cc (dump_generic_node): Handle annot_expr_maybe_infinite_kind. gcc/cp/ * semantics.cc: Implement C++26 P2809R3 - Trivial infinite loops are not Undefined Behavior. (maybe_warn_for_constant_evaluated): Add trivial_infinite argument and emit special diagnostics for that case. (finish_if_stmt_cond): Adjust caller. (finish_loop_cond): New function. (finish_while_stmt): Use it. (finish_do_stmt): Likewise. (finish_for_stmt): Likewise. gcc/testsuite/ * g++.dg/cpp26/trivial-infinite-loop1.C: New test. * g++.dg/cpp26/trivial-infinite-loop2.C: New test. * g++.dg/cpp26/trivial-infinite-loop3.C: New test.
Diffstat (limited to 'gcc/tree-cfg.cc')
-rw-r--r--gcc/tree-cfg.cc10
1 files changed, 7 insertions, 3 deletions
diff --git a/gcc/tree-cfg.cc b/gcc/tree-cfg.cc
index bdffc3b..96686db 100644
--- a/gcc/tree-cfg.cc
+++ b/gcc/tree-cfg.cc
@@ -297,6 +297,9 @@ replace_loop_annotate_in_block (basic_block bb, class loop *loop)
loop->can_be_parallel = true;
loop->safelen = INT_MAX;
break;
+ case annot_expr_maybe_infinite_kind:
+ loop->finite_p = false;
+ break;
default:
gcc_unreachable ();
}
@@ -320,12 +323,12 @@ replace_loop_annotate (void)
for (auto loop : loops_list (cfun, 0))
{
+ /* Push the global flag_finite_loops state down to individual loops. */
+ loop->finite_p = flag_finite_loops;
+
/* Check all exit source blocks for annotations. */
for (auto e : get_loop_exit_edges (loop))
replace_loop_annotate_in_block (e->src, loop);
-
- /* Push the global flag_finite_loops state down to individual loops. */
- loop->finite_p = flag_finite_loops;
}
/* Remove IFN_ANNOTATE. Safeguard for the case loop->latch == NULL. */
@@ -347,6 +350,7 @@ replace_loop_annotate (void)
case annot_expr_no_vector_kind:
case annot_expr_vector_kind:
case annot_expr_parallel_kind:
+ case annot_expr_maybe_infinite_kind:
break;
default:
gcc_unreachable ();