add support for checking struct/class member container in CheckStl::size()
This commit is contained in:
parent
b95e9c110c
commit
1aca09a8bf
|
@ -804,13 +804,13 @@ void CheckStl::if_findError(const Token *tok, bool str)
|
|||
|
||||
|
||||
|
||||
bool CheckStl::isStlContainer(const Token *tok)
|
||||
bool CheckStl::isStlContainer(unsigned int varid)
|
||||
{
|
||||
// check if this token is defined
|
||||
if (tok->varId())
|
||||
if (varid)
|
||||
{
|
||||
// find where this token is defined
|
||||
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok->varId());
|
||||
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(varid);
|
||||
|
||||
if (!var)
|
||||
return false;
|
||||
|
@ -847,23 +847,60 @@ void CheckStl::size()
|
|||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next())
|
||||
{
|
||||
if (Token::Match(tok, "%var% . size ( )"))
|
||||
if (Token::Match(tok, "%var% . size ( )") ||
|
||||
Token::Match(tok, "%var% . %var% . size ( )"))
|
||||
{
|
||||
// check for comparison to zero
|
||||
if (Token::Match(tok->tokAt(5), "==|!=|> 0") ||
|
||||
Token::Match(tok->tokAt(-2), "0 ==|!=|<"))
|
||||
{
|
||||
if (isStlContainer(tok))
|
||||
sizeError(tok);
|
||||
}
|
||||
int offset = 5;
|
||||
const Token *tok1 = tok;
|
||||
unsigned int varid = 0;
|
||||
|
||||
// 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) == ")")
|
||||
// get the variable id
|
||||
if (tok->strAt(2) != "size")
|
||||
{
|
||||
if (isStlContainer(tok))
|
||||
sizeError(tok);
|
||||
offset = 7;
|
||||
tok1 = tok1->tokAt(2);
|
||||
|
||||
// found a.b.size(), lookup class/struct variable
|
||||
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok->varId());
|
||||
if (var && var->type())
|
||||
{
|
||||
// get class/struct variable type
|
||||
const Scope *type = var->type();
|
||||
|
||||
// lookup variable member
|
||||
std::list<Variable>::const_iterator it;
|
||||
for (it = type->varlist.begin(); it != type->varlist.end(); ++it)
|
||||
{
|
||||
if (it->name() == tok1->str())
|
||||
{
|
||||
// found member variable, save varid
|
||||
varid = it->varId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
varid = tok1->varId();
|
||||
|
||||
if (varid)
|
||||
{
|
||||
// check for comparison to zero
|
||||
if (Token::Match(tok->tokAt(offset), "==|!=|> 0") ||
|
||||
Token::Match(tok->tokAt(-2), "0 ==|!=|<"))
|
||||
{
|
||||
if (isStlContainer(varid))
|
||||
sizeError(tok1);
|
||||
}
|
||||
|
||||
// check for using as boolean expression
|
||||
else if ((Token::Match(tok->tokAt(-2), "if|while (") ||
|
||||
Token::Match(tok->tokAt(-3), "if|while ( !")) &&
|
||||
tok->strAt(offset) == ")")
|
||||
{
|
||||
if (isStlContainer(varid))
|
||||
sizeError(tok1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -192,7 +192,7 @@ private:
|
|||
"* common mistakes when using string::c_str()";
|
||||
}
|
||||
|
||||
bool isStlContainer(const Token *tok);
|
||||
bool isStlContainer(unsigned int varid);
|
||||
};
|
||||
/// @}
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
|
@ -90,6 +90,7 @@ private:
|
|||
TEST_CASE(if_str_find);
|
||||
|
||||
TEST_CASE(size1);
|
||||
TEST_CASE(size2);
|
||||
|
||||
// Redundant conditions..
|
||||
// if (ints.find(123) != ints.end()) ints.remove(123);
|
||||
|
@ -1162,6 +1163,22 @@ private:
|
|||
ASSERT_EQUALS("[test.cpp:3]: (style) Redundant checking of STL container element.\n", errout.str());
|
||||
}
|
||||
|
||||
void size2()
|
||||
{
|
||||
check("struct Fred {\n"
|
||||
" std::list<int> x;\n"
|
||||
"};\n"
|
||||
"struct Wilma {\n"
|
||||
" Fred f;\n"
|
||||
" void foo();\n"
|
||||
"};\n"
|
||||
"void Wilma::foo()\n"
|
||||
"{\n"
|
||||
" if (f.x.size() == 0) {}\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("[test.cpp:10]: (performance) Possible inefficient checking for 'x' emptiness.\n", errout.str());
|
||||
}
|
||||
|
||||
void redundantCondition2()
|
||||
{
|
||||
check("void f()\n"
|
||||
|
|
Loading…
Reference in New Issue