Skip to content

Case 26b โ€” Union Field Added (No Size Change)

Field Value
Verdict ๐ŸŸข COMPATIBLE
Category Addition (Compatible)
Platforms Linux, macOS, Windows
Flags โ€”
Detected ChangeKinds โ€”
Source files examples/case26b_union_field_added_compatible/

Verdict: ๐ŸŸข COMPATIBLE

What changes

Version Definition
v1 union Value { long l; double d; };
v2 union Value { long l; double d; int i; };

Real Failure Demo

Severity: COMPATIBLE - NO FAILURE EXPECTED

This is intentionally a non-failure demo. The app is compiled against v1, then run with v2 under the old SONAME. Because the added union field does not change sizeof(union Value), the result is identical.

cmake -S examples -B /tmp/abicheck-examples-build -DCMAKE_BUILD_TYPE=Debug
cmake --build /tmp/abicheck-examples-build --target case27_union_field_added_compatible_app case27_union_field_added_compatible_v2

tmp=$(mktemp -d)
cp /tmp/abicheck-examples-build/case27_union_field_added_compatible/app_v1 "$tmp/"
cp /tmp/abicheck-examples-build/case27_union_field_added_compatible/libv2.so "$tmp/libv1.so"
(cd "$tmp" && LD_LIBRARY_PATH=. ./app_v1)
# after fill: v.l = 42
# OK: union field added (no size change) is ABI-compatible

Why this is NOT a binary ABI break

Adding int i does not change sizeof(union Value): - v1: sizeof = max(sizeof(long)=8, sizeof(double)=8) = 8 bytes - v2: sizeof = max(sizeof(long)=8, sizeof(double)=8, sizeof(int)=4) = 8 bytes

All existing fields remain at offset 0 with identical sizes and types. Old callers allocate exactly the right amount of memory for v2 as well. No struct embeddings or array strides are affected.

Contrast with case26

Case Field added sizeof change Verdict
case26 double d added to {int i; float f} 4 โ†’ 8 bytes BREAKING (TYPE_SIZE_CHANGED)
case26b int i added to {long l; double d} 8 โ†’ 8 bytes COMPATIBLE

Code diff

 union Value {
     long   l;
     double d;
+    int    i;   /* sizeof stays 8: smaller than double โ€” COMPATIBLE */
 };

Runtime Demo

# Build libs + app compiled against v1
make all

# Run with v1 lib โ€” baseline
./app_v1
# โ†’ after fill: v.l = 42
# โ†’ OK: union field added (no size change) is ABI-compatible

# Swap to v2 (old binary, new lib โ€” sizeof unchanged)
make test-compat
# โ†’ after fill: v.l = 42   โ† identical result
# โ†’ EXIT:0                  โ† app exits cleanly: COMPATIBLE

abicheck output

abicheck detects no TYPE_SIZE_CHANGED (sizeof stays 8 bytes). The added int i field appears as a new union member โ€” informational only. Verdict: COMPATIBLE.

References


Source files

  • CMakeLists.txt
  • app.c

See also: Examples overview ยท All COMPATIBLE cases ยท Category: Addition (Compatible).