Repository navigation
Fix #15150 Duplicate accessMoved (passed by value to subfunction) - #8969
chrchr-github wants to merge 3 commits into
Conversation
|
Test results for commit 9d0880c (tools/test-my-pr.py, main compared to this PR): Test: http://ec2-16-170-140-253.eu-north-1.compute.amazonaws.com/pr-8969/ Posted automatically by the cppcheck PR test runner. +N: warnings only with this PR, -N: warnings only with main. The AI review is written by Claude and can be wrong. |
dmcppcheck
left a comment
There was a problem hiding this comment.
AI review
The change loses real accessMoved warnings. It drops moved values for every argument passed to a subfunction, not only for parameters taken by value. When a moved-from object is passed by non-const reference, the caller reports nothing because the callee could reinitialize the object. Before this PR the warning came from inside the callee, through the moved value that valueflow passes into the subfunction. With the PR that warning is gone, so true positives are lost. This may be the "1 regression" that the PR test runner reported.
A narrower fix would only remove moved values when the parameter is passed by value, e.g. return v.isMovedValue() && !argvar->isReference();. That fixes #15150 and keeps the moved value for reference parameters. I have not built or tested this alternative.
Testing
I built cppcheck and testrunner in pr/ and cppcheck in base/. ./testrunner TestOther TestValueFlow TestUninitVar passed, and the new moveSubFunction test passes.
False negative (reproduced): scratch/b.cpp
#include <string>
#include <utility>
#include <vector>
struct T { void set(std::string a) { m = std::move(a); } std::string m; };
void f(std::string s) { T t; t.set(std::move(s)); t.set(s); }
void g1(std::vector<int>& v) { int x = v[0]; (void)x; }
void f1() { std::vector<int> v; auto w = std::move(v); g1(v); }
void g3(std::string& s) { std::string t = s; }
void f3() { std::string s; std::string t = std::move(s); g3(s); }Command: cppcheck -q --enable=warning --template='{line}:{column} {id} {message}' b.cpp (only the accessMoved lines are shown)
base:
4:52 accessMoved Access of moved variable 'a'. <- the false positive from #15150
5:57 accessMoved Access of moved variable 's'.
6:40 accessMoved Access of moved variable 'v'.
8:43 accessMoved Access of moved variable 's'.
PR:
5:57 accessMoved Access of moved variable 's'.
The PR removes the #15150 false positive (4:52), but it also loses the true positives at 6:40 (v[0] on a moved-from vector) and 8:43. The caller does not report them either, so these bugs are no longer found.
Arguments passed by value, by const reference and as std::move(s) after a move (scratch/a.cpp) give the same results with base and PR. The callers already report them.
Automated review of 9d0880c by Claude. The pull request was built and tested locally.
| if (v.isLifetimeValue()) | ||
| return !v.isLocalLifetimeValue() && !v.isSubFunctionLifetimeValue(); | ||
| return false; | ||
| return v.isMovedValue(); |
There was a problem hiding this comment.
AI review
This removes moved values for every parameter kind, so it loses true positives when a moved-from object is passed by non-const reference. The caller does not warn in that case, because the callee could reinitialize the object, so before this PR the callee was the only place where the warning came from:
void g1(std::vector<int>& v) { int x = v[0]; (void)x; }
void f1() { std::vector<int> v; auto w = std::move(v); g1(v); }base: accessMoved at v[0]. PR: no warning.
Restricting the removal to by-value parameters would fix #15150 and keep these warnings, e.g. return v.isMovedValue() && !argvar->isReference(); (the lambda would need to capture argvar). A test with a reference parameter would also help.
No description provided.