Fixed #1680 (Bad iterators checks fail to detect invalidation of iterator for deletion by value)
This commit is contained in:
parent
70d20ac544
commit
0510d9a2b0
|
@ -46,6 +46,11 @@ void CheckStl::dereferenceErasedError(const Token *tok, const std::string &itern
|
||||||
reportError(tok, Severity::error, "eraseDereference", "Dereferenced iterator '" + itername + "' has been erased");
|
reportError(tok, Severity::error, "eraseDereference", "Dereferenced iterator '" + itername + "' has been erased");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckStl::eraseByValueError(const Token *tok, const std::string &containername, const std::string &itername)
|
||||||
|
{
|
||||||
|
reportError(tok, Severity::error, "eraseByValue", "Iterator '" + itername + "' becomes invalid when deleted by value from '" + containername + "'");
|
||||||
|
}
|
||||||
|
|
||||||
void CheckStl::iterators()
|
void CheckStl::iterators()
|
||||||
{
|
{
|
||||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||||
|
@ -111,6 +116,10 @@ void CheckStl::iterators()
|
||||||
dereferenceErasedError(tok2, tok2->strAt(0));
|
dereferenceErasedError(tok2, tok2->strAt(0));
|
||||||
tok2 = tok2->tokAt(2);
|
tok2 = tok2->tokAt(2);
|
||||||
}
|
}
|
||||||
|
else if (Token::Match(tok2, "%var% . erase ( * %varid%", iteratorId) && tok2->varId() == containerId)
|
||||||
|
{
|
||||||
|
eraseByValueError(tok2, tok2->strAt(0), tok2->strAt(5));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,6 +124,7 @@ private:
|
||||||
void stlBoundriesError(const Token *tok, const std::string &container_name);
|
void stlBoundriesError(const Token *tok, const std::string &container_name);
|
||||||
void if_findError(const Token *tok, bool str);
|
void if_findError(const Token *tok, bool str);
|
||||||
void sizeError(const Token *tok);
|
void sizeError(const Token *tok);
|
||||||
|
void eraseByValueError(const Token *tok, const std::string &containername, const std::string &itername);
|
||||||
|
|
||||||
void getErrorMessages()
|
void getErrorMessages()
|
||||||
{
|
{
|
||||||
|
@ -139,6 +140,7 @@ private:
|
||||||
if_findError(0, false);
|
if_findError(0, false);
|
||||||
if_findError(0, true);
|
if_findError(0, true);
|
||||||
sizeError(0);
|
sizeError(0);
|
||||||
|
eraseByValueError(0, "container", "iterator");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string name() const
|
std::string name() const
|
||||||
|
|
|
@ -56,6 +56,7 @@ private:
|
||||||
TEST_CASE(eraseGoto);
|
TEST_CASE(eraseGoto);
|
||||||
TEST_CASE(eraseAssign);
|
TEST_CASE(eraseAssign);
|
||||||
TEST_CASE(eraseErase);
|
TEST_CASE(eraseErase);
|
||||||
|
TEST_CASE(eraseByValue);
|
||||||
|
|
||||||
TEST_CASE(pushback1);
|
TEST_CASE(pushback1);
|
||||||
TEST_CASE(pushback2);
|
TEST_CASE(pushback2);
|
||||||
|
@ -475,6 +476,18 @@ private:
|
||||||
ASSERT_EQUALS("[test.cpp:6]: (error) Invalid iterator: iter\n", errout.str());
|
ASSERT_EQUALS("[test.cpp:6]: (error) Invalid iterator: iter\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void eraseByValue()
|
||||||
|
{
|
||||||
|
check("void f()\n"
|
||||||
|
"{\n"
|
||||||
|
" std::set<int> foo;\n"
|
||||||
|
" for (std::set<int> it = foo.begin(); it != foo.end(); ++it)\n"
|
||||||
|
" {\n"
|
||||||
|
" foo.erase(*it);\n"
|
||||||
|
" }\n"
|
||||||
|
"}\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:6]: (error) Iterator 'it' becomes invalid when deleted by value from 'foo'\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void pushback1()
|
void pushback1()
|
||||||
|
|
Loading…
Reference in New Issue