You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
tests/.clang-tidy disables thirteen checks, each with a documented reason about test idiom. But clang-tidy applies the configuration of the main translation
unit, not of the file a diagnostic lands in. So every one of those thirteen
suppressions also applies to include/morph/** headers, whenever the header is
reached from a TU under tests/.
That means a header finding's visibility depends on which TU happened to reach
it. The same finding in the same header is reported from an examples/ TU and
silently dropped from a tests/ TU.
This matters now for two reasons:
clang-tidy-diff's changed-lines scope hides 101 findings in include/morph/, each a trap for the next edit to that line #580's census gate proposal is directly affected. That census recommends
gating on "all 60 [verify_interface_header_sets] stubs plus every TU under tests/". The tests/ half of that gate cannot report cppcoreguidelines-pro-bounds-avoid-unchecked-container-access — the check
that is 250 of the census's 596 — in any header it reaches, nor bugprone-unchecked-optional-access (4 of the census's flagged possible
defects), nor readability-identifier-length (58). A gate built to that
recipe would be green on findings it was built to catch.
It is a second instance of this repository's named failure mode — a
control that reports success while measuring nothing — and it is invisible
from inside: tests/.clang-tidy is a correct and well-argued file about tests/, and nothing in it says it reaches further.
Verification status: reproduced
Revision 0e3b8823 (origin/master), clang-tidy 22.1.8, .clang-tidy
unmodified, compile database configured exactly as .github/workflows/ci.yml's
clang-tidy job configures it (ci.yml:2191, every optional feature ON).
The case is include/morph/forms/forms.hpp:496, which #627 records as leaking
two cppcoreguidelines-pro-bounds-avoid-unchecked-container-access findings past
a wrapped NOLINTNEXTLINE. It is inside forEachNamedMember, a template, so it
needs a TU that instantiates it.
From a tests/ TU that does instantiate it — tests/test_views.cpp, whose own comments say it "exercises buildViewSchema's forEachNamedMember walk":
Zero, across the whole run — not just at :496. The check is off for the entire
include closure.
Other checks from the same TU are unaffected, so the run was real:
$ grep -E "forms\.hpp:(489|496)" test_views.log | sort -u
.../include/morph/core/../forms/forms.hpp:489:39: error: forwarding reference parameter 'action' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward,-warnings-as-errors]
.../include/morph/core/../forms/forms.hpp:489:57: error: forwarding reference parameter 'visitor' is never forwarded inside the function body [cppcoreguidelines-missing-std-forward,-warnings-as-errors]
From a non-tests/ TU, examples/forms/gui_qml/FormsController.cpp, same
revision, same database, same command:
Its own comment for that entry scopes the reasoning to test code — "these are dom["key"] on the line after REQUIRE(dom.contains("key")) … the bound is
established by the assertion the check cannot read" — which is a correct
statement about tests/ and says nothing about include/morph/. The file's
header likewise says "Checks suppressed inside tests/ only", which is what
the author intended and not what clang-tidy does.
The same applies to the nine examples/*/tests/.clang-tidy copies, which carry
the same entries.
I did not check whether clang-tidy has an option to apply the diagnostic
file's config rather than the main file's. I believe it does not (the config
is resolved once, from the TU path, before analysis), but I read no clang-tidy
source.
Not reproduced on the CI image, only locally on Arch Linux with clang-tidy
22.1.8.
This is not a claim that tests/.clang-tidy is wrong. Every entry in it is
argued and, for test code, convincing. The defect is the unstated reach.
tests/.clang-tidy's reach is narrowed so its suppressions cannot apply to include/morph/** (if clang-tidy offers a mechanism for that), or
it is written down — in tests/.clang-tidy's own header and wherever the
header gate is documented — that these thirteen checks are unreportable for
any header reached from a test TU, with the list of which ones.
Re-open if a gate is later built on tests/ TUs without that record.
Found while verifying #627's fixes in PR #631. Filed rather than folded in, per
AGENTS.md: it is about the check configuration's scope, not about any of the
directives that PR repairs.
Summary
tests/.clang-tidydisables thirteen checks, each with a documented reason abouttest idiom. But clang-tidy applies the configuration of the main translation
unit, not of the file a diagnostic lands in. So every one of those thirteen
suppressions also applies to
include/morph/**headers, whenever the header isreached from a TU under
tests/.That means a header finding's visibility depends on which TU happened to reach
it. The same finding in the same header is reported from an
examples/TU andsilently dropped from a
tests/TU.This matters now for two reasons:
gating on "all 60 [
verify_interface_header_sets] stubs plus every TU undertests/". Thetests/half of that gate cannot reportcppcoreguidelines-pro-bounds-avoid-unchecked-container-access— the checkthat is 250 of the census's 596 — in any header it reaches, nor
bugprone-unchecked-optional-access(4 of the census's flagged possibledefects), nor
readability-identifier-length(58). A gate built to thatrecipe would be green on findings it was built to catch.
control that reports success while measuring nothing — and it is invisible
from inside:
tests/.clang-tidyis a correct and well-argued file abouttests/, and nothing in it says it reaches further.Verification status: reproduced
Revision
0e3b8823(origin/master), clang-tidy 22.1.8,.clang-tidyunmodified, compile database configured exactly as
.github/workflows/ci.yml'sclang-tidy job configures it (
ci.yml:2191, every optional feature ON).The case is
include/morph/forms/forms.hpp:496, which #627 records as leakingtwo
cppcoreguidelines-pro-bounds-avoid-unchecked-container-accessfindings pasta wrapped
NOLINTNEXTLINE. It is insideforEachNamedMember, a template, so itneeds a TU that instantiates it.
From a
tests/TU that does instantiate it —tests/test_views.cpp, whose own comments say it "exercisesbuildViewSchema'sforEachNamedMemberwalk":Zero, across the whole run — not just at
:496. The check is off for the entireinclude closure.
Other checks from the same TU are unaffected, so the run was real:
From a non-
tests/TU,examples/forms/gui_qml/FormsController.cpp, samerevision, same database, same command:
Both findings present.
tests/.clang-tidycarriesInheritParentConfig: trueand this in itsChecks:list, among twelve others:Its own comment for that entry scopes the reasoning to test code — "these are
dom["key"]on the line afterREQUIRE(dom.contains("key"))… the bound isestablished by the assertion the check cannot read" — which is a correct
statement about
tests/and says nothing aboutinclude/morph/. The file'sheader likewise says "Checks suppressed inside
tests/only", which is whatthe author intended and not what clang-tidy does.
The same applies to the nine
examples/*/tests/.clang-tidycopies, which carrythe same entries.
What I did not verify
tests/-driven run. Establishing that means re-running the census twice —once over
tests/TUs only, once over the rest — and differencing. The censusitself was a full-tree sweep over 695 TUs, so its 596 is not affected; only
a gate built from a
tests/-TU subset would be.file's config rather than the main file's. I believe it does not (the config
is resolved once, from the TU path, before analysis), but I read no clang-tidy
source.
22.1.8.
tests/.clang-tidyis wrong. Every entry in it isargued and, for test code, convincing. The defect is the unstated reach.
What would change the verdict
Close this when one of:
a
tests/-TU's configuration — e.g. gating only on theverify_interface_header_setsstubs, which sit underbuild/and inherit theroot
.clang-tidy, plus non-tests/user TUs for the instantiation-dependentresidual; or
tests/.clang-tidy's reach is narrowed so its suppressions cannot apply toinclude/morph/**(if clang-tidy offers a mechanism for that), ortests/.clang-tidy's own header and wherever theheader gate is documented — that these thirteen checks are unreportable for
any header reached from a test TU, with the list of which ones.
Re-open if a gate is later built on
tests/TUs without that record.Related
forms.hpp:496's two findings couldnot be reproduced from the obvious
tests/TU, which is what surfaced it.unable to report), for a different structural reason.
Found while verifying #627's fixes in PR #631. Filed rather than folded in, per
AGENTS.md: it is about the check configuration's scope, not about any of the
directives that PR repairs.