Skip to content

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

Verdict: NO_CHANGE (exit 0)

_No ABI changes detected._

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.txt
  • app.c
  • v1.c
  • v1.h
  • v2.c
  • v2.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.