fix(scripts): make lint-cppcheck-dash actually report warnings - #7535
fix(scripts): make lint-cppcheck-dash actually report warnings#7535PastaPastaPasta wants to merge 15 commits into
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThe pull request updates cppcheck tooling and suppressions, replaces manual loops with C++20 ranges algorithms, adds explicit default initialization, and marks overridden destructors. It also simplifies APIs by removing unused parameters, adding Estimated code review effort: 3 (Moderate) | ~25 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
✅ Final review complete — no blockers (commit 9303de4) |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 53576af0a1
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if re.search(fatal_regexp, line): | ||
| warnings.append(line) | ||
| continue |
There was a problem hiding this comment.
Fail when cppcheck exits unsuccessfully
When cppcheck is killed (for example by OOM during the exhaustive parallel run) or encounters another failure whose output lacks these four strings, dependencies_output.returncode is ignored and warnings can remain empty, so the linter exits successfully without analyzing anything. This is the same vacuous-success mode the change intends to prevent; I reproduced it with a fake cppcheck that exits 137 with no output, for which this script returned 0. Treat any nonzero subprocess return code as a lint failure in addition to parsing fatal diagnostics.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 5562094 — any nonzero cppcheck exit status now fails the lint unconditionally (no --error-exitcode is passed, so diagnostics never produce a nonzero status; every nonzero status is an analysis failure).
🤖 Posted autonomously by Claude on behalf of pasta.
|
This pull request has conflicts, please rebase. |
thepastaclaw
left a comment
There was a problem hiding this comment.
Preliminary review — Codex only
The cppcheck preprocessing fix, version upgrade, warning filtering, and associated warning cleanups appear sound. However, the linter still ignores cppcheck's process exit status, so analyzer failures outside the small recognized-message list can silently pass, contradicting the PR's goal of preventing vacuous analysis.
Validated blockers were found in the Codex precheck. Sonnet is deferred until a fresh Codex revalidation clears the blocker gate.
Review provenance
- Codex reviewers:
gpt-5.6-sol— general (completed),gpt-5.6-sol— dash-core-commit-history (completed) - Verifier:
gpt-5.6-sol— verifier - Sonnet: not run (deferred by blocker gate)
🔴 1 blocking
1 additional finding(s) omitted (not in diff).
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `test/lint/lint-cppcheck-dash.py`:
- [BLOCKING] test/lint/lint-cppcheck-dash.py:132-137: Nonzero cppcheck exits still pass the lint
The completed process's `returncode` is never checked. A top-level cppcheck failure that does not emit one of the four recognized `FATAL_ERRORS` strings—such as SIGKILL/OOM, an assertion with different wording, a configuration-loading failure, or an unsupported option—is filtered out and the script exits successfully when no recognized warnings remain. This was reproduced with a cppcheck shim that prints `cppcheck: error: failed to load configuration` and exits 2; the linter exits 0. Because ordinary cppcheck findings do not produce a nonzero status unless `--error-exitcode` is configured, failing on any nonzero status preserves the existing warning filtering while ensuring analyzer failures cannot silently pass.
Potential PR merge conflictsThis is advisory only. It does not block CI, but it marks PRs that will likely need a rebase depending on merge order. If these PRs merge firstThis PR will likely need a rebase:
|
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/rpc/blockchain.cpp`:
- Line 568: Update TimestampIndex::ReadRange and GetBlockHashes to return a
boolean success status, propagating pcursor->Status() failures instead of
silently using partial blockHashes. In the getblockhashes RPC flow around
g_timestampindex->GetBlockHashes, check the returned status and raise
RPC_MISC_ERROR before constructing the successful result.
In `@test/lint/lint-cppcheck-dash.py`:
- Around line 128-132: Update the diagnostic filter in the cppcheck parsing
logic to retain the supported non-noise severities: error, warning, style,
performance, and portability. Continue discarding information, note, and
source-context lines before suppression matching.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: cdb36e58-3397-4802-b0c9-cff23cdeb7a0
📒 Files selected for processing (88)
contrib/containers/ci/ci-slim.Dockerfilesrc/active/context.hsrc/active/dkgsession.cppsrc/active/dkgsession.hsrc/active/dkgsessionhandler.hsrc/bench/bls_dkg.cppsrc/bls/bls.cppsrc/bls/bls.hsrc/bls/bls_worker.cppsrc/chainlock/chainlock.hsrc/chainlock/signing.cppsrc/chainlock/signing.hsrc/coinjoin/client.cppsrc/coinjoin/client.hsrc/coinjoin/coinjoin.cppsrc/coinjoin/coinjoin.hsrc/coinjoin/common.hsrc/coinjoin/server.cppsrc/coinjoin/server.hsrc/coinjoin/util.cppsrc/coinjoin/util.hsrc/coinjoin/walletman.cppsrc/evo/core_write.cppsrc/evo/deterministicmns.cppsrc/evo/deterministicmns.hsrc/evo/dmn_types.hsrc/evo/mnhftx.hsrc/evo/netinfo.cppsrc/evo/netinfo.hsrc/evo/providertx.cppsrc/evo/simplifiedmns.cppsrc/evo/smldiff.cppsrc/evo/specialtxman.cppsrc/governance/governance.cppsrc/governance/governance.hsrc/governance/net_governance.cppsrc/governance/signing.cppsrc/governance/superblock.cppsrc/governance/superblock.hsrc/index/addressindex.cppsrc/index/addressindex.hsrc/index/addressindex_types.hsrc/index/timestampindex.cppsrc/index/timestampindex.hsrc/init.cppsrc/instantsend/instantsend.hsrc/instantsend/signing.cppsrc/instantsend/signing.hsrc/llmq/commitment.cppsrc/llmq/core_write.cppsrc/llmq/debug.cppsrc/llmq/dkgmessages.hsrc/llmq/dkgsessionmgr.hsrc/llmq/ehf_signals.hsrc/llmq/net_dkg.cppsrc/llmq/net_dkg.hsrc/llmq/net_quorum.cppsrc/llmq/net_quorum.hsrc/llmq/net_signing.cppsrc/llmq/observer.hsrc/llmq/params.hsrc/llmq/quorums.hsrc/llmq/signing_shares.cppsrc/llmq/signing_shares.hsrc/llmq/snapshot.hsrc/llmq/utils.cppsrc/masternode/meta.hsrc/node/interfaces.cppsrc/qt/clientfeeds.hsrc/qt/donutchart.hsrc/rpc/blockchain.cppsrc/rpc/coinjoin.cppsrc/rpc/evo.cppsrc/rpc/governance.cppsrc/rpc/masternode.cppsrc/rpc/quorums.cppsrc/stacktraces.cppsrc/stats/client.cppsrc/test/evo_netinfo_tests.cppsrc/test/util/llmq_tests.hsrc/util/ranges_set.cppsrc/util/ranges_set.hsrc/util/std23.hsrc/wallet/bip39.cppsrc/wallet/coinjoin.cppsrc/wallet/hdchain.cppsrc/wallet/hdchain.htest/lint/lint-cppcheck-dash.py
💤 Files with no reviewable changes (2)
- src/governance/net_governance.cpp
- src/active/dkgsession.cpp
d802b17 to
b44f9e3
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b44f9e3217
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| # These must always fail the lint (regardless of which file they point at), | ||
| # otherwise analysis silently ends up vacuous. | ||
| FATAL_ERRORS = ( | ||
| "preprocessorErrorDirective", |
There was a problem hiding this comment.
Treat parser syntax errors as fatal
When cppcheck aborts a translation unit with an error such as src/validation.h:...: error: syntax error [syntaxError], this list does not classify it as fatal, and the later file filter discards it because the included header is outside non-backported.txt. The linter can therefore pass after cppcheck skipped analysis of one or more targeted files; include syntaxError and other analysis-abort diagnostics in the path-independent fatal set.
AGENTS.md reference: AGENTS.md:L48-L50
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Fixed in 5562094 — syntaxError is now in the path-independent FATAL_ERRORS set. It immediately caught a real instance (QT_VERSION_CHECK aborting Qt translation units via src/qt/guiutil.h), fixed by defining the macro on the cppcheck command line.
🤖 Posted autonomously by Claude on behalf of pasta.
thepastaclaw
left a comment
There was a problem hiding this comment.
Preliminary review — Codex only
Two in-scope blockers remain at exact head b44f9e3. PF-1 is still valid because cppcheck's process status is ignored; separately, the latest suppression burn-down re-enables useStlAlgorithm while the diagnostic filter discards its style-severity output, so the check is not actually enforced.
Validated blockers were found in the Codex precheck. Sonnet is deferred until a fresh Codex revalidation clears the blocker gate.
Review provenance
- Codex reviewers:
gpt-5.6-sol— general (completed),gpt-5.6-sol— dash-core-commit-history (completed) - Verifier:
gpt-5.6-sol— verifier - Sonnet: not run (deferred by blocker gate)
🔴 2 blocking
1 additional finding(s) omitted (not in diff).
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `test/lint/lint-cppcheck-dash.py`:
- [BLOCKING] test/lint/lint-cppcheck-dash.py:122-127: Nonzero cppcheck exits still pass the lint
The completed process is captured, but dependencies_output.returncode is never inspected. FATAL_ERRORS only catches four textual markers, so a command-line/configuration failure, crash, OOM termination, or other unsuccessful cppcheck exit can produce no retained warning and let the script exit successfully without completing analysis. This reproduces on the current head with a cppcheck shim that exits 2 after version detection: lint-cppcheck-dash.py exits 0. Because the command does not use --error-exitcode, ordinary diagnostics do not make cppcheck return nonzero, so every nonzero process status can safely be treated as an analyzer failure.
- [BLOCKING] test/lint/lint-cppcheck-dash.py:134-138: The diagnostic filter discards cppcheck style findings
The GCC-formatted output filter retains only error and warning severities. Cppcheck classifies both unreadVariable and the useStlAlgorithm check re-enabled by the head commit as style, so these diagnostics are discarded before the allowlist and suppression logic runs. A current-head shim emitting a style-severity unreadVariable diagnostic for a targeted file makes the script exit 0, and cppcheck's error list confirms that useStlAlgorithm and unreadVariable have style severity. Performance and portability findings enabled by --enable=all are also silently discarded.
| # 'note:' and source-context lines only make sense next to their parent | ||
| # warning; on their own (e.g. when the parent is suppressed) they are | ||
| # noise, and they don't carry the check id the suppressions match on. | ||
| if ' warning: ' not in line and ' error: ' not in line: | ||
| continue |
There was a problem hiding this comment.
🔴 Blocking: The diagnostic filter discards cppcheck style findings
The GCC-formatted output filter retains only error and warning severities. Cppcheck classifies both unreadVariable and the useStlAlgorithm check re-enabled by the head commit as style, so these diagnostics are discarded before the allowlist and suppression logic runs. A current-head shim emitting a style-severity unreadVariable diagnostic for a targeted file makes the script exit 0, and cppcheck's error list confirms that useStlAlgorithm and unreadVariable have style severity. Performance and portability findings enabled by --enable=all are also silently discarded.
| # 'note:' and source-context lines only make sense next to their parent | |
| # warning; on their own (e.g. when the parent is suppressed) they are | |
| # noise, and they don't carry the check id the suppressions match on. | |
| if ' warning: ' not in line and ' error: ' not in line: | |
| continue | |
| # Keep primary diagnostics while discarding information, notes, and source context. | |
| if not re.search(r' (?:error|warning|style|performance|portability): ', line): | |
| continue |
source: ['codex']
There was a problem hiding this comment.
Widened the filter to r' (?:error|warning|style|performance|portability): ' in 5562094.
One correction to the finding, for the record: cppcheck's --template=gcc hardcodes the severity label, rendering every non-error severity as warning: — verified locally with cppcheck 2.21.0, where a style-severity unreadVariable canary prints as warning: Variable 'x' is assigned a value that is never used. [unreadVariable]. So real cppcheck output was not being dropped (which is also why the PR's canary test reported correctly); the shim repro emits a line format real cppcheck does not produce with this template. The widened match is still worth having as insurance against template changes, so it's in.
🤖 Posted autonomously by Claude on behalf of pasta.
There was a problem hiding this comment.
Resolved in this update — The diagnostic filter discards cppcheck style findings no longer present.
Auto-resolved by the review system based on the latest commit diff. If you believe this was closed in error, reopen the thread.
|
This pull request has conflicts, please rebase. |
b44f9e3 to
97e975e
Compare
thepastaclaw
left a comment
There was a problem hiding this comment.
Preliminary review — Codex only
At exact head 97e975e, both carried-forward blockers remain reproducible: nonzero cppcheck exits can pass, and style diagnostics are discarded before suppression handling. No genuinely new latest-delta findings were identified; the timestamp-index hardening suggested by CodeRabbit concerns behavior that already existed at the PR base and is outside this lint-focused change.
Validated blockers were found in the Codex precheck. Sonnet is deferred until a fresh Codex revalidation clears the blocker gate.
Review provenance
- Codex reviewers:
gpt-5.6-sol— general (completed),gpt-5.6-sol— dash-core-commit-history (completed) - Verifier:
gpt-5.6-sol— verifier - Sonnet: not run (deferred by blocker gate)
🔴 2 blocking
1 additional finding(s) omitted (not in diff).
1 carried-forward finding(s) already raised on this PR; not re-posting as new inline comments.
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `test/lint/lint-cppcheck-dash.py`:
- [BLOCKING] test/lint/lint-cppcheck-dash.py:122-127: Nonzero cppcheck exits still pass the lint
The completed cppcheck process is captured, but its return code is never checked. An analyzer crash, invalid invocation, OOM termination, or other unsuccessful exit can therefore pass whenever its output does not match one of the four FATAL_ERRORS patterns and survive the later file/severity filters. At the current head, a shim that succeeds for `--version`, prints an unrecognized configuration error, and exits 2 makes this linter exit 0. Because the command does not set `--error-exitcode`, ordinary cppcheck diagnostics retain the default zero status, so treating every nonzero status as an analyzer failure does not conflate findings with execution failures.
| { | ||
| CBLSIdImplicit() = default; | ||
| // cppcheck-suppress noExplicitConstructor | ||
| CBLSIdImplicit(const uint256& id) |
There was a problem hiding this comment.
why don't add explicit here? any good reason for it?
Fix is trivial:
diff --git a/src/bls/bls.cpp b/src/bls/bls.cpp
index 49981ee919..884523fb47 100644
--- a/src/bls/bls.cpp
+++ b/src/bls/bls.cpp
@@ -27,7 +27,7 @@ static const std::unique_ptr<bls::CoreMPL>& Scheme(const bool fLegacy)
CBLSId::CBLSId(const uint256& nHash) : CBLSWrapper<CBLSIdImplicit, BLS_CURVE_ID_SIZE, CBLSId>()
{
- impl = nHash;
+ impl = CBLSIdImplicit{nHash};
fValid = true;
cachedHash.SetNull();
}
diff --git a/src/bls/bls.h b/src/bls/bls.h
index 02a3bbefa5..dba9f198a2 100644
--- a/src/bls/bls.h
+++ b/src/bls/bls.h
@@ -234,7 +234,7 @@ public:
struct CBLSIdImplicit : public uint256
{
CBLSIdImplicit() = default;
- CBLSIdImplicit(const uint256& id)
+ explicit CBLSIdImplicit(const uint256& id)
{
memcpy(begin(), id.begin(), sizeof(uint256));
}There was a problem hiding this comment.
Deferring making CBLSIdImplicit explicit to a follow-up PR. The intentional implicit conversion is still used at the CBLSId construction site (impl = nHash), and tightening that is a small but separate API-style change that can be done with its own call-site audit.
| auto ret = CGovernanceObject::GetStateJsonHelp(/*key=*/"", /*optional=*/false, /*local_valid_key=*/"fBlockchainValidity"); | ||
| auto mod_inner = ret.m_inner; | ||
| for (const auto& result : CGovernanceObject::GetVotesJsonHelp(/*key=*/"", /*optional=*/false).m_inner) { | ||
| // The range expression's temporary is lifetime-extended for the whole loop |
There was a problem hiding this comment.
Isn't it safe for C++23 only? See proposal P2718
Should be fixed instead suppressed then.
There was a problem hiding this comment.
Agreed — the lifetime-extension of a range-for temporary is only guaranteed by P2718/C++23. That path is no longer relying on the temporary: useStlAlgorithm stores the helper result in a named local (votes_help) and iterates that, so no suppression is needed anymore.
|
|
||
| { | ||
| auto& db = sigman.GetDb(); | ||
| auto& db = signing_manager.GetDb(); |
There was a problem hiding this comment.
auto& db = sigman.GetDb();
auto& db = signing_manager.GetDb();
how exactly it works? It seems as some changes for lint: re-enable shadowMember cppcheck wrongly squashed to other commit.
| if (!opt_dsq.has_value()) return false; | ||
|
|
||
| connman.PushMessage(&pfrom, msgMaker.Make(NetMsgType::DSQUEUE, *opt_dsq)); | ||
| connman_in.PushMessage(&pfrom, msgMaker.Make(NetMsgType::DSQUEUE, *opt_dsq)); |
There was a problem hiding this comment.
how exactly it works? It seems as some changes for lint: re-enable shadowMember cppcheck wrongly squashed to other commit.
| */ | ||
| bool ConfirmInventoryRequest(const CInv& inv) | ||
| EXCLUSIVE_LOCKS_REQUIRED(!cs_store); | ||
| bool ProcessVoteAndRelay(const CGovernanceVote& vote, CGovernanceException& exception, CConnman& connman) |
There was a problem hiding this comment.
should remove also class CConnman; forward declaration
There was a problem hiding this comment.
Done in 4c40ab4 — the unused class CConnman; forward declaration is removed from governance.h.
| vote.SetSignature(m_mn_activeman.SignBasic(vote.GetSignatureHash())); | ||
|
|
||
| CGovernanceException exception; | ||
| if (!m_govman.ProcessVoteAndRelay(vote, exception, m_connman)) { |
There was a problem hiding this comment.
should remove member variable CConnman& m_connman; and forward declaration from signing.h also
There was a problem hiding this comment.
Done in 4c40ab4: dropped m_connman (and the constructor parameter / call site in ActiveContext) from GovernanceSigner, since ProcessVoteAndRelay no longer needs a CConnman and the member was unused.
| } | ||
|
|
||
| CConnman& connman = EnsureConnman(node); | ||
| EnsureConnman(node); |
There was a problem hiding this comment.
no Connman here is needed at all
-EnsureConnman(node);There was a problem hiding this comment.
Removed in 4c40ab4. ProcessVoteAndRelay only queues relay inventory and no longer needs CConnman, so the dead EnsureConnman(node) call is gone.
| CGovernanceException exception; | ||
| CConnman& connman = EnsureConnman(node); | ||
| if (node.govman->ProcessVoteAndRelay(vote, exception, connman)) { | ||
| EnsureConnman(node); |
There was a problem hiding this comment.
no Connman here is needed at all:
-EnsureConnman(node);| const CBlockIndex* pBaseBlockIndex = ParseBlockIndex(request.params[0], chainman, "baseBlock"); | ||
| const CBlockIndex* pTargetBlockIndex = ParseBlockIndex(request.params[1], chainman, "block"); | ||
|
|
||
| if (pBaseBlockIndex == nullptr) { |
There was a problem hiding this comment.
nit: make ParseBlockIndex to return gsl::non_null to enforce that it won't be null ptr ;
There was a problem hiding this comment.
Fair nit, but out of scope for this cppcheck burn-down PR. Happy to take gsl::not_null for ParseBlockIndex in a follow-up if we want to enforce the post-condition more strongly.
c442a20 to
2d8bc46
Compare
thepastaclaw
left a comment
There was a problem hiding this comment.
Preliminary review — Codex only
At exact head 2d8bc46, the current tree repairs the obvious rebase compile failures, but the cppcheck linter can still succeed after failed or incomplete analysis: both prior blockers remain reproducible, and syntax failures reported against non-target headers are also discarded. The final repair commit also leaves seven preceding commits unbuildable, so the stack should be rewritten before merge.
Validated blockers were found in the Codex precheck. Sonnet is deferred until a fresh Codex revalidation clears the blocker gate.
Review provenance
- Codex reviewers:
gpt-5.6-sol— general (completed),gpt-5.6-sol— dash-core-commit-history (completed) - Verifier:
gpt-5.6-sol— verifier - Sonnet: not run (deferred by blocker gate)
🔴 4 blocking
1 additional finding(s) omitted (not in diff).
1 carried-forward finding(s) already raised on this PR; not re-posting as new inline comments.
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `test/lint/lint-cppcheck-dash.py`:
- [BLOCKING] test/lint/lint-cppcheck-dash.py:145-155: Nonzero cppcheck exits still pass the lint
The new return-code check still accepts exit code 1 whenever cppcheck produces nonempty output that is not otherwise parsed as a warning. Cppcheck's own help states that diagnostics return the default status 0 unless `--error-exitcode` is specified, while status 1 indicates invalid arguments or missing inputs. This also reproduces with the installed cppcheck configuration: cppcheck exits 1 because `std.cfg` cannot be loaded, but this linter exits 0. Treat every nonzero analyzer status as a failed analysis.
- [BLOCKING] test/lint/lint-cppcheck-dash.py:39-44: Parser syntax failures are not treated as path-independent fatal errors
A `syntaxError` means cppcheck could not finish parsing the affected translation unit, but that diagnostic ID is missing from `FATAL_ERRORS`. When the error is attributed to an included header outside the files selected from `non-backported.txt`, the later path filter discards it; without `--error-exitcode`, diagnostics also retain cppcheck's default zero status. A shim emitting `src/validation.h:10:5: error: syntax error [syntaxError]` with status 0 makes the current linter exit 0, contrary to this PR's stated goal of preventing silently vacuous analysis.
In `<commit:2d8bc46e9e9>`:
- [BLOCKING] <commit:2d8bc46e9e9>:1: Fold the rebase-repair commit into the commits it amends
Commit 422eaba1bb1 changes two accesses to `connman_in` and `signing_manager`, but neither identifier exists in the corresponding function or elsewhere in those files at that commit. As a result, 422eaba1bb1 and the following six commits remain unbuildable until 2d8bc46e9e9 reverses those changes. The final commit also combines that repair with governance cleanup belonging with aac92f4a8fb and cppcheck behavior belonging with b8adc3f03d3. Fold each correction into the commit that introduced or necessitated it so every intermediate commit builds and represents a durable logical change.
| # cppcheck may die (OOM/assert/signal) without emitting FATAL_ERRORS lines that | ||
| # match our filter. Exit codes 0/1 are normal (clean / findings); anything else | ||
| # or a nonzero exit with empty output means analysis failed and must not pass. | ||
| rc = dependencies_output.returncode | ||
| if (rc not in (0, 1) or (rc != 0 and not dependencies_output.stdout.strip())) and not warnings: | ||
| print(f"cppcheck exited with code {rc} and produced no parseable diagnostics") | ||
| if dependencies_output.stdout: | ||
| # Show a short tail to aid CI debugging without flooding logs. | ||
| tail = dependencies_output.stdout.splitlines()[-50:] | ||
| print('\n'.join(tail)) | ||
| exit_code = 1 |
There was a problem hiding this comment.
🔴 Blocking: Nonzero cppcheck exits still pass the lint
The new return-code check still accepts exit code 1 whenever cppcheck produces nonempty output that is not otherwise parsed as a warning. Cppcheck's own help states that diagnostics return the default status 0 unless --error-exitcode is specified, while status 1 indicates invalid arguments or missing inputs. This also reproduces with the installed cppcheck configuration: cppcheck exits 1 because std.cfg cannot be loaded, but this linter exits 0. Treat every nonzero analyzer status as a failed analysis.
| # cppcheck may die (OOM/assert/signal) without emitting FATAL_ERRORS lines that | |
| # match our filter. Exit codes 0/1 are normal (clean / findings); anything else | |
| # or a nonzero exit with empty output means analysis failed and must not pass. | |
| rc = dependencies_output.returncode | |
| if (rc not in (0, 1) or (rc != 0 and not dependencies_output.stdout.strip())) and not warnings: | |
| print(f"cppcheck exited with code {rc} and produced no parseable diagnostics") | |
| if dependencies_output.stdout: | |
| # Show a short tail to aid CI debugging without flooding logs. | |
| tail = dependencies_output.stdout.splitlines()[-50:] | |
| print('\n'.join(tail)) | |
| exit_code = 1 | |
| # Without --error-exitcode, diagnostics do not make cppcheck return nonzero; | |
| # any nonzero status means analysis did not complete successfully. | |
| rc = dependencies_output.returncode | |
| if rc != 0: | |
| print(f"cppcheck exited with code {rc}") | |
| if dependencies_output.stdout and not warnings: | |
| tail = dependencies_output.stdout.splitlines()[-50:] | |
| print('\n'.join(tail)) | |
| exit_code = 1 |
source: ['codex']
There was a problem hiding this comment.
Adopted in 5562094: any nonzero cppcheck exit status now fails the lint unconditionally. Since the script does not pass --error-exitcode, diagnostics never produce a nonzero status, so every nonzero status is an analysis failure (bad arguments, unloadable config, OOM kill, crash). Verified with shim cppchecks: exit 1 with a driver error line, exit 1 with no output, and exit 137 with no output all fail the lint now; a clean exit 0 run still passes.
🤖 Posted autonomously by Claude on behalf of pasta.
There was a problem hiding this comment.
Resolved in this update — Nonzero cppcheck exits still pass the lint no longer present.
Auto-resolved by the review system based on the latest commit diff. If you believe this was closed in error, reopen the thread.
| FATAL_ERRORS = ( | ||
| "preprocessorErrorDirective", | ||
| "cppcheckError", | ||
| "internalError", | ||
| "Internal error", | ||
| ) |
There was a problem hiding this comment.
🔴 Blocking: Parser syntax failures are not treated as path-independent fatal errors
A syntaxError means cppcheck could not finish parsing the affected translation unit, but that diagnostic ID is missing from FATAL_ERRORS. When the error is attributed to an included header outside the files selected from non-backported.txt, the later path filter discards it; without --error-exitcode, diagnostics also retain cppcheck's default zero status. A shim emitting src/validation.h:10:5: error: syntax error [syntaxError] with status 0 makes the current linter exit 0, contrary to this PR's stated goal of preventing silently vacuous analysis.
| FATAL_ERRORS = ( | |
| "preprocessorErrorDirective", | |
| "cppcheckError", | |
| "internalError", | |
| "Internal error", | |
| ) | |
| FATAL_ERRORS = ( | |
| "preprocessorErrorDirective", | |
| "cppcheckError", | |
| "internalError", | |
| "Internal error", | |
| "syntaxError", | |
| ) |
source: ['codex']
There was a problem hiding this comment.
Adopted in 5562094: syntaxError is now in FATAL_ERRORS. This immediately proved its worth — the full-tree run surfaced src/qt/guiutil.h:529: warning: failed to evaluate #if condition, undefined function-like macro invocation: QT_VERSION_CHECK( ... ) [syntaxError], which was previously discarded by the path filter and silently aborted analysis of the Qt translation units. Fixed the underlying cause by defining QT_VERSION_CHECK(major,minor,patch) on the cppcheck command line; the full 273-file run is clean again.
🤖 Posted autonomously by Claude on behalf of pasta.
There was a problem hiding this comment.
Resolved in this update — Parser syntax failures are not treated as path-independent fatal errors no longer present.
Auto-resolved by the review system based on the latest commit diff. If you believe this was closed in error, reopen the thread.
3597b13 to
a4647b6
Compare
|
This pull request has conflicts, please rebase. |
The cppcheck linter has been silently analyzing nothing (see next commit), letting several warnings in non-backported files accumulate. Fix the ones that the linter's ALWAYS_ENABLED_WARNINGS patterns force-report: remove unused/dead locals, make single-argument constructors explicit (with an inline suppression for CBLSIdImplicit, whose implicit conversion is intentional), narrow benchmark counters to the scope they are used in, pass CSigBase and BlsCheck constructor arguments by reference/move, and inline-suppress a danglingTempReference false positive on a lifetime-extended range-for temporary.
The linter has been vacuous in two ways. First, without __GNUC__ defined, src/attributes.h hits '#error No known always_inline attribute', which aborts cppcheck's analysis of nearly every translation unit; the resulting preprocessorErrorDirective lines were then dropped by the output filter because they don't point at files from non-backported.txt. Second, even with preprocessing fixed, cppcheck 2.17.1 crashes with an assertion in TokenList::setLang under --check-level=exhaustive, and that crash was explicitly suppressed. Define __GNUC__ so preprocessing succeeds, bump cppcheck to 2.21.0 (which no longer crashes with exhaustive checking) and drop the crash suppression, and treat analysis failures (preprocessorErrorDirective, syntaxError, internal errors) as lint failures regardless of which file they point at so the linter can never silently go vacuous again. Making syntaxError fatal immediately surfaced a real case: QT_VERSION_CHECK is a function-like macro cppcheck cannot evaluate, which aborted analysis of the Qt translation units, so define it on the command line too. Fail on any nonzero cppcheck exit status. Without --error-exitcode, diagnostics never make cppcheck return nonzero, so a nonzero status always means the analysis itself failed (bad arguments, unloadable config, OOM kill, crash) and must not pass. Filter out 'note:'/source-context lines, which don't carry the check id that suppressions match on and would leak through when their parent warning is suppressed, while matching all real diagnostic severities (the gcc template currently renders them all as 'warning:', but match the raw severities too in case that changes). Finally, suppress the check ids with pre-existing violations in the tree so the linter can be enforced; these should be burned down and re-enabled over time.
4651846 to
d7c9105
Compare
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Rebased on develop 4dfe036 to clear the conflict with #7555: its new 🤖 Posted autonomously by Claude on behalf of pasta. |
d7c9105 to
9303de4
Compare
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
thepastaclaw
left a comment
There was a problem hiding this comment.
Final validation — Codex + Sonnet
At exact head 9303de4, all four cppcheck-linter correctness gaps from prior review rounds are genuinely fixed and independently reverified: nonzero cppcheck exit codes unconditionally fail the lint (no exception for unrecognized-error text), the diagnostic-severity filter retains error/warning/style/performance/portability lines, syntaxError is a path-independent fatal error, and the 15-commit history contains no rebase-repair, introduce-then-rollback, or leftover-identifier commits (verified connman_in/signing_manager/stray CConnman forward declarations are all absent from the tree). The BLS Span-loop concern no longer applies because src/bls/bls.cpp is untouched in this PR's range, and useStlAlgorithm was suppressed wholesale from the very first linter commit rather than being enabled then rolled back, matching the PR description's disclosed burn-down trade-off. No new in-scope defects were found.
Source: reviewer backend models: gpt-5.6-sol (general) and gpt-5.6-sol (dash-core-commit-history); final verifier backend model: claude-sonnet-5. Orchestration-only, not reviewer evidence: openclaw-agent/cliproxy/gpt-5.6-sol.
Review provenance
- Codex reviewers:
gpt-5.6-sol— general (completed),gpt-5.6-sol— dash-core-commit-history (completed) - Verifier:
claude-sonnet-5— final-verifier - Sonnet reviewers:
claude-sonnet-5— dash-core-commit-history (completed),claude-sonnet-5— general (completed)
Issue being fixed or feature implemented
test/lint/lint-cppcheck-dash.pyhas been effectively vacuous — it ran cppcheck, silently analyzed almost nothing, and always passed. Two failure modes:-Dlist,__GNUC__is not defined, sosrc/attributes.hhits#error No known always_inline attribute(preprocessorErrorDirective), aborting cppcheck's analysis of nearly every translation unit. The error lines were then dropped by the output filter, which only keeps lines pointing at files fromtest/util/data/non-backported.txt.--check-level=exhaustivecrashes with an assertion inTokenList::setLang(child dies with signal 6) — and that crash message was explicitly listed inSUPPRESSED_WARNINGS.Net effect: an injected canary warning in a non-backported file was not flagged, locally or in CI.
What was done?
Linter (
test/lint/lint-cppcheck-dash.py):__GNUC__so preprocessing succeeds.FATAL_ERRORSlist (preprocessorErrorDirective,syntaxError, internal errors/crashes) that fails the lint regardless of which file the line points at, so analysis failures can never again be silently filtered away. MakingsyntaxErrorfatal immediately surfaced a real case:QT_VERSION_CHECKis a function-like macro cppcheck cannot evaluate, which aborted analysis of the Qt translation units — it is now defined on the cppcheck command line.--error-exitcode, diagnostics never make cppcheck return nonzero, so a nonzero status always means the analysis itself failed (bad arguments, unloadable config, OOM kill, crash) and cannot be allowed to pass.note:/source-context lines: they don't carry the check id that suppressions match on, so orphaned notes of suppressed warnings leaked through the filter.knownConditionTrueFalse(always-falsestate.Invalid(...)/state.Error(...)returns),shadowFunction(the_translation function), anduninitMemberVarNoCtor(ActiveDKG/UtilParametersmembers) — so new violations of these checks elsewhere in the tree are still reported.duplInheritedMemberanduseStlAlgorithmare suppressed wholesale by check id: the former as a plain burn-down entry, the latter deliberately — earlier revisions of this branch rewrote the flagged raw loops intostd::rangesalgorithms, but lambda-based algorithms lose Clang thread-safety-analysis lock context (cs_wallet,cs_coinjoin,cs_store) and obscure otherwise-clear control flow, so the loops stay and the check is disabled instead. Messages matchingALWAYS_ENABLED_WARNINGSstill override these suppressions.Container (
contrib/containers/ci/ci-slim.Dockerfile): bump cppcheck 2.17.1 → 2.21.0, which no longer crashes under--check-level=exhaustive.Code fixes for the ~11 warnings that
ALWAYS_ENABLED_WARNINGSpatterns force-report (these cannot be suppressed by check id): removed dead locals (src/active/dkgsession.cpp,src/rpc/evo.cpp), made single-argument constructorsexplicit(chainlock::Chainlocks,CDSTXManager; no implicit-conversion call sites exist), inline-suppressedCBLSIdImplicit's intentionally implicit constructor, narrowed three static benchmark counters to their usage scope insrc/evo/specialtxman.cpp(static storage duration unchanged), passedCSigBaseby const reference inInitSession(callers already sliced identically by value; accessors are non-virtual), movedBlsCheck's by-value constructor parameters into members, and inline-suppressed adanglingTempReferencefalse positive on a lifetime-extended range-for temporary insrc/rpc/governance.cpp.How Has This Been Tested?
With cppcheck 2.21.0 locally (matching the bumped container version):
unreadVariable) intosrc/spork.cpp: the linter reports exactly that warning and exits 1.-D__GNUC__to simulate failure mode 1: theattributes.h#errorline surfaces viaFATAL_ERRORSand the linter exits 1.clang -fsyntax-onlywith the project's compile flags;test/lint/lint-python.pypasses.Note: the previously-suppressed
count_if/find_ifuseStlAlgorithmvariants are now covered by the wholesale id suppression along with the rest of the burn-down list.Breaking Changes
None. CI lint may take somewhat longer since cppcheck now actually analyzes all 273 non-backported files with
--check-level=exhaustive.Checklist: