Simplify checks by caching symbol database Variable pointer in Token

This commit is contained in:
Robert Reif 2013-01-31 20:08:48 +01:00 committed by Daniel Marjamäki
parent e2faed355b
commit 94c953931d
5 changed files with 41 additions and 51 deletions

View File

@ -66,7 +66,7 @@ void Check64BitPortability::pointerassignment()
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) { for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "return %var% [;+]")) { if (Token::Match(tok, "return %var% [;+]")) {
const Variable *var = symbolDatabase->getVariableFromVarId(tok->next()->varId()); const Variable *var = tok->next()->variable();
if (retPointer && isint(var)) if (retPointer && isint(var))
returnIntegerError(tok); returnIntegerError(tok);
else if (!retPointer && isaddr(var)) else if (!retPointer && isaddr(var))
@ -81,8 +81,8 @@ void Check64BitPortability::pointerassignment()
for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) { for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "[;{}] %var% = %var% [;+]")) { if (Token::Match(tok, "[;{}] %var% = %var% [;+]")) {
const Variable *var1(symbolDatabase->getVariableFromVarId(tok->next()->varId())); const Variable *var1(tok->next()->variable());
const Variable *var2(symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId())); const Variable *var2(tok->tokAt(3)->variable());
if (isaddr(var1) && isint(var2) && tok->strAt(4) != "+") if (isaddr(var1) && isint(var2) && tok->strAt(4) != "+")
assignmentIntegerToAddressError(tok->next()); assignmentIntegerToAddressError(tok->next());

View File

@ -36,15 +36,13 @@ void CheckAssignIf::assignIf()
if (!_settings->isEnabled("style")) if (!_settings->isEnabled("style"))
return; return;
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
if (tok->str() != "=") if (tok->str() != "=")
continue; continue;
if (Token::Match(tok->tokAt(-2), "[;{}] %var% =")) { if (Token::Match(tok->tokAt(-2), "[;{}] %var% =")) {
const unsigned int varid(tok->previous()->varId()); const Variable *var = tok->previous()->variable();
if (varid == 0) if (var == 0)
continue; continue;
char bitop = '\0'; char bitop = '\0';
@ -67,12 +65,7 @@ void CheckAssignIf::assignIf()
if (num < 0 && bitop == '|') if (num < 0 && bitop == '|')
continue; continue;
bool islocal = false; assignIfParseScope(tok, tok->tokAt(4), var->varId(), var->isLocal(), bitop, num);
const Variable *var = symbolDatabase->getVariableFromVarId(varid);
if (var && var->isLocal())
islocal = true;
assignIfParseScope(tok, tok->tokAt(4), varid, islocal, bitop, num);
} }
} }
} }

View File

