Skip to content

HeaderFilterRegex excludes every examples/** header from clang-tidy: 49 findings from five of 737 TUs #664

Description

@Yaraslaut

What

The repository-root .clang-tidy carries

HeaderFilterRegex: "include/morph/.*"

clang-tidy reports diagnostics in the main file plus any header whose path
matches that regex, and discards the rest. So no finding in any header under
examples/** is ever reported, by any job, no matter which translation unit
reaches it.

This is the same shape as #481, #650, #651 and #656 -- a gate that reads code
and is believed to cover examples/, covering only part of it -- one level
down: those were about which translation units the job analyses, this is
about which headers it reports on once it has them.

It is not a small remainder. The ladder keeps model logic, DTOs and inline
presenter helpers in headers by design: examples/bank/include/bank/models/*
and examples/<rung>/include/<rung>/** are where a rung's code actually
lives, and every one of those files is silent today.

Measurement

Reproduced, on 7ab4c7a9 plus this branch's #656 commit (so the eleven
bank-GUI sources are already clean), clang-tidy 22.1.8, against the
clang-tidy job's own configure and its own -extra-arg pair. Five of the
eleven bank-GUI TUs, re-run with --header-filter='examples/.*' in place of
the configured include/morph/.*:

distinct findings in examples/**.hpp, from 5 of the 11 TUs: 49
--- per header ---
      8 examples/bank/include/bank/models/card_model.hpp
      6 examples/bank/include/bank/models/payment_model.hpp
      6 examples/bank/include/bank/models/loan_model.hpp
      5 examples/bank/include/bank/models/transaction_model.hpp
      5 examples/bank/include/bank/models/auth_model.hpp
      4 examples/bank/include/bank/models/payee_model.hpp
      4 examples/bank/include/bank/dto/payee_dto.hpp
      3 examples/bank/include/bank/models/customer_model.hpp
      3 examples/bank/include/bank/core/types.hpp
      3 examples/bank/gui/controllers/Format.hpp
      1 examples/bank/gui/controllers/../BankClient.hpp
      1 examples/bank/gui/BankClient.hpp
--- per check ---
     37 cert-dcl59-cpp,misc-anonymous-namespace-in-header
      4 readability-identifier-length
      2 cppcoreguidelines-special-member-functions
      2 cppcoreguidelines-pro-bounds-avoid-unchecked-container-access
      1 readability-use-anyofallof
      1 readability-math-missing-parentheses
      1 misc-const-correctness
      1 bugprone-incorrect-roundings

Real output, the first six:

examples/bank/gui/BankClient.hpp:20:7: error: class 'BankClient' defines a copy constructor and a copy assignment operator but does not define a destructor, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions,-warnings-as-errors]
examples/bank/gui/controllers/../BankClient.hpp:20:7: error: class 'BankClient' defines a copy constructor and a copy assignment operator but does not define a destructor, a move constructor or a move assignment operator [cppcoreguidelines-special-member-functions,-warnings-as-errors]
examples/bank/gui/controllers/Format.hpp:69:10: error: variable name 'ok' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]
examples/bank/gui/controllers/Format.hpp:76:38: error: casting (double + 0.5) to integer leads to incorrect rounding; consider using lround (#include <cmath>) instead [bugprone-incorrect-roundings,-warnings-as-errors]
examples/bank/gui/controllers/Format.hpp:76:38: error: '*' has higher precedence than '+'; add parentheses to explicitly specify the order of operations [readability-math-missing-parentheses,-warnings-as-errors]
examples/bank/include/bank/core/types.hpp:27:55: error: parameter name 'c' is too short, expected at least 3 characters [readability-identifier-length,-warnings-as-errors]

Two things the numbers do and do not say

  • 49 is a lower bound, and a small one. It comes from five bank TUs. The
    job's database holds 737 entries spanning thirteen example directories;
    every rung's own headers are in the same position and none of them was
    measured here.
  • The same-header-two-paths duplicate is real. BankClient.hpp appears
    twice, once as examples/bank/gui/BankClient.hpp and once as
    examples/bank/gui/controllers/../BankClient.hpp, because a header filter
    matches the spelling of the include path rather than the resolved file.
    That is a property of any wider regex too, worth knowing before one is
    written.
  • One of the findings looks like a real defect, not style. Filed
    separately as bank GUI: parseMinor casts an unbounded double to int64_t; 1e30 in any amount field is UB #663 (bugprone-incorrect-roundings on
    Format.hpp:76, and the unbounded double -> int64_t cast on the same
    line, which is reproduced UB). It has sat unreported for as long as this
    filter has been in place, which is the argument for the filter being the
    issue and not the one finding.

Verification status

  • Reproduced: the 49, the per-header and per-check split, on the revision
    and toolchain named above.
  • Reproduced: that widening the filter is what surfaces them -- the same
    five TUs under the configured include/morph/.* report zero findings in
    any examples/** header.
  • Inferred, not measured: the repository-wide total. Only five of 737
    database entries were re-run.
  • Not attempted: any fix. Nothing has been changed.

Why it is not simply "widen the regex"

Widening it to (include/morph|examples)/.* would make the clang-tidy job
report all of the above on the first PR that touches a changed line in one of
those headers, which is #656's situation repeated at a larger scale, and 37
of the 49 are one check (misc-anonymous-namespace-in-header) that wants a
decision about the ladder's header idiom rather than 37 edits. The sequencing
#646/#656 established applies: widen the filter in one change, clear what it
exposes in another, and do not gate the first on the second.

tests/.clang-tidy's reach note (#632, scripts/check_tidy_suppression_scope.sh)
is also in scope for whoever takes this: once examples/** headers are
reported, the per-rung examples/*/tests/.clang-tidy suppressions start
applying to them from every test TU, exactly as tests/.clang-tidy does for
include/morph/**.

What would change the verdict

Close when the filter reports on the ladder's own headers and the findings it
exposes are either fixed or recorded -- verified by re-running the command
above and pasting the output, not by a green CI run, since a green
clang-tidy-diff leg proves only that those lines were not touched.

Close as invalid if the narrow filter turns out to be a deliberate,
recorded decision somewhere this search missed; nothing in .clang-tidy,
tests/.clang-tidy or ci.yml argues for it.

Context

Found while clearing #656. HeaderFilterRegex is repository-wide, so this is
not a bank-GUI issue and was not folded into that change.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions