Case 206: Deprecation Documented Without the Attribute¶
| Field | Value |
|---|---|
| Verdict | ✅ NO_CHANGE |
| Category | No Change |
| Classification | Rule |
| Platforms | Linux |
| Flags | Bad practice |
Detected ChangeKinds |
— |
| Source files | catalog/cases/case206_deprecation_documented_without_attribute/ |
| Rule family | deprecation-documented-without-attribute |
| Subject | Safe changes correctly not flagged |
Category: No Change | Verdict: ✅ NO_CHANGE
Verdict and consumer impact¶
legacy_open() is announced as deprecated in a header comment only — no
__attribute__((deprecated)), no [[deprecated]]. The declaration itself is
byte-for-byte the same contract as v1, so no consumer is warned, no call site
changes, and no tool that reads declarations can see the intent.
This is the negative control paired with
case205_public_function_marked_deprecated.
The pair proves two things about these two fixtures: a real deprecation
attribute is reported (case205), and prose in a comment is not silently
promoted into one (this case).
It is worth being explicit about what the "correct" answer here means. NO_CHANGE
is the right technical verdict — nothing observable changed — and it is
also the reason a comment is a poor way to deprecate: the announcement
reaches a human reading the header and nothing else in the toolchain.
Old/new diff¶
| v1.h | v2.h |
|---|---|
int legacy_open(const char *name); |
/* Deprecated: prefer modern_open() ... */int legacy_open(const char *name); |
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¶
func_deprecated_added is expected not to fire. That absence is the point
of the case.
Minimum evidence¶
min_evidence: L2 — the public header AST is the tier at which a deprecation
attribute would be visible at all, so it is the tier at which "no attribute
was added" is a claim worth making. At L0/L1 the two sides are trivially
identical and the case proves nothing.
Why abicheck catches it¶
Nothing is reported because the header-AST backends record a declaration's
attributes, not the comments around it: a /* Deprecated: ... */ block is
discarded by the preprocessor before the AST exists. A text-scanning
heuristic looking for the word "deprecated" near a declaration would report a
finding here that no consumer can act on.
Runtime failure demonstration¶
Severity: none — verified no observable effect.
gcc -shared -fPIC -g v1.c -o libv1.so
gcc -g app.c -L. -lv1 -Wl,-rpath,. -o app
./app
# → legacy_open -> 1
gcc -shared -fPIC -g v2.c -o libv1.so # swap in v2, no recompile
./app
# → legacy_open -> 1 (identical output, and no warning on recompile either)
Safe redesign¶
Mark the declaration with __attribute__((deprecated)) (C) or
[[deprecated]] (C++17) in addition to documenting it, so the deprecation
reaches the compiler, the consumer's build log, and a compatibility report —
which is exactly what case205 does.
Cross-tool comparison¶
abidiff and ABICC also report nothing here. The case is a guard against
inventing a finding from prose, not a differentiator.
Source files¶
CMakeLists.txtapp.cv1.cv1.hv2.cv2.h
See also: Compatibility Catalog · All NO_CHANGE cases · Category: No Change · Rule: Deprecation announced only in a comment · Subject: Safe changes correctly not flagged.