Pull to refresh
Logo
C++26 makes trivial infinite loops well-defined

C++26 makes trivial infinite loops well-defined

Rule Changes

Empty loops like `while (true);` were undefined behavior since C++11; the new standard defines them

2 days ago: Explainer publishes on the change

Overview

Updated 1 hour ago

A compiler could legally delete `while (true);` from your C++ program, and Clang actually did: execution fell through into whatever code the linker placed next, producing a demo that printed "Hello world!" after `main` supposedly never ended. That was allowed because trivial infinite loops were undefined behavior since C++11. C++26 makes them well-defined.

The fix gives empty infinite loops forward-progress semantics and replaces the body with a call to `std::this_thread::yield()`. It also closes a 13-year divergence from C, which never made `while (1);` undefined. The change matters most for embedded and kernel code that uses such loops to halt a device on fatal errors.

Why it matters

Empty infinite loops halt embedded devices on fatal errors; compilers previously could delete them. C++26 guarantees the loop survives optimization.

Questions about this story

Free account needed to ask — your question is kept and asked for you right after sign-up. Answers are public.

No questions yet — be the first to ask.

Key Indicators

2011
Year C++ made trivial infinite loops undefined behavior
C++11's forward-progress guarantee let compilers assume any thread eventually terminates.
Mar 2024
When WG21 adopted P2809R3
Adopted as a standard change and a defect report, so implementations can apply it in older language modes.
4
Loop forms now well-defined
`while (true);`, `for (;;);`, `do {} while (true);`, and loops with a constant true condition.
Clang
Compiler that exploited the undefined behavior
Optimized away `while (true);` in a demo, letting `main` fall through to a function printing "Hello world!".

Voices

Curated perspectives — historical figures and your fellow readers.

Ever wondered what historical figures would say about today's headlines?

Sign up to generate historical perspectives on this story.

People Involved

Organizations Involved

Timeline

August 2011 September 2026

7 events Latest: 2 days ago
Tap a bar to jump to that date
  1. Explainer publishes on the change

    Latest Analysis

    Sandor Dargo's article details the history, the Clang demo, and the scope of the new rules.

  2. P3881R0 proposes broader fix

    Proposal

    Motion to extend forward-progress to all infinite loops, not just trivial ones.

  3. CWG files issue 2923

    Standards

    Forward-progress note deemed factually wrong; removal approved by the Core Working Group.

  4. Clang implements P2809

    Implementation

    Compiler lands support and stops assuming trivial loops terminate in C++11 and later modes.

  5. WG21 adopts P2809R3

    Standard

    Trivial infinite loops redefined as well-defined, replaced with a yield call; accepted as a defect report.

  6. C11 publishes with the divergence

    Standard

    C added a constant-expression exception keeping `while (1);` well-defined; C++ did not.

  7. C++11 publishes forward-progress rule

    Standard

    The guarantee let compilers assume any thread eventually terminates, making trivial infinite loops undefined behavior.

Scenarios

1

C++26 publishes with trivial infinite loops well-defined

Likely Resolves by Jan 31, 2027

Discussed by: WG21, compiler release notes

The standard is expected to be finalized in late 2026 with the change already adopted. The published text will define trivial infinite loops as well-defined and specify the yield replacement, locking in the fix for all conforming compilers.

2

WG21 extends forward-progress to all infinite loops

Possible Resolves by End of 2027

Discussed by: P3881R0 authors, WG21

P3881R0 proposes giving forward-progress semantics to every infinite loop without side effects, not just the empty-body forms. The trade-off is lost optimization speculation, which the paper argues is rarely realized in practice. Adoption would remove the remaining undefined-behavior source entirely.

3

Compilers diverge on older language modes

Possible Resolves by Q2 2027

Discussed by: Compiler engineers, Sandor Dargo

Because P2809 was accepted as a defect report, implementations may apply the fix in C++11, 14, 17, and 20 modes, but coverage can differ. Freestanding implementations are explicitly allowed to skip the yield replacement, which matters on bare-metal systems where a halt loop must stay a halt. Portability surprises could surface on older codebases.

Historical Context

2 moments from history that rhyme with this story — and how they unfolded.

December 2011

C11 forward-progress rule (2011)

The C and C++ standards committees both introduced forward-progress guarantees in 2011. C added one more rule: loops whose controlling expression is a constant expression cannot be assumed to terminate. C++ did not.

Then

`while (1);` became well-defined in C but undefined behavior in C++ from that day onward.

Now

The two languages diverged for 13 years, with C++ compilers free to delete empty infinite loops while C compilers could not.

Why this matters now

This divergence is the exact gap that P2809R3 closes. The C++ fix deliberately avoids copying C's broader rule, using a narrower definition to preserve optimization flexibility.

2015 onward

Rust's well-defined loop semantics (2015)

Rust shipped with `loop {}` as a language primitive: an infinite loop is a normal construct the compiler treats as non-terminating by default, except where the developer opts in to additional assumptions.

Then

Rust developers never faced the surprise of a halt loop being optimized away.

Now

Rust's design became a reference point for C++ proposals; P3881R0 cites cross-language consistency with Rust as a reason to extend forward-progress to all infinite loops.

Why this matters now

Rust's approach shows the alternative C++ could have chosen and gives the broader proposal a concrete precedent for making infinite loops well-defined without losing useful optimizations.

Sources

(6)