convert CheckStl::size() to use symbol database, fix false positives, and remove inconclusive

This commit is contained in:
Robert Reif 2011-03-07 19:49:43 -05:00
parent 03bdd22ccf
commit e305a155af
2 changed files with 68 additions and 26 deletions

View File

@ -17,8 +17,8 @@
*/
#include "checkstl.h"
#include "token.h"
#include "executionpath.h"
#include "symboldatabase.h"
#include <sstream>
// Register this check class (by creating a static instance of it)
@ -799,11 +799,13 @@ bool CheckStl::isStlContainer(const Token *tok)
if (tok->varId())
{
// find where this token is defined
const Token *type = Token::findmatch(_tokenizer->tokens(), "%varid%", tok->varId());
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok->varId());
if (!var)
return false;
// find where this tokens type starts
while (type->previous() && !Token::Match(type->previous(), "[;{,(]"))
type = type->previous();
const Token *type = var->typeStartToken();
// ignore "const"
if (type->str() == "const")
@ -829,38 +831,27 @@ bool CheckStl::isStlContainer(const Token *tok)
void CheckStl::size()
{
if (!_settings->_checkCodingStyle || !_settings->inconclusive)
if (!_settings->_checkCodingStyle)
return;
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
{
if (Token::Match(tok, "%var% . size ( )"))
{
if (Token::Match(tok->tokAt(5), "==|!=|> 0"))
// check for comparison to zero
if (Token::Match(tok->tokAt(5), "==|!=|> 0") ||
Token::Match(tok->tokAt(-2), "0 ==|!=|<"))
{
if (isStlContainer(tok))
sizeError(tok);
}
else if ((tok->tokAt(5)->str() == ")" ||
tok->tokAt(5)->str() == "&&" ||
tok->tokAt(5)->str() == "||" ||
tok->tokAt(5)->str() == "!") &&
(tok->tokAt(-1)->str() == "(" ||
tok->tokAt(-1)->str() == "&&" ||
tok->tokAt(-1)->str() == "||" ||
tok->tokAt(-1)->str() == "!"))
// check for using as boolean expression
else if ((Token::Match(tok->tokAt(-2), "if|while (") ||
Token::Match(tok->tokAt(-3), "if|while ( !")) &&
tok->strAt(5) == ")")
{
if (tok->tokAt(-1)->str() == "(" &&
tok->tokAt(5)->str() == ")")
{
// check for passing size to function call
if (Token::Match(tok->tokAt(-2), "if|while"))
{
if (isStlContainer(tok))
sizeError(tok);
}
}
else if (isStlContainer(tok))
if (isStlContainer(tok))
sizeError(tok);
}
}

View File

@ -113,7 +113,6 @@ private:
errout.str("");
Settings settings;
settings.inconclusive = true;
settings._checkCodingStyle = true;
// Tokenize..
@ -1064,6 +1063,23 @@ private:
void size1()
{
check("struct Fred {\n"
" void foo();\n"
" std::list<int> x;\n"
"};\n"
"void Fred::foo()\n"
"{\n"
" if (x.size() == 0) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:7]: (performance) Possible inefficient checking for 'x' emptiness.\n", errout.str());
check("std::list<int> x;\n"
"void f()\n"
"{\n"
" if (x.size() == 0) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness.\n", errout.str());
check("void f()\n"
"{\n"
" std::list<int> x;\n"
@ -1071,6 +1087,13 @@ private:
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness.\n", errout.str());
check("void f()\n"
"{\n"
" std::list<int> x;\n"
" if (0 == x.size()) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness.\n", errout.str());
check("void f()\n"
"{\n"
" std::list<int> x;\n"
@ -1078,6 +1101,13 @@ private:
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness.\n", errout.str());
check("void f()\n"
"{\n"
" std::list<int> x;\n"
" if (0 != x.size()) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness.\n", errout.str());
check("void f()\n"
"{\n"
" std::list<int> x;\n"
@ -1085,6 +1115,13 @@ private:
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness.\n", errout.str());
check("void f()\n"
"{\n"
" std::list<int> x;\n"
" if (0 < x.size()) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness.\n", errout.str());
check("void f()\n"
"{\n"
" std::list<int> x;\n"
@ -1092,12 +1129,26 @@ private:
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness.\n", errout.str());
check("void f()\n"
"{\n"
" std::list<int> x;\n"
" if (!x.size()) {}\n"
"}\n");
ASSERT_EQUALS("[test.cpp:4]: (performance) Possible inefficient checking for 'x' emptiness.\n", errout.str());
check("void f()\n"
"{\n"
" std::list<int> x;\n"
" fun(x.size());\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("void f()\n"
"{\n"
" std::list<int> x;\n"
" fun(!x.size());\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void redundantCondition1()