Case 210: Calling Convention Respelled via a Macro¶
| Field | Value |
|---|---|
| Verdict | ✅ NO_CHANGE |
| Category | No Change |
| Classification | Rule |
| Platforms | Linux |
| Flags | — |
Detected ChangeKinds |
— |
| Source files | catalog/cases/case210_calling_convention_respelled_via_macro/ |
| Rule family | calling-convention-respelled-via-macro |
| Subject | Safe changes correctly not flagged |
Category: No change | Verdict: ✅ NO_CHANGE
Verdict and consumer impact¶
The negative control for
case209_calling_convention_changed_via_macro.
v1 declares vector_dot/vector_scale with a literal
__attribute__((ms_abi)); v2 introduces
#define MATHLIB_CALL __attribute__((ms_abi)) and declares
MATHLIB_CALL double vector_dot(...). The declaration text changes, but the
convention it expands to does not. Both libraries are built ms_abi, so the
binary interface is identical and an unchanged old consumer works against
either — nothing for abicheck to report.
Old/new diff¶
| v1.h | v2.h |
|---|---|
__attribute__((ms_abi)) double vector_dot(...); |
#define MATHLIB_CALL __attribute__((ms_abi))MATHLIB_CALL double vector_dot(...); |
abicheck command¶
gcc -shared -fPIC -g v1.c -o libv1.so
gcc -shared -fPIC -g v2.c -o libv2.so
abicheck compare libv1.so libv2.so --header old=v1.h --header new=v2.h
Expected abicheck finding¶
calling_convention_changed and func_return_changed must both stay
absent. Verified identically with ABICHECK_AST_FRONTEND=castxml and
ABICHECK_AST_FRONTEND=clang.
Minimum evidence¶
min_evidence: L2 — the only difference between the two versions is in the
public header text; the binaries (and their DWARF) are the same. Below the
header AST the two sides are trivially identical and the case proves nothing.
Why abicheck catches it¶
abicheck compares the effective convention per function after macro
expansion, not the declaration's spelling. A text-level recovery that read
only the literal tokens would see ms_abi on the v1 side and an opaque
MATHLIB_CALL on the v2 side and manufacture a convention (or return-type)
change; this case pins that it does not.
Runtime failure demonstration¶
There is none — that is the point of the control.
gcc -shared -fPIC -g v1.c -o libv1.so
gcc -g app.c -L. -lv1 -Wl,-rpath,'$ORIGIN' -o app -lm
./app # dot product = 32.0, scaled = {2.0, 4.0, 6.0} exit 0
gcc -shared -fPIC -g v2.c -o libv1.so # swap in v2, no recompile
./app # dot product = 32.0, scaled = {2.0, 4.0, 6.0} exit 0
Safe redesign¶
Nothing to redesign: routing an existing convention through a macro is a safe refactoring as long as the macro's expansion matches the shipped convention on every platform.
Cross-tool comparison¶
abidw --out-file v1.xml libv1.so
abidw --out-file v2.xml libv2.so
abidiff v1.xml v2.xml # no changes: the binaries are identical
Source files¶
CMakeLists.txtapp.cv1.cv1.hv2.cv2.h
See also: Compatibility Catalog · All NO_CHANGE cases · Category: No Change · Rule: Calling convention respelled via a macro · Subject: Safe changes correctly not flagged.