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 (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..
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue