The Little Bool of Doom: When C23’s New Keywords Break 31-Year-Old Code

When a classic 1993 video game suddenly won’t compile on modern systems, the debugging journey that follows reveals fascinating insights about programming language evolution, backwards compatibility, and the subtle dangers lurking in type definitions.
The Core Insight
A Fedora maintainer’s routine rebuild of Chocolate DOOM—a faithful recreation of the original 1993 game—ran headfirst into GCC 15’s switch to C23 as the default standard. The culprit? C23 transformed bool, true, and false from macros into proper keywords, instantly breaking code that had worked fine for three decades.
The original DOOM source code defined its own boolean type:
typedef enum {
false,
true
} boolean;
This worked perfectly in C89 and C99, but C23’s new keywords now clash directly with these custom enum values. What seemed like a simple fix—switching to the built-in bool type—revealed an even deeper rabbit hole.
Why This Matters
The most fascinating part of this story isn’t the initial compilation failure—it’s what happened next. When developers tried using C99’s _Bool type instead of the custom enum, the game crashed immediately on startup. Through meticulous debugging, they discovered that _Bool and the custom enum behave fundamentally differently when initialized with -1.
With a 4-byte enum, comparing 0xFFFFFFFF to 0x0 yields false (not equal).
With a 1-byte _Bool containing 255, the compiler generates code that treats this value as both true and false simultaneously.
The assembly code tells the tale: while enum comparisons use straightforward CMP instructions, _Bool comparisons use TEST combined with special conditional logic. A _Bool value of 255 (from memset(..., -1, ...)) produces unexpected results because the compiler assumes _Bool can only ever be 0 or 1.
Key Takeaways
Language evolution has hidden costs: Every major language update potentially breaks existing code in subtle ways. C23’s keyword changes seemed harmless but affected countless projects.
Type size matters more than you think: The switch from a 4-byte enum to a 1-byte
_Boolchanged memory layout and comparison semantics in ways no one anticipated.Initialization patterns can be fragile: Using
memset(..., -1, ...)to initialize boolean arrays works with custom enums but creates undefined behavior with_Bool.Mass rebuilds reveal systemic issues: Fedora’s regular mass rebuilds serve as an early warning system for the entire open source ecosystem.
Debugging skills remain essential: Even in 2026, understanding assembly language and using gdb effectively saved the day.
Looking Ahead
This incident highlights a broader challenge in software maintenance: as programming languages modernize, they accumulate decades of legacy code with implicit assumptions about type behavior. The C23 standard committee made a sensible choice in promoting bool, true, and false to keywords—but millions of lines of existing code weren’t written with that future in mind.
For developers maintaining long-lived codebases, this story is a reminder to:
1. Explicitly specify C standards in build configurations rather than relying on compiler defaults
2. Test code against upcoming compiler versions before they become mainstream
3. Avoid relying on implementation-specific behavior of boolean types
4. Consider the full implications of “simple” type changes
The fix for Chocolate DOOM was ultimately straightforward: declare the project as C99 and include <stdbool.h>, but keep storing boolean values as int rather than _Bool. Sometimes the best solution is knowing which battles not to fight.
Based on analysis of “The little bool of doom” from blog.svgames.pl