Case 08: Enum Value Change¶
| Field | Value |
|---|---|
| Verdict | ๐ด BREAKING |
| Category | Breaking |
| Platforms | Linux |
| Flags | ABI break, API break |
Detected ChangeKinds |
enum_member_value_changed |
| Source files | browse on GitHub |
Category: Type Layout | Verdict: ๐ก ABI CHANGE (exit 4)
Note on abidiff 2.4.0: Returns exit 4. Semantically breaking because code compiled against v1 uses hardcoded integer values (e.g.,
if (c == 1)for GREEN) that now mean YELLOW.
What breaks¶
Any switch statement or comparison against GREEN (value 1) now hits the YELLOW
branch instead. Serialized data (files, network packets) using the old integer values
becomes misinterpreted.
Why abidiff catches it¶
Reports 1 enumerator insertion: 'Color::YELLOW' value '1' and two enumerator changes
for GREEN and BLUE.
Code diff¶
| v1.c | v2.c |
|---|---|
{ RED=0, GREEN=1, BLUE=2 } |
{ RED=0, YELLOW=1, GREEN=2, BLUE=3 } |
Reproduce manually¶
gcc -shared -fPIC -g v1.c -o libfoo_v1.so
gcc -shared -fPIC -g v2.c -o libfoo_v2.so
abidw --out-file v1.xml libfoo_v1.so
abidw --out-file v2.xml libfoo_v2.so
abidiff v1.xml v2.xml
echo "exit: $?" # โ 4
How to fix¶
Only append new enum values at the end (never insert). Mark the enum as "reserved slots allowed" in documentation. Never renumber existing values.
Real-world example¶
Protocol Buffers (protobuf) enforces append-only enum values for exactly this reason. Inserting values in the middle is a common source of subtle bugs in versioned protocols.
Real Failure Demo¶
Severity: CRITICAL
Scenario: app compiled with v1 (GREEN=1) calls get_signal() which returns GREEN. With v2 GREEN shifted to 2 โ app checks against wrong value.
# Build v1 + app
gcc -shared -fPIC -g v1.c -o libfoo.so
gcc -g app.c -I. -L. -lfoo -Wl,-rpath,. -o app
./app
# โ GREEN (correct)
# Swap in v2 (no recompile)
gcc -shared -fPIC -g v2.c -o libfoo.so
./app
# โ ERROR: expected GREEN=1, got 2
Why CRITICAL: The integer value 1 now means YELLOW in v2 but the compiled app
still checks if c == 1 for GREEN. Any stored values, protocol messages, or switch
statements using the old numeric constants silently route to the wrong branch.
References¶
Source files¶
See also: Examples overview ยท All BREAKING cases ยท Category: Breaking.