Fixed #4850 (False positive: invalidIterator1 detected when iterator container is member of some struct)

This commit is contained in:
Daniel Marjamäki 2013-10-26 17:48:20 +02:00
parent 853d9dd7a9
commit 8687e85e56
2 changed files with 26 additions and 1 deletions

View File

@ -57,6 +57,13 @@ void CheckStl::dereferenceErasedError(const Token *erased, const Token* deref, c
} }
} }
static const Token *skipMembers(const Token *tok)
{
while (Token::Match(tok, "%var% ."))
tok = tok->tokAt(2);
return tok;
}
void CheckStl::iterators() void CheckStl::iterators()
{ {
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
@ -152,7 +159,8 @@ void CheckStl::iterators()
// it = foo.erase(.. // it = foo.erase(..
// taking the result of an erase is ok // taking the result of an erase is ok
else if (Token::Match(tok2, "%varid% = %var% . erase (", iteratorId)) { else if (Token::Match(tok2, "%varid% = %var% .", iteratorId) &&
Token::simpleMatch(skipMembers(tok2->tokAt(2)), "erase (")) {
// the returned iterator is valid // the returned iterator is valid
validatingToken = tok2->linkAt(5); validatingToken = tok2->linkAt(5);
tok2 = tok2->tokAt(5); tok2 = tok2->tokAt(5);

View File

@ -67,6 +67,7 @@ private:
TEST_CASE(eraseAssign1); TEST_CASE(eraseAssign1);
TEST_CASE(eraseAssign2); TEST_CASE(eraseAssign2);
TEST_CASE(eraseAssign3); TEST_CASE(eraseAssign3);
TEST_CASE(eraseAssign4);
TEST_CASE(eraseAssignByFunctionCall); TEST_CASE(eraseAssignByFunctionCall);
TEST_CASE(eraseErase); TEST_CASE(eraseErase);
TEST_CASE(eraseByValue); TEST_CASE(eraseByValue);
@ -910,6 +911,22 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void eraseAssign4() {
check("void f(std::list<int> data) {\n"
" std::list<int>::const_iterator it = data.begin();\n"
" it = data.erase(it);\n"
" it = data.erase(it);\n"
"}");
ASSERT_EQUALS("", errout.str());
check("void f(Data data) {\n"
" std::list<int>::const_iterator it = data.ints.begin();\n"
" it = data.ints.erase(it);\n"
" it = data.ints.erase(it);\n"
"}");
ASSERT_EQUALS("", errout.str());
}
void eraseAssignByFunctionCall() { void eraseAssignByFunctionCall() {
check("void f(std::list<list<int> >& l) {\n" check("void f(std::list<list<int> >& l) {\n"
" std::list<foo>::const_iterator i;\n" " std::list<foo>::const_iterator i;\n"