Skip to content

Case 34 โ€” Access Level Changed

Field Value
Verdict ๐ŸŸ  API_BREAK
Category API Break
Platforms Linux, macOS
Flags API break
Detected ChangeKinds โ€”
Source files browse on GitHub

Verdict: ๐ŸŸ  API_BREAK abicheck verdict: API_BREAK (with headers) / NO_CHANGE (ELF-only)

What changes

Version Member v1 access v2 access
helper() method public private
cache field public private
internal_init() method protected public
// v1
class Widget {
public:
    void render();
    void helper();       // public
    int cache;           // public
protected:
    void internal_init();
};

// v2
class Widget {
public:
    void render();
    void internal_init();  // promoted: protected โ†’ public
private:
    void helper();         // narrowed: public โ†’ private
    int cache;             // narrowed: public โ†’ private
};

Why this is NOT a binary ABI break

Access specifiers (public, private, protected) are compile-time only in C++. They are not stored in the ELF symbol table and do not appear in the mangled name.

At the binary level: - Symbol _ZN6Widget6helperEv is exported identically in both versions. - No vtable changes (non-virtual methods). - No struct layout changes (cache stays at same offset).

Old binaries compiled against v1 that call widget.helper() continue to link and run without errors โ€” the symbol resolves to the same address.

Why this IS a source-level break

New code compiled against v2 cannot call widget.helper() or widget.cache from outside the class โ€” the compiler will reject the access. This breaks source compatibility but not binary compatibility.

abicheck reports: - METHOD_ACCESS_CHANGED: helper (public โ†’ private) โ€” API_BREAK - FIELD_ACCESS_CHANGED: cache (public โ†’ private) โ€” API_BREAK

Tool comparison

Tool Verdict Reason
abicheck (ELF only) NO_CHANGE No ELF difference
abicheck (with headers) API_BREAK Parses C++ headers, detects access narrowing
abidiff NO_CHANGE No DWARF/ELF difference
ABICC API_BREAK Header parser detects Method_Became_Private

Benchmark note

The benchmark runs abicheck with headers for this case, so the expected verdict is API_BREAK. Without headers, abicheck correctly returns NO_CHANGE (the binary is unchanged).

Reproduce steps

cd examples/case34_access_level
g++ -shared -fPIC -o libv1.so v1.cpp
g++ -shared -fPIC -o libv2.so v2.cpp

# ELF-only: no change detected
abicheck dump libv1.so -o v1.json
abicheck dump libv2.so -o v2.json
abicheck compare v1.json v2.json   # โ†’ NO_CHANGE

# With headers: API_BREAK detected
abicheck dump libv1.so --header v1.hpp -o v1h.json
abicheck dump libv2.so --header v2.hpp -o v2h.json
abicheck compare v1h.json v2h.json  # โ†’ API_BREAK: METHOD_ACCESS_CHANGED

Why runtime result may differ from verdict

Access level narrowing: binary layout unchanged, compile fails

References


Source files

See also: Examples overview ยท All API_BREAK cases ยท Category: API Break.