stl: Fixed ticket #277 - dereferencing an iterator that has been erased
This commit is contained in:
parent
6a009f7084
commit
3819c66f36
|
@ -35,18 +35,24 @@ void CheckStl::iteratorsError(const Token *tok, const std::string &container1, c
|
|||
reportError(tok, "error", "iterators", "Same iterator is used with both " + container1 + " and " + container2);
|
||||
}
|
||||
|
||||
// Error message used when dereferencing an iterator that has been erased..
|
||||
void CheckStl::dereferenceErasedError(const Token *tok, const std::string &itername)
|
||||
{
|
||||
reportError(tok, "error", "eraseDereference", "Dereferenced iterator '" + itername + "' has been erased");
|
||||
}
|
||||
|
||||
void CheckStl::iterators()
|
||||
{
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
if (Token::Match(tok, "%var% = %var% . begin ( ) ;"))
|
||||
if (Token::Match(tok, "%var% = %var% . begin ( ) ;|+"))
|
||||
{
|
||||
const unsigned int iteratorId(tok->varId());
|
||||
const unsigned int containerId(tok->tokAt(2)->varId());
|
||||
if (iteratorId == 0 || containerId == 0)
|
||||
continue;
|
||||
|
||||
bool validIterator = true;
|
||||
for (const Token *tok2 = tok->tokAt(6); tok2; tok2 = tok2->next())
|
||||
{
|
||||
if (tok2->str() == "}")
|
||||
|
@ -60,6 +66,12 @@ void CheckStl::iterators()
|
|||
{
|
||||
if (tok2->varId() != containerId)
|
||||
iteratorsError(tok2, tok->strAt(2), tok2->str());
|
||||
else if (tok2->strAt(2) == std::string("erase"))
|
||||
validIterator = false;
|
||||
}
|
||||
else if (!validIterator && tok2->Match(tok2, "* %varid%", iteratorId))
|
||||
{
|
||||
dereferenceErasedError(tok2, tok2->strAt(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,6 +63,9 @@ public:
|
|||
*/
|
||||
void iterators();
|
||||
|
||||
/** Dereferencing an erased iterator */
|
||||
void dereferenceErasedError(const Token *tok, const std::string &itername);
|
||||
|
||||
/**
|
||||
* Dangerous usage of erase
|
||||
*/
|
||||
|
@ -97,6 +100,7 @@ private:
|
|||
void getErrorMessages()
|
||||
{
|
||||
iteratorsError(0, "container1", "container2");
|
||||
dereferenceErasedError(0, "iter");
|
||||
stlOutOfBoundsError(0, "i", "foo");
|
||||
eraseError(0);
|
||||
pushbackError(0, "iterator");
|
||||
|
|
|
@ -39,6 +39,8 @@ private:
|
|||
TEST_CASE(iterator2);
|
||||
TEST_CASE(iterator3);
|
||||
|
||||
TEST_CASE(dereference);
|
||||
|
||||
TEST_CASE(STLSize);
|
||||
TEST_CASE(STLSizeNoErr);
|
||||
TEST_CASE(erase);
|
||||
|
@ -46,7 +48,6 @@ private:
|
|||
TEST_CASE(eraseReturn);
|
||||
TEST_CASE(eraseGoto);
|
||||
TEST_CASE(eraseAssign);
|
||||
TEST_CASE(eraseDereference);
|
||||
TEST_CASE(eraseErase);
|
||||
|
||||
TEST_CASE(pushback1);
|
||||
|
@ -118,6 +119,22 @@ private:
|
|||
}
|
||||
|
||||
|
||||
// Dereferencing invalid pointer
|
||||
void dereference()
|
||||
{
|
||||
check("void f()\n"
|
||||
"{\n"
|
||||
" std::vector<int> ints;"
|
||||
" std::vector<int>::iterator iter;\n"
|
||||
" iter = ints.begin() + 2;\n"
|
||||
" ints.erase(iter);\n"
|
||||
" std::cout << (*iter) << std::endl;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:6]: (error) Dereferenced iterator 'iter' has been erased\n", errout.str());
|
||||
}
|
||||
|
||||
|
||||
|
||||
void STLSize()
|
||||
{
|
||||
check("void foo()\n"
|
||||
|
@ -258,20 +275,6 @@ private:
|
|||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void eraseDereference()
|
||||
{
|
||||
check("void f(std::vector<ints> &ints)\n"
|
||||
"{\n"
|
||||
" std::vector<int>::iterator iter;\n"
|
||||
" iter = ints.begin() + 2;\n"
|
||||
" ints.erase(iter);\n"
|
||||
" std::cout << (*iter) << std::endl;\n"
|
||||
"}\n");
|
||||
|
||||
// Ticket #277 - STL: Dereferencing an erased iterator
|
||||
TODO_ASSERT_EQUALS("[test.cpp:6]: (error) Dereferencing invalid iterator\n", errout.str());
|
||||
}
|
||||
|
||||
void eraseErase()
|
||||
{
|
||||
check("void f(std::vector<ints> &ints)\n"
|
||||
|
|
Loading…
Reference in New Issue