Added support for different containers, while-loops and if to CheckStl::stlOutOfBounds()
This commit is contained in:
parent
b3a2b69120
commit
0f03995995
|
@ -282,30 +282,36 @@ void CheckStl::stlOutOfBounds()
|
|||
|
||||
// Scan through all scopes..
|
||||
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
|
||||
const Token* const tok = i->classDef;
|
||||
// only interested in "for" loops
|
||||
if (i->type != Scope::eFor || !tok)
|
||||
const Token* tok = i->classDef;
|
||||
// only interested in conditions
|
||||
if ((i->type != Scope::eFor && i->type != Scope::eWhile && i->type != Scope::eIf && i->type != Scope::eElseIf) || !tok)
|
||||
continue;
|
||||
|
||||
if (i->type == Scope::eElseIf)
|
||||
tok = tok->tokAt(2);
|
||||
else if (i->type == Scope::eFor)
|
||||
tok = Token::findsimplematch(tok->tokAt(2), ";");
|
||||
else
|
||||
tok = tok->next();
|
||||
|
||||
// check if the for loop condition is wrong
|
||||
for (const Token *tok2 = tok->tokAt(2); tok2 && tok2 != tok->next()->link(); tok2 = tok2->next()) {
|
||||
if (Token::Match(tok2, "; %var% <= %var% . size ( ) ;")) {
|
||||
if (Token::Match(tok, ";|( %var% <= %var% . size|length ( ) ;|)|%oror%")) {
|
||||
// Is it a vector?
|
||||
const Variable *container = tok2->tokAt(3)->variable();
|
||||
const Variable *container = tok->tokAt(3)->variable();
|
||||
if (!container)
|
||||
continue;
|
||||
if (!Token::simpleMatch(container->typeStartToken(), "std :: vector <"))
|
||||
if (!Token::Match(container->typeStartToken(), "std :: vector|deque|array|string|wstring|basic_string"))
|
||||
continue;
|
||||
|
||||
// variable id for loop variable.
|
||||
unsigned int numId = tok2->next()->varId();
|
||||
unsigned int numId = tok->next()->varId();
|
||||
|
||||
// variable id for the container variable
|
||||
unsigned int varId = tok2->tokAt(3)->varId();
|
||||
unsigned int varId = container->varId();
|
||||
|
||||
for (const Token *tok3 = tok2->tokAt(8); tok3 && tok3 != i->classEnd; tok3 = tok3->next()) {
|
||||
for (const Token *tok3 = tok->tokAt(8); tok3 && tok3 != i->classEnd; tok3 = tok3->next()) {
|
||||
if (tok3->varId() == varId) {
|
||||
if (Token::simpleMatch(tok3->next(), ". size ( )"))
|
||||
if (Token::Match(tok3->next(), ". size|length ( )"))
|
||||
break;
|
||||
else if (Token::Match(tok3->next(), "[ %varid% ]", numId))
|
||||
stlOutOfBoundsError(tok3, tok3->strAt(2), tok3->str(), false);
|
||||
|
@ -316,7 +322,6 @@ void CheckStl::stlOutOfBounds()
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Error message for bad iterator usage..
|
||||
|
|
|
@ -506,6 +506,28 @@ private:
|
|||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) When ii==foo.size(), foo.at(ii) is out of bounds.\n", errout.str());
|
||||
|
||||
check("void foo(const std::string& foo) {\n"
|
||||
" for (unsigned int ii = 0; ii <= foo.length(); ++ii) {\n"
|
||||
" foo[ii] = 'x';\n"
|
||||
" }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) When ii==foo.size(), foo[ii] is out of bounds.\n", errout.str());
|
||||
|
||||
check("void foo(const std::string& foo, unsigned int ii) {\n"
|
||||
" if (ii <= foo.length()) {\n"
|
||||
" foo[ii] = 'x';\n"
|
||||
" }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (error) When ii==foo.size(), foo[ii] is out of bounds.\n", errout.str());
|
||||
|
||||
check("void foo(const std::string& foo, unsigned int ii) {\n"
|
||||
" if (anything()) {\n"
|
||||
" } else if (ii <= foo.length()) {\n"
|
||||
" foo[ii] = 'x';\n"
|
||||
" }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("[test.cpp:4]: (error) When ii==foo.size(), foo[ii] is out of bounds.\n", errout.str());
|
||||
|
||||
check("void foo()\n"
|
||||
"{\n"
|
||||
" std::vector<int> foo;\n"
|
||||
|
|
Loading…
Reference in New Issue