Repository navigation
Fix #15116 FP stlFindInsert (modifying existing element) - #8968
chrchr-github wants to merge 5 commits into
Conversation
| " m[1] = true;\n" | ||
| "}\n", | ||
| dinit(CheckOptions, $.inconclusive = true)); | ||
| ASSERT_EQUALS("", errout_str()); // TODO: warn about duplicate search |
There was a problem hiding this comment.
Why are we removing the warning here? We should just update the warning message.
There was a problem hiding this comment.
Feel free to add the logic necessary to generate a fitting error message in this case. The condition handling also needs tweaking, see https://trac.cppcheck.net/ticket/15146
There was a problem hiding this comment.
I update the logic for the error message in #8975.
dmcppcheck
left a comment
There was a problem hiding this comment.
AI review
The PR fixes #15116, but the new ==-only filter in isMapFind() also removes valid stlFindInsert warnings. When a count() result is compared with != or < and the condition really means "not present", the insertion is still unconditional and the warning is correct. Two inputs lose a true positive:
if (s.count(x) != 1) s.insert(x);on astd::setif (m.count(x) < 1) m[x] = 1;
Both warn on base and are silent with the PR. The check should look at what the comparison means (key absent vs. key present), not only at the operator. I found no crashes. The removal of the warning in the added test was already raised by pfultz2, so I don't repeat it.
Testing
Builds and tests
- Built
cppcheckandtestrunnerinpr/, andcppcheckinbase/. Both built. ./testrunner TestStl: 122 tests, 0 failures.
Scratch test
scratch/t1.cpp:
#include <map>
#include <set>
void f3(std::map<int,int>& m, int x) {
if (m.count(x) < 1) { m[x] = 1; }
}
void f9(std::set<int>& s, int x) {
if (s.count(x) != 1) { s.insert(x); }
}
void f4(std::map<int,int>& m, int x) {
if (m.count(x) != 0) { m[x] = 1; } // the #15116 case
}
void f6(std::map<int,int>& m, int x) {
if (m.count(x) == 0) { m[x] = 1; }
}Command: cppcheck -q --enable=performance --inconclusive --std=c++17 t1.cpp
| Function | base | PR |
|---|---|---|
f3 |
stlFindInsert |
no warning (lost true positive) |
f9 |
stlFindInsert |
no warning (lost true positive) |
f4 |
stlFindInsert |
no warning (intended fix) |
f6 |
stlFindInsert |
stlFindInsert |
In f3 and f9 the condition means "key absent", so the search before the insert is redundant, just like in f6, which still warns.
I also tried if/else versions where both branches assign the same value (find != end, count != 0, count == 1). Base warned on them and the PR does not. That code is unusual, and the suggested try_emplace would not be equivalent there, so I don't count it as a regression.
Automated review of 99b5261 by Claude. The pull request was built and tested locally.
| return {}; | ||
| if (!tok->astOperand2()) | ||
| return {}; | ||
| if (!Token::simpleMatch(tok->astParent(), "==")) |
There was a problem hiding this comment.
AI review
Requiring == is too narrow for count(), because the operator alone does not say whether the condition means "key absent". if (s.count(x) != 1) s.insert(x); on a std::set, and if (m.count(x) < 1) m[x] = 1;, both mean "absent". Base reported stlFindInsert for both, and with this PR neither warns: lost true positives.
The fix should check the meaning of the comparison: absent means == 0, != 1 (for a set), < 1 or <= 0. It should not filter on == only. A test for one of these cases would help too.
|
Test results for commit 99b5261 (tools/test-my-pr.py, main compared to this PR): Test: http://ec2-16-170-140-253.eu-north-1.compute.amazonaws.com/pr-8968/ 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. |
No description provided.