diff --git a/lib/checkstl.cpp b/lib/checkstl.cpp index 263a9b6ee..93cb09aca 100644 --- a/lib/checkstl.cpp +++ b/lib/checkstl.cpp @@ -204,8 +204,19 @@ void CheckStl::erase() { if (Token::simpleMatch(tok, "for (")) { - for (const Token *tok2 = tok->tokAt(2); tok2 && tok2->str() != ";"; tok2 = tok2->next()) + for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next()) { + if (tok2->str() == ";") + { + if (Token::Match(tok2, "; %var% !=")) + { + const unsigned int varid = tok2->next()->varId(); + if (varid > 0 && Token::findmatch(_tokenizer->tokens(), "> :: iterator %varid%", varid)) + eraseCheckLoop(tok2->next()); + } + break; + } + if (Token::Match(tok2, "%var% = %var% . begin ( ) ; %var% != %var% . end ( ) ") && tok2->str() == tok2->tokAt(8)->str() && tok2->tokAt(2)->str() == tok2->tokAt(10)->str()) @@ -216,9 +227,11 @@ void CheckStl::erase() } } - if (Token::Match(tok, "while ( %var% != %var% . end ( )")) + if (Token::Match(tok, "while ( %var% !=")) { - eraseCheckLoop(tok->tokAt(2)); + const unsigned int varid = tok->tokAt(2)->varId(); + if (varid > 0 && Token::findmatch(_tokenizer->tokens(), "> :: iterator %varid%", varid)) + eraseCheckLoop(tok->tokAt(2)); } } } diff --git a/test/teststl.cpp b/test/teststl.cpp index 268224d23..9b09b52be 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -50,6 +50,7 @@ private: TEST_CASE(erase); TEST_CASE(erase2); TEST_CASE(erase3); + TEST_CASE(erase4); TEST_CASE(eraseBreak); TEST_CASE(eraseReturn); TEST_CASE(eraseGoto); @@ -376,6 +377,39 @@ private: ASSERT_EQUALS("", errout.str()); } + void erase4() + { + check("void f()\n" + "{\n" + " std::list::iterator it, it2;\n" + " for (it = foo.begin(); it != i2; ++it)\n" + " {\n" + " foo.erase(it);\n" + " }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:6]: (error) Dangerous iterator usage. After erase the iterator is invalid so dereferencing it or comparing it with another iterator is invalid.\n", errout.str()); + + check("void f()\n" + "{\n" + " std::list::iterator it = foo.begin();\n" + " for (; it != i2; ++it)\n" + " {\n" + " foo.erase(it);\n" + " }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:6]: (error) Dangerous iterator usage. After erase the iterator is invalid so dereferencing it or comparing it with another iterator is invalid.\n", errout.str()); + + check("void f()\n" + "{\n" + " std::list::iterator it = foo.begin();\n" + " while (it != i2)\n" + " {\n" + " foo.erase(it);\n" + " }\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:6]: (error) Dangerous iterator usage. After erase the iterator is invalid so dereferencing it or comparing it with another iterator is invalid.\n", errout.str()); + } + void eraseBreak() { check("void f()\n"