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:
parent
acdbb20c99
commit
5285635354
|
@ -273,6 +273,14 @@ void CheckStl::pushback()
|
|||
{
|
||||
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() != ">")
|
||||
tok = tok->next();
|
||||
if (!tok)
|
||||
|
@ -283,6 +291,12 @@ void CheckStl::pushback()
|
|||
if (iteratorid == 0)
|
||||
continue;
|
||||
|
||||
if (iteratorDeclaredInsideLoop && tok->tokAt(4)->str() == "=")
|
||||
{
|
||||
// skip "> :: iterator|const_iterator"
|
||||
tok = tok->tokAt(3);
|
||||
}
|
||||
|
||||
std::string vectorname;
|
||||
int indent = 0;
|
||||
bool invalidIterator = false;
|
||||
|
@ -299,15 +313,20 @@ void CheckStl::pushback()
|
|||
}
|
||||
|
||||
// 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)
|
||||
continue;
|
||||
|
||||
const Token *pushback = 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() == "{")
|
||||
++indent3;
|
||||
|
@ -329,7 +348,7 @@ void CheckStl::pushback()
|
|||
}
|
||||
|
||||
if (pushback)
|
||||
pushbackError(pushback, tok2->strAt(2));
|
||||
pushbackError(pushback, tok2->strAt(0));
|
||||
}
|
||||
|
||||
// Assigning iterator..
|
||||
|
|
|
@ -56,6 +56,7 @@ private:
|
|||
TEST_CASE(pushback3);
|
||||
TEST_CASE(pushback4);
|
||||
TEST_CASE(pushback5);
|
||||
TEST_CASE(pushback6);
|
||||
|
||||
TEST_CASE(insert1);
|
||||
|
||||
|
@ -390,6 +391,35 @@ private:
|
|||
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()
|
||||
|
|
Loading…
Reference in New Issue