CheckStl: Use Token::variable. ticket: #4535
This commit is contained in:
parent
b531195e08
commit
3e3b728a9c
115
lib/checkstl.cpp
115
lib/checkstl.cpp
|
@ -117,7 +117,7 @@ void CheckStl::iterators()
|
|||
// report an error
|
||||
if (container && tok2->varId() != container->varId()) {
|
||||
// skip error message if container is a set..
|
||||
const Variable *variableInfo = symbolDatabase->getVariableFromVarId(tok2->varId());
|
||||
const Variable *variableInfo = tok2->variable();
|
||||
const Token *decltok = variableInfo ? variableInfo->typeStartToken() : NULL;
|
||||
|
||||
if (Token::simpleMatch(decltok, "std :: set"))
|
||||
|
@ -153,7 +153,7 @@ void CheckStl::iterators()
|
|||
// Reassign the iterator
|
||||
else if (Token::Match(tok2, "%varid% = %var% . begin|rbegin|cbegin|crbegin|find (", iteratorId)) {
|
||||
validatingToken = tok2->linkAt(5);
|
||||
container = symbolDatabase->getVariableFromVarId(tok2->tokAt(2)->varId());
|
||||
container = tok2->tokAt(2)->variable();
|
||||
containerAssignScope = tok2->scope();
|
||||
|
||||
// skip ahead
|
||||
|
@ -290,19 +290,19 @@ void CheckStl::stlOutOfBounds()
|
|||
// 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 ( ) ;")) {
|
||||
// Is it a vector?
|
||||
const Variable *container = tok2->tokAt(3)->variable();
|
||||
if (!container)
|
||||
continue;
|
||||
if (!Token::simpleMatch(container->typeStartToken(), "std :: vector <"))
|
||||
continue;
|
||||
|
||||
// variable id for loop variable.
|
||||
unsigned int numId = tok2->next()->varId();
|
||||
|
||||
// variable id for the container variable
|
||||
unsigned int varId = tok2->tokAt(3)->varId();
|
||||
|
||||
// Is it a vector?
|
||||
const Variable *container = symbolDatabase->getVariableFromVarId(varId);
|
||||
if (!container)
|
||||
continue;
|
||||
if (!Token::simpleMatch(container->typeStartToken(), "std :: vector <"))
|
||||
continue;
|
||||
|
||||
for (const Token *tok3 = tok2->tokAt(8); tok3 && tok3 != i->classEnd; tok3 = tok3->next()) {
|
||||
if (tok3->varId() == varId) {
|
||||
if (Token::simpleMatch(tok3->next(), ". size ( )"))
|
||||
|
@ -480,7 +480,7 @@ void CheckStl::erase()
|
|||
if (tok2->str() == ";") {
|
||||
if (Token::Match(tok2, "; %var% !=")) {
|
||||
// Get declaration token for var..
|
||||
const Variable *variableInfo = symbolDatabase->getVariableFromVarId(tok2->next()->varId());
|
||||
const Variable *variableInfo = tok2->next()->variable();
|
||||
const Token *decltok = variableInfo ? variableInfo->typeEndToken() : NULL;
|
||||
|
||||
// Is variable an iterator?
|
||||
|
@ -801,11 +801,11 @@ void CheckStl::if_find()
|
|||
if (if_findCompare(tok->linkAt(3)))
|
||||
continue;
|
||||
|
||||
const unsigned int varid = tok->varId();
|
||||
const Variable *var = symbolDatabase->getVariableFromVarId(varid);
|
||||
const Variable *var = tok->variable();
|
||||
if (var) {
|
||||
// Is the variable a std::string or STL container?
|
||||
const Token * decl = var->typeStartToken();
|
||||
const unsigned int varid = tok->varId();
|
||||
|
||||
// stl container
|
||||
if (Token::Match(decl, "std :: %var% < %type% > &| %varid%", varid))
|
||||
|
@ -830,11 +830,11 @@ void CheckStl::if_find()
|
|||
if (if_findCompare(tok2->linkAt(2)))
|
||||
continue;
|
||||
|
||||
const unsigned int varid = tok->varId();
|
||||
const Variable *var = symbolDatabase->getVariableFromVarId(varid);
|
||||
const Variable *var = tok->variable();
|
||||
if (var) {
|
||||
// Is the variable a std::string or STL container?
|
||||
const Token * decl = var->typeStartToken();
|
||||
const unsigned int varid = tok->varId();
|
||||
|
||||
//pretty bad limitation.. but it is there in order to avoid
|
||||
//own implementations of 'find' or any container
|
||||
|
@ -895,30 +895,27 @@ void CheckStl::if_findError(const Token *tok, bool str)
|
|||
|
||||
|
||||
|
||||
bool CheckStl::isStlContainer(unsigned int varid)
|
||||
bool CheckStl::isStlContainer(const Token *tok) const
|
||||
{
|
||||
// check if this token is defined
|
||||
if (varid) {
|
||||
// find where this token is defined
|
||||
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(varid);
|
||||
// find where this token is defined
|
||||
const Variable *var = tok->variable();
|
||||
|
||||
if (!var)
|
||||
return false;
|
||||
if (!var)
|
||||
return false;
|
||||
|
||||
// find where this tokens type starts
|
||||
const Token *type = var->typeStartToken();
|
||||
// find where this tokens type starts
|
||||
const Token *type = var->typeStartToken();
|
||||
|
||||
// discard namespace if supplied
|
||||
if (Token::simpleMatch(type, "std ::"))
|
||||
type = type->tokAt(2);
|
||||
// discard namespace if supplied
|
||||
if (Token::simpleMatch(type, "std ::"))
|
||||
type = type->tokAt(2);
|
||||
|
||||
// all possible stl containers as a token
|
||||
static const char STL_CONTAINER_LIST[] = "array|bitset|deque|list|forward_list|map|multimap|multiset|priority_queue|queue|set|stack|vector|hash_map|hash_multimap|hash_set|unordered_map|unordered_multimap|unordered_set|unordered_multiset|basic_string";
|
||||
// all possible stl containers as a token
|
||||
static const char STL_CONTAINER_LIST[] = "array|bitset|deque|list|forward_list|map|multimap|multiset|priority_queue|queue|set|stack|vector|hash_map|hash_multimap|hash_set|unordered_map|unordered_multimap|unordered_set|unordered_multiset|basic_string";
|
||||
|
||||
// check if it's an stl template
|
||||
if (Token::Match(type, STL_CONTAINER_LIST))
|
||||
return true;
|
||||
}
|
||||
// check if it's an stl template
|
||||
if (Token::Match(type, STL_CONTAINER_LIST))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -936,52 +933,32 @@ void CheckStl::size()
|
|||
if (Token::Match(tok, "%var% . size ( )") ||
|
||||
Token::Match(tok, "%var% . %var% . size ( )")) {
|
||||
const Token *tok1 = tok;
|
||||
unsigned int varid = 0;
|
||||
|
||||
// get the variable id
|
||||
if (tok->strAt(2) != "size") {
|
||||
// get the variable
|
||||
if (tok->strAt(2) != "size")
|
||||
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();
|
||||
|
||||
const Token* const end = tok1->tokAt(5);
|
||||
|
||||
if (varid) {
|
||||
if (tok1->varId()) {
|
||||
// check for comparison to zero
|
||||
if ((tok->previous() && !tok->previous()->isArithmeticalOp() && Token::Match(end, "==|<=|!=|> 0")) ||
|
||||
(end->next() && !end->next()->isArithmeticalOp() && Token::Match(tok->tokAt(-2), "0 ==|>=|!=|<"))) {
|
||||
if (isStlContainer(varid))
|
||||
if (isStlContainer(tok1))
|
||||
sizeError(tok1);
|
||||
}
|
||||
|
||||
// check for comparison to one
|
||||
if ((tok->previous() && !tok->previous()->isArithmeticalOp() && Token::Match(end, ">=|< 1")) ||
|
||||
(end->next() && !end->next()->isArithmeticalOp() && Token::Match(tok->tokAt(-2), "1 <=|>"))) {
|
||||
if (isStlContainer(varid))
|
||||
if (isStlContainer(tok1))
|
||||
sizeError(tok1);
|
||||
}
|
||||
|
||||
// check for using as boolean expression
|
||||
else if ((Token::Match(tok->tokAt(-2), "if|while (") && end->str() == ")") ||
|
||||
(tok->previous()->type() == Token::eLogicalOp && Token::Match(end, "&&|)|,|;|%oror%"))) {
|
||||
if (isStlContainer(varid))
|
||||
if (isStlContainer(tok1))
|
||||
sizeError(tok1);
|
||||
}
|
||||
}
|
||||
|
@ -1116,9 +1093,9 @@ void CheckStl::missingComparisonError(const Token *incrementToken1, const Token
|
|||
}
|
||||
|
||||
|
||||
static bool isLocal(const SymbolDatabase* symbolDatabase, unsigned int varid)
|
||||
static bool isLocal(const Token *tok)
|
||||
{
|
||||
const Variable* var = symbolDatabase->getVariableFromVarId(varid);
|
||||
const Variable *var = tok->variable();
|
||||
return var && !var->isStatic() && var->isLocal();
|
||||
}
|
||||
|
||||
|
@ -1162,16 +1139,16 @@ void CheckStl::string_c_str()
|
|||
|
||||
for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) {
|
||||
// Invalid usage..
|
||||
if (Token::Match(tok, "throw %var% . c_str ( ) ;") && isLocal(symbolDatabase, tok->next()->varId())) {
|
||||
if (Token::Match(tok, "throw %var% . c_str ( ) ;") && isLocal(tok->next())) {
|
||||
string_c_strThrowError(tok);
|
||||
} else if (Token::Match(tok, "[;{}] %var% = %var% . str ( ) . c_str ( ) ;")) {
|
||||
const Variable* var = symbolDatabase->getVariableFromVarId(tok->next()->varId());
|
||||
const Variable* var = tok->next()->variable();
|
||||
if (var && var->isPointer())
|
||||
string_c_strError(tok);
|
||||
} else if (Token::Match(tok, "[;{}] %var% = %var% (") &&
|
||||
Token::simpleMatch(tok->linkAt(4), ") . c_str ( ) ;") &&
|
||||
Token::findmatch(_tokenizer->tokens(), ("std :: string|wstring " + tok->strAt(3) + " (").c_str())) {
|
||||
const Variable* var = symbolDatabase->getVariableFromVarId(tok->next()->varId());
|
||||
const Variable* var = tok->next()->variable();
|
||||
if (var && var->isPointer())
|
||||
string_c_strError(tok);
|
||||
} else if (Token::Match(tok, "%var% ( !!)") && c_strFuncParam.find(tok->str()) != c_strFuncParam.end() &&
|
||||
|
@ -1194,7 +1171,7 @@ void CheckStl::string_c_str()
|
|||
else
|
||||
tok2 = tok2->previous();
|
||||
if (tok2 && Token::simpleMatch(tok2->tokAt(-4), ". c_str ( )")) {
|
||||
const Variable* var = symbolDatabase->getVariableFromVarId(tok2->tokAt(-5)->varId());
|
||||
const Variable* var = tok2->tokAt(-5)->variable();
|
||||
if (var && Token::simpleMatch(var->typeStartToken(), "std ::"))
|
||||
string_c_strParam(tok, i->second);
|
||||
}
|
||||
|
@ -1203,9 +1180,9 @@ void CheckStl::string_c_str()
|
|||
|
||||
// Using c_str() to get the return value is only dangerous if the function returns a char*
|
||||
if (returnType == charPtr) {
|
||||
if (Token::Match(tok, "return %var% . c_str ( ) ;") && isLocal(symbolDatabase, tok->next()->varId())) {
|
||||
if (Token::Match(tok, "return %var% . c_str ( ) ;") && isLocal(tok->next())) {
|
||||
string_c_strError(tok);
|
||||
} else if (Token::Match(tok, "return %var% . str ( ) . c_str ( ) ;") && isLocal(symbolDatabase, tok->next()->varId())) {
|
||||
} else if (Token::Match(tok, "return %var% . str ( ) . c_str ( ) ;") && isLocal(tok->next())) {
|
||||
string_c_strError(tok);
|
||||
} else if (Token::Match(tok, "return std :: string|wstring (") &&
|
||||
Token::simpleMatch(tok->linkAt(4), ") . c_str ( ) ;")) {
|
||||
|
@ -1220,7 +1197,7 @@ void CheckStl::string_c_str()
|
|||
bool is_implicit_std_string = _settings->inconclusive;
|
||||
const Token *search_end = tok->next()->link();
|
||||
for (const Token *search_tok = tok->tokAt(2); search_tok != search_end; search_tok = search_tok->next()) {
|
||||
if (Token::Match(search_tok, "+ %var%") && isLocal(symbolDatabase, search_tok->next()->varId())) {
|
||||
if (Token::Match(search_tok, "+ %var%") && isLocal(search_tok->next())) {
|
||||
is_implicit_std_string = true;
|
||||
break;
|
||||
} else if (Token::Match(search_tok, "+ std :: string|wstring (")) {
|
||||
|
@ -1240,7 +1217,7 @@ void CheckStl::string_c_str()
|
|||
if (Token::simpleMatch(tok2->tokAt(-4), ". c_str ( )")) {
|
||||
tok2 = tok2->tokAt(-5);
|
||||
if (tok2->isName()) { // return var.c_str(); => check if var is a std type
|
||||
const Variable* var = symbolDatabase->getVariableFromVarId(tok2->varId());
|
||||
const Variable *var = tok2->variable();
|
||||
if (var && Token::simpleMatch(var->typeStartToken(), "std ::"))
|
||||
string_c_strReturn(tok);
|
||||
} else {
|
||||
|
@ -1403,7 +1380,7 @@ void CheckStl::uselessCalls()
|
|||
if (Token::Match(tok->tokAt(3), "0| )"))
|
||||
uselessCallsSubstrError(tok, false);
|
||||
else if (tok->strAt(3) == "0" && tok->linkAt(2)->strAt(-1) == "npos") {
|
||||
if (!symbolDatabase->getVariableFromVarId(tok->linkAt(2)->previous()->varId())) // Make sure that its no variable
|
||||
if (!tok->linkAt(2)->previous()->variable()) // Make sure that its no variable
|
||||
uselessCallsSubstrError(tok, false);
|
||||
} else if (Token::simpleMatch(tok->linkAt(2)->tokAt(-2), ", 0 )"))
|
||||
uselessCallsSubstrError(tok, true);
|
||||
|
|
|
@ -226,7 +226,7 @@ private:
|
|||
"* useless calls of string and STL functions\n";
|
||||
}
|
||||
|
||||
bool isStlContainer(unsigned int varid);
|
||||
bool isStlContainer(const Token *tok) const;
|
||||
};
|
||||
/// @}
|
||||
//---------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue