[Bug c++/114462] [C++26] P2809R3 - Trivial infinite loops are not undefined behavior

2024-04-10 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114462

Jakub Jelinek  changed:

   What|Removed |Added

 Status|ASSIGNED|RESOLVED
 Resolution|--- |FIXED

--- Comment #9 from Jakub Jelinek  ---
Implemented for GCC 14.1.

[Bug c++/114462] [C++26] P2809R3 - Trivial infinite loops are not undefined behavior

2024-04-10 Thread cvs-commit at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114462

--- Comment #8 from GCC Commits  ---
The master branch has been updated by Jakub Jelinek :

https://gcc.gnu.org/g:4be1cc5f50578fafcdcbd09160235066d76a3f86

commit r14-9887-g4be1cc5f50578fafcdcbd09160235066d76a3f86
Author: Jakub Jelinek 
Date:   Wed Apr 10 10:08:12 2024 +0200

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  

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.

[Bug c++/114462] [C++26] P2809R3 - Trivial infinite loops are not undefined behavior

2024-04-02 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114462

Jakub Jelinek  changed:

   What|Removed |Added

 Status|NEW |ASSIGNED
   Assignee|unassigned at gcc dot gnu.org  |jakub at gcc dot gnu.org

--- Comment #7 from Jakub Jelinek  ---
Created attachment 57847
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=57847=edit
gcc14-pr114462.patch

Untested fix.

[Bug c++/114462] [C++26] P2809R3 - Trivial infinite loops are not undefined behavior

2024-03-25 Thread pinskia at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114462

Andrew Pinski  changed:

   What|Removed |Added

   Last reconfirmed||2024-03-25
 Ever confirmed|0   |1
 Status|UNCONFIRMED |NEW

--- Comment #6 from Andrew Pinski  ---
.

[Bug c++/114462] [C++26] P2809R3 - Trivial infinite loops are not undefined behavior

2024-03-25 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114462

--- Comment #5 from Jakub Jelinek  ---
constexpr bool foo () { return true; }
volatile int v;

void
bar (int x)
{
  switch (x)
{
case 0:
  while (foo ()) ;
  break;
case 1:
  while (foo ()) {}
  break;
case 2:
  do ; while (foo ());
  break;
case 3:
  do {} while (foo ());
  break;
case 4:
  do {} while (foo ());
  break;
case 5:
  for (v = 42; foo (); ) ;
  break;
case 6:
  for (v = 42; foo (); ) {}
  break;
case 7:
  for (int w = 42; foo (); ) ;
  break;
case 8:
  for (int w = 42; foo (); ) {}
  break;
default:
  break;
}
}

[Bug c++/114462] [C++26] P2809R3 - Trivial infinite loops are not undefined behavior

2024-03-25 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114462

--- Comment #4 from Jakub Jelinek  ---
Ah, if there is a declaration in the condition, then it is not a valid trivial
empty iteration statement.

Anyway, I'd say cp_fold should for WHILE_STMT, DO_STMT and FOR_STMT if the body
is
a STATEMENT_LIST with no statements at all or an empty statement (do we have
predicate for NOP_EXPR to void_type_node of integer_zero_node?) and in case of
FOR_STMT empty increment expression argument try to evaluate the condition as
mce_false constant expression and if it evaluates to constant non-zero, replace
the condition with boolean_true_node.

[Bug c++/114462] [C++26] P2809R3 - Trivial infinite loops are not undefined behavior

2024-03-25 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114462

--- Comment #3 from Jakub Jelinek  ---
And another case to watch for is:
void
qux ()
{
  while (const bool b = bar ())
;
}

[Bug c++/114462] [C++26] P2809R3 - Trivial infinite loops are not undefined behavior

2024-03-25 Thread jakub at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114462

Jakub Jelinek  changed:

   What|Removed |Added

 CC||jason at gcc dot gnu.org

--- Comment #2 from Jakub Jelinek  ---
I know, but I think this will need changes in the C++ FE.
I was asking recently Jason what the "when interpreted as a
constant-expression"
in the paper actually means, whether such expression should be evaluated as
manifestly constant evaluation or not.
If yes, it seems like an incompatible change in a DR, because say
#include 
void
foo ()
{
  while (std::is_constant_evaluated ())
;
}
changing behavior from previous doing nothing to an infinite loop.
If it is not manifestly constant evaluation, still, the FE would need to (at
least for the cases listed in the paper) try to silently constant evaluate the
condition (with
mce_false such that std::is_constant_evaluated () is folded to false in there;
but perhaps only during cp_fold_function?) and if that evaluates to non-zero
replace the condition with true, such that the middle-end would then really
consider it as infinite loop regardless of -ffinite-loops.
Because if one has
constexpr bool
bar ()
{
  return true;
}
void
baz ()
{
  while (bar ())
;
}
we want middle-end to see while (true) ; rather than while (bar ()) ; because
the latter would be under -ffinite-loops decision.

[Bug c++/114462] [C++26] P2809R3 - Trivial infinite loops are not undefined behavior

2024-03-25 Thread rguenth at gcc dot gnu.org via Gcc-bugs
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114462

--- Comment #1 from Richard Biener  ---
Apart from marking via -ffinite-loops GCC considers loops without an exit as
not required to make "forward progress".  That's more than just a constant
controlling expression but should allow optimizing most relevant cases.