Skip to content

Commit eb288ec

Browse files
committed
CheckStl: Use AST to handle iterator comparisons better
1 parent a3916c5 commit eb288ec

2 files changed

Lines changed: 27 additions & 4 deletions

File tree

lib/checkstl.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,15 @@ void CheckStl::iterators()
140140
validIterator = true;
141141

142142
// Is iterator compared against different container?
143-
if (Token::Match(tok2, "%varid% !=|== %name% . end|rend|cend|crend ( )", iteratorId) && container && tok2->tokAt(2)->varId() != container->declarationId()) {
144-
iteratorsError(tok2, container->name(), tok2->strAt(2));
145-
tok2 = tok2->tokAt(6);
143+
if (tok2->isComparisonOp() && container) {
144+
const Token *other = nullptr;
145+
if (tok2->astOperand1()->varId() == iteratorId)
146+
other = tok2->astOperand2()->tokAt(-3);
147+
else if (tok2->astOperand2()->varId() == iteratorId)
148+
other = tok2->astOperand1()->tokAt(-3);
149+
150+
if (Token::Match(other, "%name% . end|rend|cend|crend ( )") && other->varId() != container->declarationId())
151+
iteratorsError(tok2, container->name(), other->str());
146152
}
147153

148154
// Is the iterator used in a insert/erase operation?

test/teststl.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,6 +172,15 @@ class TestStl : public TestFixture {
172172
"}");
173173
ASSERT_EQUALS("[test.cpp:5]: (error) Same iterator is used with different containers 'l1' and 'l2'.\n", errout.str());
174174

175+
check("void f()\n"
176+
"{\n"
177+
" list<int> l1;\n"
178+
" list<int> l2;\n"
179+
" for (list<int>::iterator it = l1.begin(); l2.end() != it; ++it)\n"
180+
" { }\n"
181+
"}");
182+
ASSERT_EQUALS("[test.cpp:5]: (error) Same iterator is used with different containers 'l1' and 'l2'.\n", errout.str());
183+
175184
// Same check with reverse iterator
176185
check("void f()\n"
177186
"{\n"
@@ -442,6 +451,14 @@ class TestStl : public TestFixture {
442451
"}");
443452
ASSERT_EQUALS("[test.cpp:5]: (error) Same iterator is used with different containers 'map1' and 'map2'.\n", errout.str());
444453

454+
check("void f() {\n"
455+
" std::map<int, int> map1;\n"
456+
" std::map<int, int> map2;\n"
457+
" std::map<int, int>::const_iterator it = map1.find(123);\n"
458+
" if (map2.end() == it) { }"
459+
"}");
460+
ASSERT_EQUALS("[test.cpp:5]: (error) Same iterator is used with different containers 'map1' and 'map2'.\n", errout.str());
461+
445462
check("void f(std::string &s) {\n"
446463
" int pos = s.find(x);\n"
447464
" s.erase(pos);\n"
@@ -457,7 +474,7 @@ class TestStl : public TestFixture {
457474
" std::vector<int>::const_iterator it;\n"
458475
" it = a.begin();\n"
459476
" while (it!=a.end())\n"
460-
" v++it;\n"
477+
" ++it;\n"
461478
" it = t.begin();\n"
462479
" while (it!=a.end())\n"
463480
" ++it;\n"

0 commit comments

Comments
 (0)