Symbol database: more function/variable cleanup. Ticket: #4494

This commit is contained in:
Robert Reif 2013-01-31 06:41:18 +01:00 committed by Daniel Marjamäki
parent fc42aa3a30
commit ec1c86c152
10 changed files with 80 additions and 20 deletions

View File

@ -230,7 +230,7 @@ bool CheckAutoVariables::returnTemporary(const Token *tok) const
bool retref = false; // is there such a function that returns a reference? bool retref = false; // is there such a function that returns a reference?
bool retvalue = false; // is there such a function that returns a value? bool retvalue = false; // is there such a function that returns a value?
const Function *function = symbolDatabase->findFunction(tok); const Function *function = tok->function();
if (function) { if (function) {
retref = function->tokenDef->strAt(-1) == "&"; retref = function->tokenDef->strAt(-1) == "&";
if (!retref) { if (!retref) {

View File

@ -625,7 +625,7 @@ void CheckBufferOverrun::checkFunctionParameter(const Token &tok, unsigned int p
// Calling a user function? // Calling a user function?
// only 1-dimensional arrays can be checked currently // only 1-dimensional arrays can be checked currently
else if (arrayInfo.num().size() == 1) { else if (arrayInfo.num().size() == 1) {
const Function* func = _tokenizer->getSymbolDatabase()->findFunction(&tok); const Function* func = tok.function();
if (func && func->hasBody) { if (func && func->hasBody) {
// Get corresponding parameter.. // Get corresponding parameter..
@ -695,7 +695,7 @@ void CheckBufferOverrun::checkFunctionParameter(const Token &tok, unsigned int p
// Check 'float x[10]' arguments in declaration // Check 'float x[10]' arguments in declaration
if (_settings->isEnabled("style")) { if (_settings->isEnabled("style")) {
const Function* func = _tokenizer->getSymbolDatabase()->findFunction(&tok); const Function* func = tok.function();
// If argument is '%type% a[num]' then check bounds against num // If argument is '%type% a[num]' then check bounds against num
if (func) { if (func) {

View File

@ -219,7 +219,7 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getAllocationType(const Token *tok2,
tok2 = tok2->tokAt(2); tok2 = tok2->tokAt(2);
// User function // User function
const Function* func = tokenizer->getSymbolDatabase()->findFunction(tok2); const Function* func = tok2->function();
if (func == NULL) if (func == NULL)
return No; return No;
@ -643,7 +643,7 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<co
// lock/unlock.. // lock/unlock..
if (varid == 0) { if (varid == 0) {
const Function* func = _tokenizer->getSymbolDatabase()->findFunction(tok); const Function* func = tok->function();
if (!func || !func->hasBody) if (!func || !func->hasBody)
return 0; return 0;
@ -689,7 +689,7 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<co
if (dot) if (dot)
return "use"; return "use";
const Function* function = _tokenizer->getSymbolDatabase()->findFunction(functok); const Function* function = functok->function();
if (!function) if (!function)
return "use"; return "use";
@ -721,7 +721,7 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<co
return ret; return ret;
} }
if (varid > 0 && Token::Match(tok, "& %varid% [,()]", varid)) { if (varid > 0 && Token::Match(tok, "& %varid% [,()]", varid)) {
const Function *func = _tokenizer->getSymbolDatabase()->findFunction(functok); const Function *func = functok->function();
if (func == 0) if (func == 0)
continue; continue;
AllocType a; AllocType a;

View File

@ -450,7 +450,7 @@ bool CheckNullPointer::CanFunctionAssignPointer(const Token *functiontoken, unsi
unsigned int argumentNumber = 0; unsigned int argumentNumber = 0;
for (const Token *arg = functiontoken->tokAt(2); arg; arg = arg->nextArgument()) { for (const Token *arg = functiontoken->tokAt(2); arg; arg = arg->nextArgument()) {
if (Token::Match(arg, "%varid% [,)]", varid)) { if (Token::Match(arg, "%varid% [,)]", varid)) {
const Function* func = _tokenizer->getSymbolDatabase()->findFunction(functiontoken); const Function* func = functiontoken->function();
if (!func) { // Unknown function if (!func) { // Unknown function
unknown = true; unknown = true;
return true; // assume that the function might assign the pointer return true; // assume that the function might assign the pointer

View File

@ -753,7 +753,7 @@ void CheckOther::checkRedundantAssignment()
} }
} }
} else if (scope->type == Scope::eSwitch) { // Avoid false positives if noreturn function is called in switch } else if (scope->type == Scope::eSwitch) { // Avoid false positives if noreturn function is called in switch
const Function* func = symbolDatabase->findFunction(tok); const Function* func = tok->function();
if (!func || !func->hasBody) { if (!func || !func->hasBody) {
varAssignments.clear(); varAssignments.clear();
memAssignments.clear(); memAssignments.clear();
@ -2379,7 +2379,7 @@ void CheckOther::checkMisusedScopedObject()
if (Token::Match(tok, "[;{}] %var% (") if (Token::Match(tok, "[;{}] %var% (")
&& Token::simpleMatch(tok->linkAt(2), ") ;") && Token::simpleMatch(tok->linkAt(2), ") ;")
&& symbolDatabase->isClassOrStruct(tok->next()->str()) && symbolDatabase->isClassOrStruct(tok->next()->str())
&& !symbolDatabase->findFunction(tok->next())) { && !tok->next()->function()) {
tok = tok->next(); tok = tok->next();
misusedScopeObjectError(tok, tok->str()); misusedScopeObjectError(tok, tok->str());
tok = tok->next(); tok = tok->next();
@ -2422,7 +2422,7 @@ void CheckOther::checkComparisonOfFuncReturningBool()
first_token = tok->previous(); first_token = tok->previous();
} }
if (Token::Match(first_token, "%var% (") && !Token::Match(first_token->previous(), "::|.")) { if (Token::Match(first_token, "%var% (") && !Token::Match(first_token->previous(), "::|.")) {
const Function* func = symbolDatabase->findFunction(first_token); const Function* func = first_token->function();
if (func && func->tokenDef && func->tokenDef->strAt(-1) == "bool") { if (func && func->tokenDef && func->tokenDef->strAt(-1) == "bool") {
first_token_func_of_type_bool = true; first_token_func_of_type_bool = true;
} }
@ -2434,7 +2434,7 @@ void CheckOther::checkComparisonOfFuncReturningBool()
second_token = second_token->next(); second_token = second_token->next();
} }
if (Token::Match(second_token, "%var% (") && !Token::Match(second_token->previous(), "::|.")) { if (Token::Match(second_token, "%var% (") && !Token::Match(second_token->previous(), "::|.")) {
const Function* func = symbolDatabase->findFunction(second_token); const Function* func = second_token->function();
if (func && func->tokenDef && func->tokenDef->strAt(-1) == "bool") { if (func && func->tokenDef && func->tokenDef->strAt(-1) == "bool") {
second_token_func_of_type_bool = true; second_token_func_of_type_bool = true;
} }
@ -3657,7 +3657,7 @@ void CheckOther::checkRedundantCopy()
const Token *match_end = (tok->next()->link()!=NULL)?tok->next()->link()->next():NULL; const Token *match_end = (tok->next()->link()!=NULL)?tok->next()->link()->next():NULL;
if (match_end==NULL || !Token::Match(match_end,expect_end_token)) //avoid usage like "const A a = getA()+3" if (match_end==NULL || !Token::Match(match_end,expect_end_token)) //avoid usage like "const A a = getA()+3"
break; break;
const Function* func = _tokenizer->getSymbolDatabase()->findFunction(tok); const Function* func = tok->function();
if (func && func->tokenDef->previous() && func->tokenDef->previous()->str() == "&") { if (func && func->tokenDef->previous() && func->tokenDef->previous()->str() == "&") {
redundantCopyError(var_tok,var_tok->str()); redundantCopyError(var_tok,var_tok->str());
} }
@ -3842,7 +3842,7 @@ void CheckOther::checkVarFuncNullUB()
ftok = ftok ? ftok->previous() : NULL; ftok = ftok ? ftok->previous() : NULL;
if (ftok && ftok->isName()) { if (ftok && ftok->isName()) {
// If this is a variadic function then report error // If this is a variadic function then report error
const Function *f = symbolDatabase->findFunction(ftok); const Function *f = ftok->function();
if (f && f->argCount() <= argnr) { if (f && f->argCount() <= argnr) {
const Token *tok2 = f->argDef; const Token *tok2 = f->argDef;
tok2 = tok2 ? tok2->link() : NULL; // goto ')' tok2 = tok2 ? tok2->link() : NULL; // goto ')'

View File

@ -1211,7 +1211,7 @@ void CheckStl::string_c_str()
Token::simpleMatch(tok->linkAt(4), ") . c_str ( ) ;")) { Token::simpleMatch(tok->linkAt(4), ") . c_str ( ) ;")) {
string_c_strError(tok); string_c_strError(tok);
} else if (Token::Match(tok, "return %var% (") && Token::simpleMatch(tok->linkAt(2), ") . c_str ( ) ;")) { } else if (Token::Match(tok, "return %var% (") && Token::simpleMatch(tok->linkAt(2), ") . c_str ( ) ;")) {
const Function* func =_tokenizer->getSymbolDatabase()->findFunction(tok->next()); const Function* func = tok->next()->function();
if (func && Token::Match(func->tokenDef->tokAt(-3), "std :: string|wstring")) if (func && Token::Match(func->tokenDef->tokAt(-3), "std :: string|wstring"))
string_c_strError(tok); string_c_strError(tok);
} else if (Token::simpleMatch(tok, "return (") && } else if (Token::simpleMatch(tok, "return (") &&

View File

@ -1485,7 +1485,7 @@ bool CheckUninitVar::isVariableUsage(const Token *vartok, bool pointer) const
// is this a function call? // is this a function call?
if (start && Token::Match(start->previous(), "%var% (")) { if (start && Token::Match(start->previous(), "%var% (")) {
// check how function handle uninitialized data arguments.. // check how function handle uninitialized data arguments..
const Function *func = _tokenizer->getSymbolDatabase()->findFunction(start->previous()); const Function *func = start->previous()->function();
if (func) { if (func) {
const Variable *arg = func->getArgumentVar(argumentNumber); const Variable *arg = func->getArgumentVar(argumentNumber);
if (arg) { if (arg) {

View File

@ -34,6 +34,8 @@ Token::Token(Token **t) :
_previous(0), _previous(0),
_link(0), _link(0),
_scope(0), _scope(0),
_function(0),
_variable(0),
_str(""), _str(""),
_varId(0), _varId(0),
_fileIndex(0), _fileIndex(0),
@ -198,6 +200,8 @@ void Token::deleteThis()
_linenr = _next->_linenr; _linenr = _next->_linenr;
_link = _next->_link; _link = _next->_link;
_scope = _next->_scope; _scope = _next->_scope;
_function = _next->_function;
_variable = _next->_variable;
if (_link) if (_link)
_link->link(this); _link->link(this);
@ -217,6 +221,8 @@ void Token::deleteThis()
_linenr = _previous->_linenr; _linenr = _previous->_linenr;
_link = _previous->_link; _link = _previous->_link;
_scope = _previous->_scope; _scope = _previous->_scope;
_function = _previous->_function;
_variable = _previous->_variable;
if (_link) if (_link)
_link->link(this); _link->link(this);

View File

@ -25,6 +25,8 @@
#include "config.h" #include "config.h"
class Scope; class Scope;
class Function;
class Variable;
/// @addtogroup Core /// @addtogroup Core
/// @{ /// @{
@ -439,17 +441,47 @@ public:
* Associate this token with given scope * Associate this token with given scope
* @param s Scope to be associated * @param s Scope to be associated
*/ */
void scope(Scope* s) { void scope(const Scope *s) {
_scope = s; _scope = s;
} }
/** /**
* Returns a pointer to the scope containing this token. * Returns a pointer to the scope containing this token.
*/ */
Scope* scope() const { const Scope *scope() const {
return _scope; return _scope;
} }
/**
* Associate this token with given function
* @param f Function to be associated
*/
void function(const Function *f) {
_function = f;
}
/**
* Returns a pointer to the Function associated with this token.
*/
const Function *function() const {
return _function;
}
/**
* Associate this token with given variable
* @param v Variable to be associated
*/
void variable(const Variable *v) {
_variable = v;
}
/**
* Returns a pointer to the variable associated with this token.
*/
const Variable *variable() const {
return _variable;
}
/** /**
* Links two elements against each other. * Links two elements against each other.
**/ **/
@ -541,7 +573,10 @@ private:
Token *_previous; Token *_previous;
Token *_link; Token *_link;
Scope* _scope; // symbol database information
const Scope *_scope;
const Function *_function;
const Variable *_variable;
std::string _str; std::string _str;
unsigned int _varId; unsigned int _varId;

View File

@ -9264,14 +9264,33 @@ void Tokenizer::createSymbolDatabase()
} }
} }
} }
// Set function pointers
const std::size_t functions = _symbolDatabase->functionScopes.size();
for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = _symbolDatabase->functionScopes[i];
for (Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "%var% (")) {
tok->function(_symbolDatabase->findFunction(tok));
}
}
}
// Set variable pointers
for (Token* tok = list.front(); tok != list.back(); tok = tok->next()) {
if (tok->varId())
tok->variable(_symbolDatabase->getVariableFromVarId(tok->varId()));
}
} }
} }
void Tokenizer::deleteSymbolDatabase() void Tokenizer::deleteSymbolDatabase()
{ {
// Clear scope pointers // Clear scope, function, and variable pointers
for (Token* tok = list.front(); tok != list.back(); tok = tok->next()) { for (Token* tok = list.front(); tok != list.back(); tok = tok->next()) {
tok->scope(0); tok->scope(0);
tok->function(0);
tok->variable(0);
} }
delete _symbolDatabase; delete _symbolDatabase;