Fixed #735 (Detects invalid iterator after push_back() when iterator declared inside for())

http://sourceforge.net/apps/trac/cppcheck/ticket/735
This commit is contained in:
Slava Semushin 2009-09-27 14:59:19 +07:00
parent acdbb20c99
commit 5285635354
2 changed files with 53 additions and 4 deletions

View File

@ -273,6 +273,14 @@ void CheckStl::pushback()
{ {
if (Token::simpleMatch(tok, "vector <")) if (Token::simpleMatch(tok, "vector <"))
{ {
// if iterator declaration inside for() loop
bool iteratorDeclaredInsideLoop = false;
if ((tok->tokAt(-2) && Token::simpleMatch(tok->tokAt(-2), "for (")) ||
(tok->tokAt(-4) && Token::simpleMatch(tok->tokAt(-4), "for ( std ::")))
{
iteratorDeclaredInsideLoop = true;
}
while (tok && tok->str() != ">") while (tok && tok->str() != ">")
tok = tok->next(); tok = tok->next();
if (!tok) if (!tok)
@ -283,6 +291,12 @@ void CheckStl::pushback()
if (iteratorid == 0) if (iteratorid == 0)
continue; continue;
if (iteratorDeclaredInsideLoop && tok->tokAt(4)->str() == "=")
{
// skip "> :: iterator|const_iterator"
tok = tok->tokAt(3);
}
std::string vectorname; std::string vectorname;
int indent = 0; int indent = 0;
bool invalidIterator = false; bool invalidIterator = false;
@ -299,15 +313,20 @@ void CheckStl::pushback()
} }
// Using push_back or push_front inside a loop.. // Using push_back or push_front inside a loop..
if (Token::Match(tok2, "for ( %varid% = %var% . begin ( ) ; %varid% != %var% . end ( ) ; ++ %varid% ) {", iteratorid)) if (Token::Match(tok2, "for ("))
{ {
const unsigned int vectorid(tok2->tokAt(4)->varId()); tok2 = tok2->tokAt(2);
}
if (Token::Match(tok2, "%varid% = %var% . begin ( ) ; %varid% != %var% . end ( ) ; ++ %varid% ) {", iteratorid))
{
const unsigned int vectorid(tok2->tokAt(2)->varId());
if (vectorid == 0) if (vectorid == 0)
continue; continue;
const Token *pushback = 0; const Token *pushback = 0;
unsigned int indent3 = 0; unsigned int indent3 = 0;
for (const Token *tok3 = tok2->tokAt(22); tok3; tok3 = tok3->next()) for (const Token *tok3 = tok2->tokAt(20); tok3; tok3 = tok3->next())
{ {
if (tok3->str() == "{") if (tok3->str() == "{")
++indent3; ++indent3;
@ -329,7 +348,7 @@ void CheckStl::pushback()
} }
if (pushback) if (pushback)
pushbackError(pushback, tok2->strAt(2)); pushbackError(pushback, tok2->strAt(0));
} }
// Assigning iterator.. // Assigning iterator..

View File

@ -56,6 +56,7 @@ private:
TEST_CASE(pushback3); TEST_CASE(pushback3);
TEST_CASE(pushback4); TEST_CASE(pushback4);
TEST_CASE(pushback5); TEST_CASE(pushback5);
TEST_CASE(pushback6);
TEST_CASE(insert1); TEST_CASE(insert1);
@ -390,6 +391,35 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void pushback6()
{
// ticket #735
check("void f()\n"
"{\n"
" vector<int> v;\n"
" vector.push_back(1);\n"
" vector.push_back(2);\n"
" for (vector<int>::iterator it = v.begin(); it != v.end(); ++it)\n"
" {\n"
" if (*it == 1)\n"
" v.push_back(10);\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:9]: (error) After push_back or push_front, the iterator 'it' may be invalid\n", errout.str());
check("void f()\n"
"{\n"
" std::vector<int> v;\n"
" vector.push_back(1);\n"
" vector.push_back(2);\n"
" for (std::vector<int>::iterator it = v.begin(); it != v.end(); ++it)\n"
" {\n"
" if (*it == 1)\n"
" v.push_back(10);\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:9]: (error) After push_back or push_front, the iterator 'it' may be invalid\n", errout.str());
}
void insert1() void insert1()