@ -35,23 +35,23 @@ namespace {
} }
bool CheckAutoVariables::isRefPtrArg(unsigned int varId) bool CheckAutoVariables::isRefPtrArg(const Token *tok)
{ {
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(varId); const Variable *var = tok->variable();
return(var && var->isArgument() && var->isReference() && var->isPointer()); return(var && var->isArgument() && var->isReference() && var->isPointer());
} }
bool CheckAutoVariables::isPtrArg(unsigned int varId) bool CheckAutoVariables::isPtrArg(const Token *tok)
{ {
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(varId); const Variable *var = tok->variable();
return(var && var->isArgument() && var->isPointer()); return(var && var->isArgument() && var->isPointer());
} }
bool CheckAutoVariables::isAutoVar(unsigned int varId) bool CheckAutoVariables::isAutoVar(const Token *tok)
{ {
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(varId); const Variable *var = tok->variable();
if (!var || !var->isLocal() || var->isStatic()) if (!var || !var->isLocal() || var->isStatic())
return false; return false;
@ -66,9 +66,9 @@ bool CheckAutoVariables::isAutoVar(unsigned int varId)
return true; return true;
} }
bool CheckAutoVariables::isAutoVarArray(unsigned int varId) bool CheckAutoVariables::isAutoVarArray(const Token *tok)
{ {
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(varId); const Variable *var = tok->variable();
return (var && var->isLocal() && !var->isStatic() && var->isArray()); return (var && var->isLocal() && !var->isStatic() && var->isArray());
} }
@ -88,21 +88,21 @@ void CheckAutoVariables::autoVariables()
const Scope * scope = symbolDatabase->functionScopes[i]; const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) { for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) {
// Critical assignment // Critical assignment
if (Token::Match(tok, "[;{}] %var% = & %var%") && isRefPtrArg(tok->next()->varId()) && isAutoVar(tok->tokAt(4)->varId())) { if (Token::Match(tok, "[;{}] %var% = & %var%") && isRefPtrArg(tok->next()) && isAutoVar(tok->tokAt(4))) {
const Variable * var = symbolDatabase->getVariableFromVarId(tok->tokAt(4)->varId()); const Variable * var = tok->tokAt(4)->variable();
if (checkRvalueExpression(var, tok->tokAt(5))) if (checkRvalueExpression(var, tok->tokAt(5)))
errorAutoVariableAssignment(tok->next(), false); errorAutoVariableAssignment(tok->next(), false);
} else if (Token::Match(tok, "[;{}] * %var% = & %var%") && isPtrArg(tok->tokAt(2)->varId()) && isAutoVar(tok->tokAt(5)->varId())) { } else if (Token::Match(tok, "[;{}] * %var% = & %var%") && isPtrArg(tok->tokAt(2)) && isAutoVar(tok->tokAt(5))) {
const Variable * var = symbolDatabase->getVariableFromVarId(tok->tokAt(5)->varId()); const Variable * var = tok->tokAt(5)->variable();
if (checkRvalueExpression(var, tok->tokAt(6))) if (checkRvalueExpression(var, tok->tokAt(6)))
errorAutoVariableAssignment(tok->next(), false); errorAutoVariableAssignment(tok->next(), false);
} else if (Token::Match(tok, "[;{}] %var% . %var% = & %var%")) { } else if (Token::Match(tok, "[;{}] %var% . %var% = & %var%")) {
// TODO: check if the parameter is only changed temporarily (#2969) // TODO: check if the parameter is only changed temporarily (#2969)
if (_settings->inconclusive) { if (_settings->inconclusive) {
const Variable * var1 = symbolDatabase->getVariableFromVarId(tok->next()->varId()); const Variable * var1 = tok->next()->variable();
if (var1 && var1->isArgument() && var1->isPointer()) { if (var1 && var1->isArgument() && var1->isPointer()) {
const Variable * var2 = symbolDatabase->getVariableFromVarId(tok->tokAt(6)->varId()); const Variable * var2 = tok->tokAt(6)->variable();
if (isAutoVar(tok->tokAt(6)->varId()) && checkRvalueExpression(var2, tok->tokAt(7))) if (isAutoVar(tok->tokAt(6)) && checkRvalueExpression(var2, tok->tokAt(7)))
errorAutoVariableAssignment(tok->next(), true); errorAutoVariableAssignment(tok->next(), true);
} }
} }
@ -110,42 +110,42 @@ void CheckAutoVariables::autoVariables()
} else if (Token::Match(tok, "[;{}] %var% . %var% = %var% ;")) { } else if (Token::Match(tok, "[;{}] %var% . %var% = %var% ;")) {
// TODO: check if the parameter is only changed temporarily (#2969) // TODO: check if the parameter is only changed temporarily (#2969)
if (_settings->inconclusive) { if (_settings->inconclusive) {
const Variable * var1 = symbolDatabase->getVariableFromVarId(tok->next()->varId()); const Variable * var1 = tok->next()->variable();
if (var1 && var1->isArgument() && var1->isPointer()) { if (var1 && var1->isArgument() && var1->isPointer()) {
if (isAutoVarArray(tok->tokAt(5)->varId())) if (isAutoVarArray(tok->tokAt(5)))
errorAutoVariableAssignment(tok->next(), true); errorAutoVariableAssignment(tok->next(), true);
} }
} }
tok = tok->tokAt(5); tok = tok->tokAt(5);
} else if (Token::Match(tok, "[;{}] * %var% = %var% ;")) { } else if (Token::Match(tok, "[;{}] * %var% = %var% ;")) {
const Variable * var1 = symbolDatabase->getVariableFromVarId(tok->tokAt(2)->varId()); const Variable * var1 = tok->tokAt(2)->variable();
if (var1 && var1->isArgument() && Token::Match(var1->nameToken()->tokAt(-3), "%type% * *")) { if (var1 && var1->isArgument() && Token::Match(var1->nameToken()->tokAt(-3), "%type% * *")) {
if (isAutoVarArray(tok->tokAt(4)->varId())) if (isAutoVarArray(tok->tokAt(4)))
errorAutoVariableAssignment(tok->next(), false); errorAutoVariableAssignment(tok->next(), false);
} }
tok = tok->tokAt(4); tok = tok->tokAt(4);
} else if (Token::Match(tok, "[;{}] %var% [") && Token::Match(tok->linkAt(2), "] = & %var%") && isPtrArg(tok->next()->varId()) && isAutoVar(tok->linkAt(2)->tokAt(3)->varId())) { } else if (Token::Match(tok, "[;{}] %var% [") && Token::Match(tok->linkAt(2), "] = & %var%") && isPtrArg(tok->next()) && isAutoVar(tok->linkAt(2)->tokAt(3))) {
const Token* const varTok = tok->linkAt(2)->tokAt(3); const Token* const varTok = tok->linkAt(2)->tokAt(3);
const Variable * var = symbolDatabase->getVariableFromVarId(varTok->varId()); const Variable * var = varTok->variable();
if (checkRvalueExpression(var, varTok->next())) if (checkRvalueExpression(var, varTok->next()))
errorAutoVariableAssignment(tok->next(), false); errorAutoVariableAssignment(tok->next(), false);
} }
// Critical return // Critical return
else if (Token::Match(tok, "return & %var% ;") && isAutoVar(tok->tokAt(2)->varId())) { else if (Token::Match(tok, "return & %var% ;") && isAutoVar(tok->tokAt(2))) {
errorReturnAddressToAutoVariable(tok); errorReturnAddressToAutoVariable(tok);
} else if (Token::Match(tok, "return & %var% [") && } else if (Token::Match(tok, "return & %var% [") &&
Token::simpleMatch(tok->linkAt(3), "] ;") && Token::simpleMatch(tok->linkAt(3), "] ;") &&
isAutoVarArray(tok->tokAt(2)->varId())) { isAutoVarArray(tok->tokAt(2))) {
errorReturnAddressToAutoVariable(tok); errorReturnAddressToAutoVariable(tok);
} else if (Token::Match(tok, "return & %var% ;") && tok->tokAt(2)->varId()) { } else if (Token::Match(tok, "return & %var% ;") && tok->tokAt(2)->varId()) {
const Variable * var1 = symbolDatabase->getVariableFromVarId(tok->tokAt(2)->varId()); const Variable * var1 = tok->tokAt(2)->variable();
if (var1 && var1->isArgument() && var1->typeEndToken()->str() != "&") if (var1 && var1->isArgument() && var1->typeEndToken()->str() != "&")
errorReturnAddressOfFunctionParameter(tok, tok->strAt(2)); errorReturnAddressOfFunctionParameter(tok, tok->strAt(2));
} }
// Invalid pointer deallocation // Invalid pointer deallocation
else if (Token::Match(tok, "free ( %var% ) ;") || Token::Match(tok, "delete [| ]| (| %var% !![")) { else if (Token::Match(tok, "free ( %var% ) ;") || Token::Match(tok, "delete [| ]| (| %var% !![")) {
tok = Token::findmatch(tok->next(), "%var%"); tok = Token::findmatch(tok->next(), "%var%");
if (isAutoVarArray(tok->varId())) if (isAutoVarArray(tok))
errorInvalidDeallocation(tok); errorInvalidDeallocation(tok);
} }
} }
@ -171,8 +171,7 @@ void CheckAutoVariables::returnPointerToLocalArray()
for (const Token *tok2 = scope->classStart->next(); tok2 && tok2 != scope->classEnd; tok2 = tok2->next()) { for (const Token *tok2 = scope->classStart->next(); tok2 && tok2 != scope->classEnd; tok2 = tok2->next()) {
// Return pointer to local array variable.. // Return pointer to local array variable..
if (Token::Match(tok2, "return %var% ;")) { if (Token::Match(tok2, "return %var% ;")) {
const unsigned int varid = tok2->next()->varId(); if (isAutoVarArray(tok2->next())) {
if (isAutoVarArray(varid)) {
errorReturnPointerToLocalArray(tok2); errorReturnPointerToLocalArray(tok2);
} }
} }
@ -285,10 +284,8 @@ void CheckAutoVariables::returnReference()
// return.. // return..
if (Token::Match(tok2, "return %var% ;")) { if (Token::Match(tok2, "return %var% ;")) {
// is the returned variable a local variable? // is the returned variable a local variable?
const unsigned int varid1 = tok2->next()->varId(); if (isAutoVar(tok2->next())) {
const Variable *var1 = symbolDatabase->getVariableFromVarId(varid1); const Variable *var1 = tok2->next()->variable();
if (isAutoVar(varid1)) {
// If reference variable is used, check what it references // If reference variable is used, check what it references
if (Token::Match(var1->nameToken(), "%var% [=(]")) { if (Token::Match(var1->nameToken(), "%var% [=(]")) {
const Token *tok3 = var1->nameToken()->tokAt(2); const Token *tok3 = var1->nameToken()->tokAt(2);
@ -297,7 +294,7 @@ void CheckAutoVariables::returnReference()
// Only report error if variable that is referenced is // Only report error if variable that is referenced is
// a auto variable // a auto variable
if (!isAutoVar(tok3->varId())) if (!isAutoVar(tok3))
continue; continue;
} }

View File

@ -63,10 +63,10 @@ public:
void returnReference(); void returnReference();
private: private:
bool isRefPtrArg(unsigned int varId); bool isRefPtrArg(const Token *tok);
bool isPtrArg(unsigned int varId); bool isPtrArg(const Token *tok);
bool isAutoVar(unsigned int varId); bool isAutoVar(const Token *tok);
bool isAutoVarArray(unsigned int varId); bool isAutoVarArray(const Token *tok);
/** /**
* Returning a temporary object? * Returning a temporary object?

View File

@ -1046,7 +1046,7 @@ void CheckBufferOverrun::checkScope(const Token *tok, const std::vector<std::str
} }
} else if ((varid > 0 && Token::Match(tok, "strcpy|strcat ( %varid% , %var% )", varid)) || } else if ((varid > 0 && Token::Match(tok, "strcpy|strcat ( %varid% , %var% )", varid)) ||
(varid == 0 && Token::Match(tok, ("strcpy|strcat ( " + varnames + " , %var% )").c_str()))) { (varid == 0 && Token::Match(tok, ("strcpy|strcat ( " + varnames + " , %var% )").c_str()))) {
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok->tokAt(4)->varId()); const Variable *var = tok->tokAt(4)->variable();
if (var && var->isArray() && var->dimensions().size() == 1) { if (var && var->isArray() && var->dimensions().size() == 1) {
const std::size_t len = (std::size_t)var->dimension(0); const std::size_t len = (std::size_t)var->dimension(0);
if (total_size > 0 && len > (unsigned int)total_size) { if (total_size > 0 && len > (unsigned int)total_size) {
@ -1915,7 +1915,7 @@ void CheckBufferOverrun::negativeIndex()
tok2 = tok2->previous()->link(); tok2 = tok2->previous()->link();
if (tok2->previous() && tok2->previous()->varId()) { if (tok2->previous() && tok2->previous()->varId()) {
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok2->previous()->varId()); const Variable *var = tok2->previous()->variable();
if (var && var->isArray()) if (var && var->isArray())
negativeIndexError(tok, index); negativeIndexError(tok, index);
} }