Skip to content

clang-tidy 22 reports cppcoreguidelines-pro-bounds-avoid-unchecked-container-access on locale_format.hpp, which the repo's own config makes an error #626

Description

@Yaraslaut

Found while implementing #591. Filed rather than folded in: it is a
repository-wide tooling question, not part of that change.

What

clang-tidy 22.1.8 reports a finding on include/morph/render/locale_format.hpp
that this repository's own .clang-tidy asks for, and that nothing in the tree
suppresses. The header was otherwise untouched by any in-flight work when I
measured it.

Verification status

Reproduced, on master @ 0e3b8823, by running clang-tidy directly over a
one-line translation unit that includes the header. Not inferred from reading.

$ cat /tmp/tu.cpp
#include <morph/render/locale_format.hpp>

$ clang-tidy --version | head -3
LLVM (http://llvm.org/):
  LLVM version 22.1.8
  Optimized build.

$ clang-tidy --config-file=.clang-tidy /tmp/tu.cpp -- -std=c++23 -I include
include/morph/render/locale_format.hpp:457:29: error: possibly unsafe 'operator[]', consider bounds-safe alternatives [cppcoreguidelines-pro-bounds-avoid-unchecked-container-access,-warnings-as-errors]

Line 457 on that revision is the display loop in formatCanonicalNumber:

        grouped += wholePart[i];

cppcoreguidelines-* is in the Checks list and WarningsAsErrors is "*",
so this is an error by the repository's own configuration, not a check I
enabled.

One methodological note, because it changes how to reproduce this. The
finding only appears when the header's path matches HeaderFilterRegex
(include/morph/.*). Pointing clang-tidy at a copy of the header under some
other path reports nothing at all, silently — which is how I initially
convinced myself a different check was not firing when it was.

What I did not verify

  • Which clang-tidy version CI runs, and whether it reports this. This is the
    load-bearing unknown. The check
    cppcoreguidelines-pro-bounds-avoid-unchecked-container-access is recent; an
    older clang-tidy does not have it, which would explain why a green CI has been
    sitting on top of this. I did not read the workflow to find the pinned version
    and I did not run CI's toolchain locally.
  • Whether the rest of the tree has the same finding. I measured one header,
    because it is the one I was working in. A tree-wide sweep is exactly what
    would size this, and I am told a separate lane is already running one — this
    issue should be reconciled with that lane's result rather than duplicated by
    it.
  • Whether this is a real safety problem. i is bounded by the loop condition
    three lines above, so the access is in fact in range. This is a suppression /
    policy question, not a defect report.

Why it matters

Not because the indexing is wrong — it is not. It matters because the
repository has decided it wants clang-tidy as strict as possible (#580), and a
check that the configuration enables and that fires on first-party code is
either a finding to fix, a check to disable deliberately, or a suppression to
write with a reason. Which of the three it is has not been recorded anywhere,
and the difference only shows up when someone upgrades the compiler on the CI
image.

The existing code already knows about this check: the same header carries

        // i is bounded by the loop condition.
        // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-avoid-unchecked-container-access)

twice, in groupingIsWellPlaced and in normalizeLocaleNumber. So it fires in
CI at least sometimes, or did once — and formatCanonicalNumber's identical
pattern simply never got the same treatment.

Incidental note

PR #630 rewrites that loop for unrelated reasons (#591 needed the digits mapped
through a base rather than copied), and the rewrite happens to use a range-for
with a separate index counter, so the finding is gone on that branch. That
is a side effect of the rewrite, not a fix, and it says nothing about the rest
of the tree. This issue is about the policy and the sweep, not about that line.

What would change the verdict

  • Close as fixed when a tree-wide clang-tidy run at the version CI pins
    reports no
    cppcoreguidelines-pro-bounds-avoid-unchecked-container-access outside
    suppressions that state a reason.
  • Close as invalid if CI's pinned clang-tidy does not implement this check
    and the project decides not to move to a version that does — in which case the
    two existing NOLINTNEXTLINEs for it in this same header are dead weight and
    should go, which is a finding in itself.
  • Re-open / widen if the tree-wide sweep finds this in more than a handful
    of places, which would make it a configuration decision rather than a few
    annotations.

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

    area: ciSubsystem: ciarea: formsSubsystem: formsbugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions