Skip to content

P2809R3 Trivial infinite loops are not Undefined Behavior #6894

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 9 additions & 4 deletions source/basic.tex
Original file line number Diff line number Diff line change
Expand Up @@ -6478,13 +6478,18 @@
following:
\begin{itemize}
\item terminate,
\item invoke the function \tcode{std::this_thread::yield}\iref{thread.thread.this},
\item make a call to a library I/O function,
\item perform an access through a volatile glvalue, or
\item perform a synchronization operation or an atomic operation.
\item perform an access through a volatile glvalue,
\item perform a synchronization operation or an atomic operation, or
\item continue execution of a trivial infinite loop\iref{stmt.iter.general}.
\end{itemize}
\begin{note}
This is intended to allow compiler transformations such as removal of
empty loops, even when termination cannot be proven.
This is intended to allow compiler transformations
such as removal, merging, and reordering of empty loops,
even when termination cannot be proven.
An affordance is made for trivial infinite loops,
which cannot be removed nor reordered.
\end{note}

\pnum
Expand Down
30 changes: 30 additions & 0 deletions source/statements.tex
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,36 @@
Thus after the \keyword{while} statement, \tcode{i} is no longer in scope.
\end{example}

\pnum
A \defnadj{trivially empty}{iteration statement} is
an iteration statement matching one of the following forms:
\begin{itemize}
\item \tcode{while (} \grammarterm{expression} \tcode{) ;}
\item \tcode{while (} \grammarterm{expression} \tcode{) \{ \}}
\item \tcode{do ; while (} \grammarterm{expression} \tcode{) ;}
\item \tcode{do \{ \} while (} \grammarterm{expression} \tcode{) ;}
\item \tcode{for (} \grammarterm{init-statement} \opt{\grammarterm{expression}} \tcode{; ) ;}
\item \tcode{for (} \grammarterm{init-statement} \opt{\grammarterm{expression}} \tcode{; ) \{ \}}
\end{itemize}
The \defnadj{controlling}{expression} of a trivially empty iteration statement
is the \grammarterm{expression} of
a \tcode{while}, \tcode{do}, or \tcode{for} statement
(or \tcode{true}, if the \tcode{for} statement has no \grammarterm{expression}).
A \defnadj{trivial infinite}{loop} is a trivially empty iteration statement
for which the converted controlling expression is a constant expression,
when interpreted as a \grammarterm{constant-expression}\iref{expr.const}, and
evaluates to \tcode{true}.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this "interpreted as a constant-expression" wording mean that the following will be treated as a trivial infinite loop?

(Note that std::is_constant_evaluated() returns true when evaluated in a constant-expression, and false when not manifestly constant-evaluated.)

#include  <type_traits>
int main() {
    while (std::is_constant_evaluated());
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that is a "trivial infinite loop". That means, optimizations are reduced around that loop and each step of the loop execution will call yield. Except that the body of the loop will never actually be executed at runtime.

The \grammarterm{statement} of a trivial infinite loop is replaced with
a call to the function \tcode{std::this_thread::yield}\iref{thread.thread.this};
it is implementation-defined whether this replacement occurs
on freestanding implementations.
\begin{note}
In a freestanding environment,
concurrent forward progress is not guaranteed;
such systems therefore require explicit cooperation.
A call to yield can add implicit cooperation where none is otherwise intended.
\end{note}

\rSec2[stmt.while]{The \keyword{while} statement}%
\indextext{statement!\idxcode{while}}

Expand Down