AI review of 2026-11-11_08-08-44-63dda398dfd0-results.txt PR: #9016 https://github.com/cppcheck-opensource/cppcheck/pull/9016 Tested: 63dda398dfd08762f9210c337664fd18f8765203 Merge base: 4b66976df1dea47746a82c7bee12be7a322305d1 Reviewed: 2026-11-13 23:13:00 UTC Model: claude-opus-5-5 (effort high) Results: 50 reviewed of 88 in the report (random sample) Verdicts: 3 acceptable regression, 39 improvement, 8 regression Tokens: 250595 input, 66934 cache read, 1366 cache write, 43428 output The verdicts are written by AI and can be wrong. ---- 1 / 50 ---- Verdict: ACCEPTABLE REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/c/cups-filters/cups-filters_1.28.17.orig.tar.gz Result: main cups-filters-1.28.17/filter/foomatic-rip/util.c:226:11: style: Variable 'pstr' can be declared as pointer to const [constVariablePointer] Explanation: In strrepl_nodups, 'pstr' is only read through (`*pstr` in the loop condition, in `strchr(chars, *pstr)`, in `*pstr == repl` and in `*p = *pstr`) and only the pointer itself is incremented. All writes go through the separate pointer 'p'. So 'pstr' could be declared 'const char *', and main's constVariablePointer warning was a true positive. The PR changes the indirection computation in isVariableChanged and drops the warning, which is a new false negative. ---- 2 / 50 ---- Verdict: REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/d/devio/devio_1.2.orig.tar.gz Result: your devio-1.2/src/devio.c:707:29: style: Parameter 'pp' can be declared as pointer to const [constParameterPointer] Explanation: `quit()` calls `close_mtd(pp->files+i)`. `files` is an array member of `*pp`, so `pp->files+i` points into the struct `pp` points to. `close_mtd` takes a non-const `mtd_file*` and closes the file, which modifies that struct. If `pp` were declared `const parse_buf*`, `pp->files+i` would become `const mtd_file*`, and passing it to `close_mtd` would discard the qualifier. The new constParameterPointer warning is therefore a false positive. The `indirect - derefs` change appears to lose track of modification through an array member used in pointer arithmetic. ---- 3 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/extension/parquet/parquet_writer.cpp:1225:13: style: Variable 'child_writer' can be declared as reference to const [constVariableReference] Explanation: In the loop, `child_writer` is a `unique_ptr` element of `children`. It is only dereferenced and passed to `GetStatsUnifier(const ColumnWriter&, ...)`, so neither the smart pointer nor the object it points to is modified, and `const auto &child_writer` would compile. The PR makes the dereference (`*child_writer`) count toward indirection, so Cppcheck no longer wrongly treats the element as possibly changed. That makes this a valid new finding. One caveat: if `ChildWriters()` already returns a const container, `auto &` already deduces const and the suggestion is redundant. ---- 4 / 50 ---- Verdict: REGRESSION (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/extension_external/mysql/src/storage/mysql_capabilities.cpp:1070:14: style: Variable 'expr' can be declared as reference to const [constVariableReference] Explanation: `node` is a `const QueryNode&`, so `select` is a const `SelectNode&`. In `for (auto &expr : select.select_list)`, `expr` is therefore already deduced as `const unique_ptr&`. Telling the user it 'can be declared as reference to const' is redundant noise: writing `const auto&` changes nothing. The warning appears because the patch subtracts `derefs` from `indirect`, which can make `pindirect` negative for the `*expr` dereference. The other new warnings come from the same pattern, `*child` / `*expr` derefs of `unique_ptr` elements passed to functions, and many of those pass the pointee to non-const functions. Those suggestions only compile because smart-pointer constness does not propagate to the pointee, which Cppcheck normally does not ignore. So this new warning is a spurious side effect of the change, not a real finding. ---- 5 / 50 ---- Verdict: IMPROVEMENT (high confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/extension_external/sqlite/src/sqlite/sqlite3.c:142604:39: style: Parameter 'pTrigger' can be declared as pointer to const [constParameterPointer] Explanation: `tableOfTrigger` only reads through `pTrigger`. It reads `pTrigger->pTabSchema` and `pTrigger->table`, then passes `&pTrigger->pTabSchema->tblHash` to `sqlite3HashFind`, which takes a `const Hash*` and does not modify anything. `pTabSchema` is a pointer member, so making `pTrigger` const does not make the pointed-to `Schema` const, and the expression would still compile. Declaring `pTrigger` as `const Trigger *` is valid, so this new warning is a true positive. ---- 6 / 50 ---- Verdict: IMPROVEMENT (high confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/extension_external/sqlite/src/sqlite/sqlite3.c:153165:13: style: Variable 'pE2' can be declared as pointer to const [constVariablePointer] Explanation: `pE2` is assigned from `pExpr->pLeft` and then only read (`pE2->op`, `pE2->iTable`, `pE2->iColumn`). Nothing is ever written through it; the only write is to `pExpr->iColumn`, which goes through `pExpr`, not `pE2`. So `pE2` can be declared `const Expr *`, and the new constVariablePointer warning is a true positive. The PR subtracts `derefs` from the indirection level, so reading through a dereferenced pointer is no longer counted as modifying it. ---- 7 / 50 ---- Verdict: IMPROVEMENT (high confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/extension_external/sqlite/src/sqlite/sqlite3.c:71512:12: style: Variable 'pPage' can be declared as pointer to const [constVariablePointer] Explanation: In moveToLeftmost, 'pPage' is only read through: it is assigned from pCur->pPage, then its 'leaf' and 'nCell' members are read. It is also passed to the findCell macro, which only reads aData, maskPage and aCellIdx, and the result goes to get4byte, which takes a const u8*. Nothing is written through pPage, so declaring it 'const MemPage *' is valid. The new warning is a true positive. ---- 8 / 50 ---- Verdict: IMPROVEMENT (high confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/extension_external/sqlite/src/storage/sqlite_transaction.cpp:177:13: style: Variable 'expr' can be declared as reference to const [constVariableReference] Explanation: `expr` is a `unique_ptr&` bound to elements of `info->expressions`. It is only used as `*expr`, which is passed to `ExtractColumnIds(const ParsedExpression&, ...)`. Nothing writes to the unique_ptr itself, and dereferencing a const unique_ptr still yields the pointee. So `const auto &expr` would compile and is correct. Before the fix, the dereference was wrongly counted as modifying `expr`; with the PR it is no longer counted, so this new warning is a true positive. ---- 9 / 50 ---- Verdict: IMPROVEMENT (low confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/execution/physical_plan/plan_cte.cpp:14:13: style: Variable 'child' can be declared as reference to const [constVariableReference] Explanation: `child` only binds to elements of `op.children` and is used as `*child`. That dereference is passed to `ContainsRecursiveCTE(const LogicalOperator&)`, so the unique_ptr reference itself is never modified. Before the PR, Cppcheck wrongly counted the dereference (`derefs`) as a possible change of `child`. With `indirect - derefs`, it now sees that `child` is not changed, so `const auto &child` is valid. Because `op` is already const, `auto&` already deduces a const reference, so the warning only asks to make that explicit. It is correct but low value, hence low confidence. ---- 10 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/function/macro_function.cpp:204:15: style: Variable 'function' can be declared as reference to const [constVariableReference] Explanation: The loop variable `function` is a reference to an element of `functions`, which is most likely a vector of `unique_ptr`. It is only used as `*function` when calling `FormatMacroFunction`. Dereferencing a const `unique_ptr` still gives a non-const `MacroFunction&`, so `const auto &function` compiles with the same behaviour no matter what `FormatMacroFunction` takes. The element itself is never modified, so the new warning is a valid style finding. It appears because the PR now subtracts the dereference count when checking whether a variable is changed. ---- 11 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/main/capi/v2/capi_v2_query_metrics.cpp:54:13: style: Variable 'child' can be declared as reference to const [constVariableReference] Explanation: `child` iterates over `node.children`, where `node` is a `const ProfilingNode &`. The loop only uses `*child`, which is passed to `SnapshotQueryMetricsOperator`, and that function takes a `const ProfilingNode &`. Nothing modifies `child` or its pointee, so `const auto &child` compiles and states the intent explicitly. The pull request now subtracts dereferences when deciding indirection, so `*child` no longer counts as a possible change of `child`. The new warning is a valid, if minor, true positive. ---- 12 / 50 ---- Verdict: REGRESSION (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/main/query_profiler.cpp:811:14: style: Variable 'child' can be declared as reference to const [constVariableReference] Explanation: `node` is a `const QueryProfileResult&`, so `node.children` is const and `auto &child` already deduces to a const reference (likely `const unique_ptr<...>&`). Telling the user to declare it as reference to const is redundant noise: adding `const` changes nothing. The new warning comes from the PR computing `indirect - derefs`, which can go negative for `*child`. The same pattern produces dozens of new `child` warnings across duckdb, where smart pointers are dereferenced and the pointees are possibly modified. This looks like a newly introduced false positive, not a useful finding. ---- 13 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/optimizer/cte_inlining.cpp:110:13: style: Variable 'child' can be declared as reference to const [constVariableReference] Explanation: In `ContainsDelimGet`, `child` is only dereferenced, and `*child` is passed by const reference to the recursive call. The `unique_ptr` element is never modified. Before the PR, the deref was not subtracted, so passing `*child` was wrongly treated as a possible change to `child` itself. Now `child` is correctly seen as unmodified, and suggesting `const auto &child` is valid. Because `op` is const, the deduced type is already const, so the suggestion is partly redundant. It is still correct and harmless, and it matches the new test case for #15203. ---- 14 / 50 ---- Verdict: REGRESSION (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/optimizer/cte_inlining.cpp:127:13: style: Variable 'child' can be declared as reference to const [constVariableReference] Explanation: `op` is a `const LogicalOperator &`, so in `for (auto &child : op.children)` the type of `child` is already deduced as `const unique_ptr&`. Writing `const auto &` would add nothing, so the new constVariableReference warning is redundant noise rather than a useful finding. The same pattern appears on many other new 'child' warnings in this package, where loops run over children of a const operator. The warning appears because the PR now uses `indirect - derefs` for `*child`, which gives a negative indirection (-1) here; that looks like an unintended side effect, not a better understanding of the code. ---- 15 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/optimizer/cte_inlining.cpp:33:13: style: Variable 'child' can be declared as reference to const [constVariableReference] Explanation: In the loop `for (auto &child : op.children)`, `child` is only dereferenced as `*child`. That value is passed to `CountBaseTableReferences(const LogicalOperator&)`, so nothing is modified through it. Before the PR, Cppcheck ignored the dereference when computing indirection and wrongly treated `child` as possibly changed. With the PR, it correctly sees no modification and reports that `child` can be `const auto&`, which compiles fine. Because `op` is const, the deduced type is already const, so the suggestion is mostly a matter of explicitness. It is still not wrong, and it matches the PR's intended behaviour. ---- 16 / 50 ---- Verdict: REGRESSION (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/optimizer/cte_inlining.cpp:62:13: style: Variable 'child' can be declared as reference to const [constVariableReference] Explanation: `op` is a `const LogicalOperator &`, so `op.children` is const. In `for (auto &child : op.children)`, `child` is therefore already deduced as `const unique_ptr &`. Writing `const auto &` would produce exactly the same type, so the advice adds no const-correctness. The PR's change to the deref/indirection handling makes Cppcheck consider `*child` unmodified, but it misses that the deduced type is already const. This is a new noisy false positive, and the same pattern is repeated at lines 33, 48 and 98 of this file. ---- 17 / 50 ---- Verdict: REGRESSION (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/optimizer/join_order/relation_manager.cpp:225:13: style: Variable 'child' can be declared as reference to const [constVariableReference] Explanation: `op` is a `const LogicalOperator&`, so `op.children` is a const vector. `auto &child` therefore already deduces to `const unique_ptr&`. The variable already is a reference to const, and writing `const auto &` would change nothing. The warning appears only because the PR now subtracts `derefs` from the indirection when `*child` is passed on, so Cppcheck no longer treats the variable as possibly changed. It still does not see that the deduced type is already const. The result is a redundant, misleading warning, i.e. a false positive introduced by the PR. ---- 18 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/optimizer/materialized_aggregate_reuse.cpp:546:13: style: Variable 'expression' can be declared as reference to const [constVariableReference] Explanation: `expression` is a reference to a `unique_ptr` element of `aggregate.expressions`. The loop only dereferences it (`*expression`) and passes the result to `RewriteToCTE`. `unique_ptr::operator*` is a const member and returns `Expression&`, so declaring `const auto &expression` compiles even if `RewriteToCTE` takes a non-const `Expression&`. The unique_ptr itself is never reset or reassigned inside the loop. The later move of `aggregate.expressions` assigns a new vector after the loop and does not touch `expression`. The new warning is therefore a valid true positive, gained because the PR subtracts dereferences when computing indirection. ---- 19 / 50 ---- Verdict: REGRESSION (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/optimizer/optimizer.cpp:178:13: style: Variable 'child' can be declared as reference to const [constVariableReference] Explanation: `op` is a `const LogicalOperator&`, so `op.children` is const. `auto &child` therefore already deduces to `const unique_ptr&`. Adding `const` would change nothing, so the warning is redundant noise, i.e. a false positive. The same pattern appears in many of the new duckdb warnings (`child` loops over const operators). The PR's change to pointer-indirection handling (`indirect - derefs`) causes this: passing `*child` to a const-ref function is now no longer treated as modifying `child`. That would be fine for a non-const range, but here the variable is already const. ---- 20 / 50 ---- Verdict: IMPROVEMENT (low confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/optimizer/optimizer.cpp:208:13: style: Variable 'child' can be declared as reference to const [constVariableReference] Explanation: `op` is `const LogicalOperator&`, so `auto &child` binds to `const unique_ptr&`. The loop only dereferences `child` and passes `*child` to `CTEContainsDML`, which takes a const reference, so `child` is never modified. Writing `const auto &child` compiles and states that intent explicitly. The PR fixes `isVariableChanged` so that a dereference passed to a const-ref parameter is no longer treated as modifying the pointer variable, which is what lets this warning appear. The warning is technically correct but of low value, because the deduced type is already const. Confidence is low: some users would see this as redundant, and the new `indirect - derefs` computation may go negative in other contexts. ---- 21 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/optimizer/pushdown/pushdown_projection.cpp:102:13: style: Variable 'expr' can be declared as reference to const [constVariableReference] Explanation: `expr` is a `unique_ptr&` taken from `split_expressions`, and the loop only uses `*expr` as an argument to `CollectReferencedProjections`. The unique_ptr itself is never reassigned, reset or moved. `unique_ptr::operator*` is const and still returns a non-const `Expression&`, so `for (const auto &expr : split_expressions)` would compile and behave the same whatever the callee's parameter type is. The warning is therefore a true positive. The PR's change, subtracting dereferences from the indirection level when a dereferenced variable is passed to a function, correctly stops treating `*expr` as a modification of `expr`. ---- 22 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/planner/binder/query_node/bind_setop_node.cpp:245:14: style: Variable 'child' can be declared as reference to const [constVariableReference] Explanation: In `for (auto &child : node.Cast().children)`, `child` (a `unique_ptr`) is only dereferenced and passed as `*child` to `SetOpProvidesOrderExpression(const ParsedExpression&, const QueryNode&)`. Neither the pointer nor the pointee is modified, so `const auto &child` is valid. Because `node` is const, the deduced type is probably already const, so the suggestion mainly makes that explicit. It is harmless and correct. The PR fixes indirection tracking when a dereferenced variable is passed to a function (see #15203), so this new finding matches its intent. ---- 23 / 50 ---- Verdict: IMPROVEMENT (low confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/planner/binder/tableref/bind_table_function.cpp:219:13: style: Variable 'child' can be declared as reference to const [constVariableReference] Explanation: In `for (auto &child : op.children)`, `child` is a `unique_ptr` element. It is only dereferenced as `*child` and passed to `PlanSupportsStatementCache(const LogicalOperator&)`, so the `unique_ptr` itself is never modified. Before the PR, `isVariableChanged` ignored the dereference and treated `*child` passed to a function as a change to `child`. The PR subtracts the deref count, so cppcheck now sees that `child` stays unchanged. Writing `const auto &child` compiles and matches what the loop does. Since `op` is already const, the deduced type is already const, so the suggestion only makes that explicit. That makes it a minor style hint rather than a wrong warning. ---- 24 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/planner/expression_nullability.cpp:53:14: style: Variable 'child' can be declared as reference to const [constVariableReference] Explanation: In the range-for loop, `child` (a `unique_ptr` element) is only dereferenced, and `*child` is passed to `FilterRejectsNull(const Expression&, ...)`. Neither the smart pointer nor the pointee is modified, so `const auto &child` is valid. Before the PR, `isVariableChanged` ignored the dereference when checking the call argument (`pindirect = indirect` instead of `indirect - derefs`). That made `*child` look like a possible modification of `child` and suppressed the warning. This PR fixes exactly that, matching the added test case. If `GetChildren()` on the const `conjunction` already returns a const container, the `auto&` is const by deduction and the hint is mostly stylistic. It is still not a wrong diagnostic, so this is a new true positive. ---- 25 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/planner/filter/expression_filter.cpp:285:15: style: Variable 'child_expr' can be declared as reference to const [constVariableReference] Explanation: `child_expr` is a reference to an element of `func.GetChildren()`, most likely a `unique_ptr`. Inside the loop it is only dereferenced as `*child_expr` and passed to `TryGetExpressionStats`. `unique_ptr::operator*` is a const member and still returns a non-const `Expression&`. So writing `const auto &child_expr` compiles and behaves the same even if the callee takes a non-const `Expression&`. The smart pointer itself is never reset, moved or reassigned. Before the PR, the dereference was wrongly counted as a modification of the variable. The PR subtracts the dereference count, so Cppcheck now reports this real const-correctness opportunity. ---- 26 / 50 ---- Verdict: IMPROVEMENT (high confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/planner/sql_export/sql_export_composition.cpp:159:14: style: Variable 'expression' can be declared as reference to const [constVariableReference] Explanation: `expression` is a reference to a `unique_ptr` element of `op.expressions`. It is only dereferenced and passed to `HasCompositionBarrier(const Expression &)`. Nothing modifies the unique_ptr or the object it points to, so `const auto &expression` would compile and is correct. Cppcheck previously missed this because of the dereference; the PR now accounts for it. This is a new true positive. ---- 27 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/planner/sql_export/sql_export_composition.cpp:252:13: style: Variable 'expression' can be declared as reference to const [constVariableReference] Explanation: `expression` is a reference to a `unique_ptr` element of `projection.expressions`. The loop only dereferences it: `HasCompositionBarrier(*expression)` and `SemanticInput(*expression)`. It never reseats, resets or moves the `unique_ptr` itself. `unique_ptr::operator*` is const and still returns a non-const `Expression&`, so `const auto &expression` compiles even if those helpers take non-const references. The new warning is therefore a true positive, consistent with the PR's intent to subtract dereferences when checking whether the variable itself is changed. ---- 28 / 50 ---- Verdict: REGRESSION (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/planner/sql_export/sql_export_values.cpp:88:13: style: Variable 'child' can be declared as reference to const [constVariableReference] Explanation: `op` is a `const LogicalOperator &`, so `op.children` is a const container. `auto &child` therefore already deduces to `const unique_ptr &`. Telling the user to declare it as reference to const is redundant and adds nothing. The new warning appears because the PR changes how dereferences (`*child`) are counted in isVariableChanged. In this case Cppcheck misses that the deduced reference is already const, so the warning is noise (a false positive). ---- 29 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/planner/table_filter_set.cpp:224:13: style: Variable 'child' can be declared as reference to const [constVariableReference] Explanation: In the range-for, `child` (a `unique_ptr` element) is only dereferenced as `*child` and passed to `SerializeExpressionToLegacyFilter(const Expression &)`. The function never modifies the pointer or its pointee through a non-const path, so `const auto &child` compiles and is correct. The PR makes `isVariableChanged` account for the dereference, which lets Cppcheck see this. The new warning is a valid (if minor, since `conjunction` is already const) style finding. ---- 30 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/src/planner/table_filter_state.cpp:590:14: style: Variable 'child_expr' can be declared as reference to const [constVariableReference] Explanation: `child_expr` is a reference to a `unique_ptr` element. It is only dereferenced and passed as `*child_expr` to `TryCreateFastExecutor(const Expression&, bool)`, which takes a const reference. Neither the element nor its pointee is modified, so `const auto &child_expr` is valid. The PR subtracts the dereference count when checking whether the variable is changed through a function call, so passing `*child_expr` to a const-ref parameter no longer counts as a modification. This is the same pattern as the PR's new test (`v.push_back(*p)`). Because `conjunction` is const, `auto&` may already deduce to const, which would make the suggestion redundant rather than wrong. Still, the warning reflects correct analysis, and adding `const` is harmless and makes the intent explicit. ---- 31 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/test/api/test_query_result_arrow.cpp:230:13: style: Variable 'array' can be declared as reference to const [constVariableReference] Explanation: The loop variable `array` is only used as `*array`, and the result is passed to `Rows()`. The elements of `arrays` are pointer-like, most likely `unique_ptr` or a raw pointer. Their `operator*` is const and still yields a mutable pointee, so `const auto &array` compiles even if `Rows` takes a non-const reference. The element itself is never modified. Before the PR, Cppcheck wrongly treated the dereference as modifying the reference variable. The PR now subtracts `derefs` from the indirection, which fixes that. The new warning is a valid true positive, matching the sibling warning at line 200. Confidence is medium because the exact element type returned by `DrainArrays` is not shown. ---- 32 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/test/api/test_query_result_arrow.cpp:45:13: style: Variable 'array' can be declared as reference to const [constVariableReference] Explanation: In `TotalRows`, `array` is only dereferenced and passed to `Rows(const ArrowArrayWrapper &)`, so neither the `unique_ptr` nor its pointee is modified. Writing `const auto &array` is valid and expresses read-only use. Since `arrays` is a const reference, `auto &` already deduces a const type, so the suggestion is mostly stylistic. It is still not a false positive. The PR now accounts for the dereference when checking whether the variable is changed, which correctly treats `*array` passed to a const reference as no change to `array`. ---- 33 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/test/api/test_retained_result_collection.cpp:95:13: style: Variable 'payload' can be declared as reference to const [constVariableReference] Explanation: `payload` is a reference to an element of `global.Get()`. The element is a smart pointer, as shown by `*payload` and `payloads[batch]->row_count`. Inside the loop it is only dereferenced and passed as `*payload` to `PayloadValues`. Dereferencing a const smart pointer still yields a non-const pointee, so `const auto &payload` compiles and behaves the same whatever `PayloadValues` takes. The PR stops counting a dereference of the variable as a modification of the variable itself. The new constVariableReference warning is therefore a valid true positive. At worst it is redundant if `Get()` already returns a const container. ---- 34 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/test/optimizer/bound_function_identity.cpp:90:13: style: Variable 'child' can be declared as reference to const [constVariableReference] Explanation: `child` iterates over `op.children` and is only used as `*child`, which is passed to `CollectJoinFilterAggregates(const LogicalOperator &, ...)`. The `unique_ptr` reference itself is never modified, so writing `const auto &child` compiles and is correct. Because `op` is a const reference, the deduced type is already const, so the suggestion adds explicitness rather than changing behavior. The PR fixes `isVariableChanged` so a dereference passed to a function is no longer treated as modifying the variable itself. That lets Cppcheck correctly see `child` is unmodified. The new warning is a valid, if low-value, true positive. ---- 35 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/d/duckdb/duckdb_2.0.0+dfsg2.orig.tar.gz Result: your duckdb-2.0.0+dfsg2/test/optimizer/expression_type_serialization.cpp:63:13: style: Variable 'expression' can be declared as reference to const [constVariableReference] Explanation: The loop `for (auto &expression : plan.expressions)` only uses `*expression` as an argument to `CheckExpressionTypes(ClientContext&, const Expression&)`. That is a read-only use, so neither the `unique_ptr` nor the `Expression` it points to is modified. Writing `const auto &expression` is therefore valid. Because `plan` is a const reference, `auto&` already deduces a const reference, so the change mostly makes the constness explicit. It is still a correct suggestion and matches the `const auto &` style used elsewhere in this file. The PR now subtracts the dereference count when checking whether a function argument changes the variable, so `*x` passed to a const reference parameter is correctly seen as not modifying `x`. That is the case shown here, so the new warning is a true positive. ---- 36 / 50 ---- Verdict: IMPROVEMENT (high confidence) Package: https://ftp.debian.org/debian/pool/main/f/fbi/fbi_2.14.orig.tar.gz Result: your fbida-2.14/RegEdit.c:407:7: style: Parameter 'selection' can be declared as pointer to const. However it seems that 'GetCommand' is a callback function, if 'selection' is declared with const you might also need to cast function pointer(s). [constParameterCallback] fbida-2.14/RegEdit.c:216:8: note: You might need to cast the function pointer here fbida-2.14/RegEdit.c:407:7: note: Parameter 'selection' can be declared as pointer to const Explanation: 'selection' is only dereferenced and its value is passed by value (`*selection`) to BuildEvent and ExecuteCommand, so it is never modified through the pointer. Before this PR, Cppcheck treated passing the dereferenced value to a function as a possible change. The PR subtracts `derefs` from the indirection level, which fixes that. The new warning is a true positive. It is correctly given as the callback variant, because GetCommand is used as an Xt selection callback at line 216. ---- 37 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/m/mozc/mozc_3.35.6354+ds1.orig.tar.xz Result: your google-mozc-5dc3f95/src/rewriter/number_rewriter_test.cc:349:12: style: Variable 'seg' can be declared as pointer to const [constVariablePointer] Explanation: In the visible code, `seg` is only reassigned from `SetupSegments(...)` and dereferenced as `*seg` to pass to `HasDescription`. That helper is a read-only check that most likely takes `const Segment&`. Reassigning a `const Segment*` from a `Segment*` is legal, and nothing changes the pointee through `seg`, so declaring it `const Segment*` works. The PR fixes the indirection count for dereferenced arguments: `*seg` passed to a function no longer looks like a modification of the pointer itself. That lets Cppcheck find this true positive. Confidence is medium because the rest of the test after line 389 and the exact signature of `HasDescription` are not shown. ---- 38 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/o/ode/ode_0.16.6.orig.tar.gz Result: your ode-0.16.6/ode/src/resource_control.cpp:174:38: style: Variable 'requirementsDescriptor' can be declared as pointer to const [constVariablePointer] Explanation: At line 176, `requirementsDescriptor` is only dereferenced and passed to the copy constructor of `dxResourceRequirementDescriptor`. An implicit or ordinary copy constructor takes `const&`, so the pointer can point to const. The commented-out `/*const */` on the parameter suggests the authors intended this too. Before the PR, the dereference was not subtracted from the indirection level when checking the constructor call, so the pointer was wrongly treated as modified. The new constVariablePointer warning is a true positive, matching the PR's test case (#15203). Confidence is medium because the class definition, and so its copy constructor signature, is not shown. ---- 39 / 50 ---- Verdict: ACCEPTABLE REGRESSION (high confidence) Package: https://ftp.debian.org/debian/pool/main/p/proxychains/proxychains_3.1.orig.tar.gz Result: main proxychains-3.1/proxychains/core.c:681:18: style: Variable 'hp' can be declared as pointer to const [constVariablePointer] Explanation: `hp` is only assigned from `proxy_gethostbyname()` and then read through `*(hp->h_addr_list)` as the source argument of `memcpy`. Nothing is ever written through `hp`, so it could be `const struct hostent *`, and the constVariablePointer warning was a true positive. The PR now subtracts `derefs` from `indirect` when checking whether a variable is changed. That miscounts the indirection on the member access here, so Cppcheck treats `hp` as possibly modified and drops the warning. This is a new false negative. ---- 40 / 50 ---- Verdict: IMPROVEMENT (high confidence) Package: https://ftp.debian.org/debian/pool/main/p/python-grpc-tools/python-grpc-tools_1.14.1.orig.tar.gz Result: your python-grpc-tools-1.14.1/third_party/protobuf/src/google/protobuf/descriptor.cc:4031:15: style: Variable 'parent_name' can be declared as pointer to const [constVariablePointer] Explanation: `parent_name` is a `string*` whose only use is `*parent_name`, passed to `AddPackage(const string& name, ...)`. That parameter is a const reference, so the pointee is never modified and `parent_name` could be `const string*`. The PR subtracts the dereference count when checking function arguments. Cppcheck now correctly sees that `*parent_name` is passed by const reference and is not changed. The new warning is a true positive. ---- 41 / 50 ---- Verdict: ACCEPTABLE REGRESSION (medium confidence) Package: https://ftp.debian.org/debian/pool/main/r/recastnavigation/recastnavigation_1.6.0+dfsg.orig.tar.gz Result: main recastnavigation-1.6.0/RecastDemo/Source/TestCase.cpp:372:11: style: The if condition is the same as the previous if condition [duplicateCondition] recastnavigation-1.6.0/RecastDemo/Source/TestCase.cpp:346:11: note: First condition recastnavigation-1.6.0/RecastDemo/Source/TestCase.cpp:372:11: note: Second condition Explanation: Both `if (iter->expand)` checks at lines 346 and 372 test the same condition. Nothing in between modifies `iter->expand`: the first block only passes float values such as `iter->spos[0]-s` to glVertex3f/glColor4ub. So the duplicateCondition warning was a true positive. The PR changes the indirection passed to the sub-check to `indirect - derefs`. With `iter->spos[...]` dereferences, this apparently makes isVariableChanged treat `iter` as possibly modified, which suppresses the warning. Losing it is a new false negative. ---- 42 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/s/speech-tools/speech-tools_2.5.0.orig.tar.gz Result: your speech_tools/ling_class/EST_item_content_aux.cc:115:12: style: Variable 'i' can be declared as pointer to const [constVariablePointer] Explanation: `i` is only dereferenced and passed as `*i` to `getFloat`. In speech_tools that function (like `start`, `getString` and `getInteger` at the other reported lines) takes `const EST_Item &`, so `i` could be `const EST_Item *`. Before the PR, Cppcheck did not subtract the dereference count when checking whether a function argument changes the variable, so the pointer looked modified. The fix matches the new test case (`v.push_back(*p)`). The new warnings are likely true positives. ---- 43 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/s/speech-tools/speech-tools_2.5.0.orig.tar.gz Result: your speech_tools/ling_class/EST_item_content_aux.cc:136:12: style: Variable 'i' can be declared as pointer to const [constVariablePointer] Explanation: `i` is only dereferenced and passed as `*i` to `start(...)`. In speech_tools, `start` for an item is declared in EST_item_aux.h as `float start(const EST_Item &)`, so the pointee is never modified and `i` could be `const EST_Item *`. Before the PR, Cppcheck checked the dereferenced argument at the wrong indirection level, treating `*i` as if it were still the pointer. It therefore assumed the pointee might change and stayed silent. The fix subtracts the dereference count, so the true positive is now reported. This matches the PR's own test case (`v.push_back(*p)`). ---- 44 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/s/speech-tools/speech-tools_2.5.0.orig.tar.gz Result: your speech_tools/ling_class/EST_item_content_aux.cc:159:12: style: Variable 'i' can be declared as pointer to const [constVariablePointer] Explanation: `i` is only used as `mid(*i)`. The speech_tools overloads `start/mid/time/end(const EST_Item &)` take a const reference, so the pointee is never modified and `i` can be `const EST_Item *`. Before the PR, the dereference was not subtracted from the indirection level, so Cppcheck wrongly assumed the pointer was modified and missed the warning. The PR fixes that false negative, and this new warning is a true positive. ---- 45 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/s/speech-tools/speech-tools_2.5.0.orig.tar.gz Result: your speech_tools/ling_class/EST_item_content_aux.cc:182:12: style: Variable 'i' can be declared as pointer to const [constVariablePointer] Explanation: `i` is only dereferenced once and passed as `*i` to `time()`. In speech_tools the EST_Item helpers (`start`, `mid`, `time`, `end`) are declared as taking `const EST_Item &`, so `i` could be `const EST_Item *`. The PR subtracts the dereference count when checking whether the pointer itself is changed. That lets Cppcheck see that `*i` passed to a const-reference parameter does not modify the pointee. This matches the new test case and gives a valid new constVariablePointer warning (a true positive). ---- 46 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/s/speech-tools/speech-tools_2.5.0.orig.tar.gz Result: your speech_tools/ling_class/EST_item_content_aux.cc:202:12: style: Variable 'i' can be declared as pointer to const [constVariablePointer] Explanation: `i` is only dereferenced and passed as `end(*i)`. In speech_tools, `end()` for an item is declared as `float end(const EST_Item &item)`, so the pointee is never modified, and `const EST_Item *i` would compile. The PR now subtracts the dereference count when checking whether the argument is changed, so the case of `*p` passed to a const-reference parameter is handled correctly. The previously missed constVariablePointer warning is therefore a true positive. The same pattern applies to the sibling lines in this file. ---- 47 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/s/speech-tools/speech-tools_2.5.0.orig.tar.gz Result: your speech_tools/ling_class/EST_item_content_aux.cc:66:12: style: Variable 'i' can be declared as pointer to const [constVariablePointer] Explanation: `i` is only dereferenced and passed as `*i` to `getVal`. In speech_tools, the `getVal`/`getString`/`getInteger`/`getFloat` overloads for `EST_Item` take `const EST_Item &`, so the pointee is never modified and `i` could be `const EST_Item *`. Before the PR, Cppcheck checked the argument with the wrong indirection: it did not subtract the dereference. That made it treat passing `*i` as a possible change to the pointee, which hid this warning. The fix corrects the indirection, so the new constVariablePointer warning is a true positive. ---- 48 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/s/speech-tools/speech-tools_2.5.0.orig.tar.gz Result: your speech_tools/ling_class/EST_item_content_aux.cc:83:12: style: Variable 'i' can be declared as pointer to const [constVariablePointer] Explanation: `i` is only used as `*i` in a call to the `getString(const EST_Item &, ...)` overload. speech_tools declares these feature getters with a const reference parameter, so the pointee is never modified. `i` can therefore be `const EST_Item *`. Before the PR, the dereference was not subtracted from the indirection level, so the call wrongly counted as a possible modification and the warning was missed. The new warning is a true positive, matching the PR's test case. ---- 49 / 50 ---- Verdict: IMPROVEMENT (medium confidence) Package: https://ftp.debian.org/debian/pool/main/s/speech-tools/speech-tools_2.5.0.orig.tar.gz Result: your speech_tools/ling_class/EST_item_content_aux.cc:99:12: style: Variable 'i' can be declared as pointer to const [constVariablePointer] Explanation: `i` is only dereferenced and passed as `*i` to `getInteger(*i, ...)`. In speech_tools, the `EST_Item` overloads of `getInteger`, `getFloat`, `getString`, `getVal` and `start` appear to take `const EST_Item &`, recalled from the header rather than shown here. If so, `i` could be `const EST_Item *`. The PR subtracts the dereference count when computing the indirection level for the argument check. Cppcheck therefore now sees that `*i` goes to a const reference, which yields this true positive that main missed. ---- 50 / 50 ---- Verdict: IMPROVEMENT (high confidence) Package: https://ftp.debian.org/debian/pool/main/u/ucspi-tcp/ucspi-tcp_0.88.orig.tar.gz Result: your ucspi-tcp-0.88/dns_ipq.c:33:79: style: Parameter 'rules' can be declared as pointer to const [constParameterPointer] Explanation: Inside dns_ip4_qualify_rules, 'rules' is only read: rules->len and rules->s[j] are read, and rules->s + i is passed to doit(). With 'const stralloc *rules', the member 's' becomes 'char * const', so 'rules->s + i' is still a 'char *' and the call to doit(stralloc*, char*) still compiles. Nothing writes through 'rules', so declaring it pointer to const is valid. The PR subtracts derefs from the indirection count, so Cppcheck no longer treats passing the pointed-to data as changing the pointer itself. This is a correct new true positive.