Fixed #4535 (Simplify checks by caching symbol database Variable pointer in Token)

This commit is contained in:
Robert Reif 2013-02-06 06:39:58 +01:00 committed by Daniel Marjamäki
parent d9de7f7052
commit 42588e9729
7 changed files with 96 additions and 117 deletions

View File

@ -1401,7 +1401,7 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable()
std::string type; std::string type;
// varid : The variable id for the array // varid : The variable id for the array
unsigned int varid = 0; const Variable *var = 0;
// nextTok : number of tokens used in variable declaration - used to skip to next statement. // nextTok : number of tokens used in variable declaration - used to skip to next statement.
int nextTok = 0; int nextTok = 0;
@ -1413,29 +1413,26 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable()
if (Token::Match(tok, "[*;{}] %var% = new %type% [ %num% ]")) { if (Token::Match(tok, "[*;{}] %var% = new %type% [ %num% ]")) {
size = MathLib::toLongNumber(tok->strAt(6)); size = MathLib::toLongNumber(tok->strAt(6));
type = tok->strAt(4); type = tok->strAt(4);
varid = tok->next()->varId(); var = tok->next()->variable();
nextTok = 8; nextTok = 8;
} else if (Token::Match(tok, "[*;{}] %var% = new %type% ( %num% )")) { } else if (Token::Match(tok, "[*;{}] %var% = new %type% ( %num% )")) {
size = 1; size = 1;
type = tok->strAt(4); type = tok->strAt(4);
varid = tok->next()->varId(); var = tok->next()->variable();
nextTok = 8; nextTok = 8;
} else if (Token::Match(tok, "[;{}] %var% = %str% ;") && } else if (Token::Match(tok, "[;{}] %var% = %str% ;") &&
tok->next()->varId() > 0 && tok->next()->varId() > 0 &&
NULL != Token::findmatch(_tokenizer->tokens(), "[;{}] const| %type% * %varid% ;", tok->next()->varId())) { NULL != Token::findmatch(_tokenizer->tokens(), "[;{}] const| %type% * %varid% ;", tok->next()->varId())) {
size = 1 + int(tok->tokAt(3)->strValue().size()); size = 1 + int(tok->tokAt(3)->strValue().size());
type = "char"; type = "char";
varid = tok->next()->varId(); var = tok->next()->variable();
nextTok = 4; nextTok = 4;
} else if (Token::Match(tok, "[*;{}] %var% = malloc|alloca ( %num% ) ;")) { } else if (Token::Match(tok, "[*;{}] %var% = malloc|alloca ( %num% ) ;")) {
size = MathLib::toLongNumber(tok->strAt(5)); size = MathLib::toLongNumber(tok->strAt(5));
type = "char"; // minimum type, typesize=1 type = "char"; // minimum type, typesize=1
varid = tok->next()->varId(); var = tok->next()->variable();
nextTok = 7; nextTok = 7;
if (varid > 0) {
// get type of variable
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(varid);
/** @todo false negatives: this may be too conservative */ /** @todo false negatives: this may be too conservative */
if (!var || var->typeEndToken()->str() != "*" || var->typeStartToken()->next() != var->typeEndToken()) if (!var || var->typeEndToken()->str() != "*" || var->typeStartToken()->next() != var->typeEndToken())
continue; continue;
@ -1449,12 +1446,11 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable()
unsigned int sizeOfType = _tokenizer->sizeOfType(var->typeStartToken()); unsigned int sizeOfType = _tokenizer->sizeOfType(var->typeStartToken());
if (sizeOfType > 0) if (sizeOfType > 0)
size /= static_cast<int>(sizeOfType); size /= static_cast<int>(sizeOfType);
}
} else { } else {
continue; continue;
} }
if (varid == 0) if (var == 0)
continue; continue;
Token sizeTok(0); Token sizeTok(0);
@ -1464,7 +1460,7 @@ void CheckBufferOverrun::checkGlobalAndLocalVariable()
continue; continue;
std::vector<std::string> v; std::vector<std::string> v;
ArrayInfo temp(varid, tok->next()->str(), total_size / size, size); ArrayInfo temp(var->varId(), tok->next()->str(), total_size / size, size);
checkScope(tok->tokAt(nextTok), v, temp); checkScope(tok->tokAt(nextTok), v, temp);
} }
} }

View File

@ -89,15 +89,14 @@ void CheckExceptionSafety::deallocThrow()
break; break;
if (!Token::Match(tok, "%var% ;")) if (!Token::Match(tok, "%var% ;"))
continue; continue;
const unsigned int varid(tok->varId());
if (varid == 0)
continue;
// we only look for global variables // we only look for global variables
const Variable* var = symbolDatabase->getVariableFromVarId(varid); const Variable *var = tok->variable();
if (!var || !(var->isGlobal() || var->isStatic())) if (!var || !(var->isGlobal() || var->isStatic()))
continue; continue;
const unsigned int varid(tok->varId());
// Token where throw occurs // Token where throw occurs
const Token *ThrowToken = 0; const Token *ThrowToken = 0;
@ -172,7 +171,7 @@ void CheckExceptionSafety::checkCatchExceptionByValue()
// Find a pass-by-value declaration in the catch(), excluding basic types // Find a pass-by-value declaration in the catch(), excluding basic types
// e.g. catch (std::exception err) // e.g. catch (std::exception err)
const Variable* var = symbolDatabase->getVariableFromVarId(i->classStart->tokAt(-2)->varId()); const Variable *var = i->classStart->tokAt(-2)->variable();
if (var && var->isClass() && !var->isPointer() && !var->isReference()) if (var && var->isClass() && !var->isPointer() && !var->isReference())
catchExceptionByValueError(i->classDef); catchExceptionByValueError(i->classDef);
} }

View File

@ -516,7 +516,7 @@ void CheckIO::checkWrongPrintfScanfArguments()
// Perform type checks // Perform type checks
if (argListTok && Token::Match(argListTok->next(), "[,)]")) { // We can currently only check the type of arguments matching this simple pattern. if (argListTok && Token::Match(argListTok->next(), "[,)]")) { // We can currently only check the type of arguments matching this simple pattern.
const Variable* variableInfo = symbolDatabase->getVariableFromVarId(argListTok->varId()); const Variable *variableInfo = argListTok->variable();
const Token* varTypeTok = variableInfo ? variableInfo->typeStartToken() : NULL; const Token* varTypeTok = variableInfo ? variableInfo->typeStartToken() : NULL;
if (varTypeTok && varTypeTok->str() == "static") if (varTypeTok && varTypeTok->str() == "static")
varTypeTok = varTypeTok->next(); varTypeTok = varTypeTok->next();

View File

@ -311,7 +311,7 @@ void CheckLeakAutoVar::checkScope(const Token * const startToken,
varInfo->erase(tok->varId()); varInfo->erase(tok->varId());
// not a local variable nor argument? // not a local variable nor argument?
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok->varId()); const Variable *var = tok->variable();
if (var && !var->isArgument() && !var->isLocal()) { if (var && !var->isArgument() && !var->isLocal()) {
continue; continue;
} }

View File

@ -492,16 +492,14 @@ void CheckNullPointer::nullPointerLinkedList()
for (const Token *tok2 = tok1->tokAt(2); tok2 != end2; tok2 = tok2->next()) { for (const Token *tok2 = tok1->tokAt(2); tok2 != end2; tok2 = tok2->next()) {
// Dereferencing a variable inside the "for" parentheses.. // Dereferencing a variable inside the "for" parentheses..
if (Token::Match(tok2, "%var% . %var%")) { if (Token::Match(tok2, "%var% . %var%")) {
// Variable id for dereferenced variable
const unsigned int varid(tok2->varId());
if (varid == 0)
continue;
// Is this variable a pointer? // Is this variable a pointer?
const Variable* var = symbolDatabase->getVariableFromVarId(varid); const Variable *var = tok2->variable();
if (!var || !var->isPointer()) if (!var || !var->isPointer())
continue; continue;
// Variable id for dereferenced variable
const unsigned int varid(tok2->varId());
if (Token::Match(tok2->tokAt(-2), "%varid% ?", varid)) if (Token::Match(tok2->tokAt(-2), "%varid% ?", varid))
continue; continue;
@ -652,7 +650,7 @@ void CheckNullPointer::nullPointerStructByDeRefAndChec()
// is pointer local? // is pointer local?
bool isLocal = false; bool isLocal = false;
const Variable * var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok1->varId()); const Variable *var = tok1->variable();
if (!var) if (!var)
continue; continue;
if (var->isLocal() || var->isArgument()) if (var->isLocal() || var->isArgument())
@ -748,19 +746,17 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
if (vartok->str() == "!") if (vartok->str() == "!")
vartok = vartok->next(); vartok = vartok->next();
// Variable id for pointer const Variable *var = vartok->variable();
const unsigned int varid(vartok->varId());
if (varid == 0)
continue;
// Name of pointer
const std::string& varname(vartok->str());
const Variable* var = symbolDatabase->getVariableFromVarId(varid);
// Check that variable is a pointer.. // Check that variable is a pointer..
if (!var || !var->isPointer()) if (!var || !var->isPointer())
continue; continue;
// Variable id for pointer
const unsigned int varid(vartok->varId());
// Name of pointer
const std::string& varname(vartok->str());
const Token * const decltok = var->nameToken(); const Token * const decltok = var->nameToken();
bool inconclusive = false; bool inconclusive = false;
@ -932,16 +928,14 @@ void CheckNullPointer::nullPointerByCheckAndDeRef()
} else } else
continue; continue;
// variable id for pointer
const unsigned int varid(vartok->varId());
if (varid == 0)
continue;
// Check if variable is a pointer // Check if variable is a pointer
const Variable* var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(varid); const Variable *var = vartok->variable();
if (!var || !var->isPointer()) if (!var || !var->isPointer())
continue; continue;
// variable id for pointer
const unsigned int varid(vartok->varId());
const Scope* declScope = &*i; const Scope* declScope = &*i;
while (declScope->nestedIn && var->scope() != declScope && declScope->type != Scope::eFunction) while (declScope->nestedIn && var->scope() != declScope && declScope->type != Scope::eFunction)
declScope = declScope->nestedIn; declScope = declScope->nestedIn;
@ -1147,7 +1141,7 @@ void CheckNullPointer::nullConstantDereference()
else if (Token::Match(tok->previous(), "!!. %var% (") && (tok->previous()->str() != "::" || tok->strAt(-2) == "std")) { else if (Token::Match(tok->previous(), "!!. %var% (") && (tok->previous()->str() != "::" || tok->strAt(-2) == "std")) {
if (Token::simpleMatch(tok->tokAt(2), "0 )") && tok->varId()) { // constructor call if (Token::simpleMatch(tok->tokAt(2), "0 )") && tok->varId()) { // constructor call
const Variable* var = symbolDatabase->getVariableFromVarId(tok->varId()); const Variable *var = tok->variable();
if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "std :: string|wstring !!::")) if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "std :: string|wstring !!::"))
nullPointerError(tok); nullPointerError(tok);
} else { // function call } else { // function call
@ -1173,27 +1167,24 @@ void CheckNullPointer::nullConstantDereference()
if (Token::simpleMatch(tok2, "std :: cin")) if (Token::simpleMatch(tok2, "std :: cin"))
nullPointerError(tok); nullPointerError(tok);
if (tok2 && tok2->varId() != 0) { if (tok2 && tok2->varId() != 0) {
const Variable* var = symbolDatabase->getVariableFromVarId(tok2->varId()); const Variable *var = tok2->variable();
if (var && Token::Match(var->typeStartToken(), "std :: istream|ifstream|istringstream|wistringstream|stringstream|wstringstream|fstream|iostream")) if (var && Token::Match(var->typeStartToken(), "std :: istream|ifstream|istringstream|wistringstream|stringstream|wstringstream|fstream|iostream"))
nullPointerError(tok); nullPointerError(tok);
} }
} }
unsigned int ovarid = 0; const Variable *ovar = 0;
if (Token::Match(tok, "0 ==|!= %var%")) if (Token::Match(tok, "0 ==|!= %var%"))
ovarid = tok->tokAt(2)->varId(); ovar = tok->tokAt(2)->variable();
else if (Token::Match(tok, "%var% ==|!= 0")) else if (Token::Match(tok, "%var% ==|!= 0"))
ovarid = tok->varId(); ovar = tok->variable();
else if (Token::Match(tok, "%var% =|+ 0 )|]|,|;|+")) else if (Token::Match(tok, "%var% =|+ 0 )|]|,|;|+"))
ovarid = tok->varId(); ovar = tok->variable();
if (ovarid) { if (ovar && !ovar->isPointer() && !ovar->isArray() && Token::Match(ovar->typeStartToken(), "std :: string|wstring !!::"))
const Variable* var = symbolDatabase->getVariableFromVarId(ovarid);
if (var && !var->isPointer() && !var->isArray() && Token::Match(var->typeStartToken(), "std :: string|wstring !!::"))
nullPointerError(tok); nullPointerError(tok);
} }
} }
} }
}
/** /**
@ -1217,7 +1208,7 @@ void CheckNullPointer::nullPointerDefaultArgument()
for (const Token *tok = scope->function->arg; tok != scope->function->arg->link(); tok = tok->next()) { for (const Token *tok = scope->function->arg; tok != scope->function->arg->link(); tok = tok->next()) {
if (Token::Match(tok, "%var% = 0 ,|)") && tok->varId() != 0) { if (Token::Match(tok, "%var% = 0 ,|)") && tok->varId() != 0) {
const Variable* var = symbolDatabase->getVariableFromVarId(tok->varId()); const Variable *var = tok->variable();
if (var && var->isPointer()) if (var && var->isPointer())
pointerArgs.insert(tok->varId()); pointerArgs.insert(tok->varId());
} }
@ -1349,7 +1340,7 @@ private:
const Token *parse(const Token &tok, std::list<ExecutionPath *> &checks) const { const Token *parse(const Token &tok, std::list<ExecutionPath *> &checks) const {
if (tok.varId() != 0) { if (tok.varId() != 0) {
// Pointer declaration declaration? // Pointer declaration declaration?
const Variable* var = symbolDatabase->getVariableFromVarId(tok.varId()); const Variable *var = tok.variable();
if (var && var->isPointer() && var->nameToken() == &tok) if (var && var->isPointer() && var->nameToken() == &tok)
checks.push_back(new Nullpointer(owner, var->varId(), var->name(), symbolDatabase)); checks.push_back(new Nullpointer(owner, var->varId(), var->name(), symbolDatabase));
} }

View File

@ -46,7 +46,7 @@ void CheckOther::checkIncrementBoolean()
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, "%var% ++")) { if (Token::Match(tok, "%var% ++")) {
if (tok->varId()) { if (tok->varId()) {
const Variable *var = symbolDatabase->getVariableFromVarId(tok->varId()); const Variable *var = tok->variable();
if (var && var->typeEndToken()->str() == "bool") if (var && var->typeEndToken()->str() == "bool")
incrementBooleanError(tok); incrementBooleanError(tok);
@ -313,13 +313,13 @@ void CheckOther::checkBitwiseOnBoolean()
const Scope * scope = symbolDatabase->functionScopes[i]; const Scope * scope = symbolDatabase->functionScopes[i];
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|&&|%oror%|throw|, %var% [&|]")) { if (Token::Match(tok, "(|.|return|&&|%oror%|throw|, %var% [&|]")) {
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok->next()->varId()); const Variable *var = tok->next()->variable();
if (var && var->typeEndToken()->str() == "bool") { if (var && var->typeEndToken()->str() == "bool") {
bitwiseOnBooleanError(tok->next(), var->name(), tok->strAt(2) == "&" ? "&&" : "||"); bitwiseOnBooleanError(tok->next(), var->name(), tok->strAt(2) == "&" ? "&&" : "||");
tok = tok->tokAt(2); tok = tok->tokAt(2);
} }
} else if (Token::Match(tok, "[&|] %var% )|.|return|&&|%oror%|throw|,") && (!tok->previous() || !tok->previous()->isExtendedOp() || tok->strAt(-1) == ")")) { } else if (Token::Match(tok, "[&|] %var% )|.|return|&&|%oror%|throw|,") && (!tok->previous() || !tok->previous()->isExtendedOp() || tok->strAt(-1) == ")")) {
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok->next()->varId()); const Variable *var = tok->next()->variable();
if (var && var->typeEndToken()->str() == "bool") { if (var && var->typeEndToken()->str() == "bool") {
bitwiseOnBooleanError(tok->next(), var->name(), tok->str() == "&" ? "&&" : "||"); bitwiseOnBooleanError(tok->next(), var->name(), tok->str() == "&" ? "&&" : "||");
tok = tok->tokAt(2); tok = tok->tokAt(2);
@ -448,15 +448,15 @@ void CheckOther::invalidPointerCast()
continue; continue;
// Find casted variable // Find casted variable
unsigned int varid = 0; const Variable *var = 0;
bool allocation = false; bool allocation = false;
bool ref = false; bool ref = false;
if (Token::Match(nextTok, "new %type%")) if (Token::Match(nextTok, "new %type%"))
allocation = true; allocation = true;
else if (Token::Match(nextTok, "%var% !![")) else if (Token::Match(nextTok, "%var% !!["))
varid = nextTok->varId(); var = nextTok->variable();
else if (Token::Match(nextTok, "& %var%") && !Token::Match(nextTok->tokAt(2), "(|[")) { else if (Token::Match(nextTok, "& %var%") && !Token::Match(nextTok->tokAt(2), "(|[")) {
varid = nextTok->next()->varId(); var = nextTok->next()->variable();
ref = true; ref = true;
} }
@ -465,7 +465,6 @@ void CheckOther::invalidPointerCast()
if (allocation) { if (allocation) {
fromTok = nextTok->next(); fromTok = nextTok->next();
} else { } else {
const Variable* var = symbolDatabase->getVariableFromVarId(varid);
if (!var || (!ref && !var->isPointer() && !var->isArray()) || (ref && (var->isPointer() || var->isArray()))) if (!var || (!ref && !var->isPointer() && !var->isArray()) || (ref && (var->isPointer() || var->isArray())))
continue; continue;
fromTok = var->typeStartToken(); fromTok = var->typeStartToken();
@ -540,7 +539,7 @@ void CheckOther::checkSizeofForArrayParameter()
varTok = varTok->next(); varTok = varTok->next();
} }
if (varTok->varId() > 0) { if (varTok->varId() > 0) {
const Variable *var = symbolDatabase->getVariableFromVarId(varTok->varId()); const Variable *var = varTok->variable();
if (var && var->isArray() && var->isArgument()) { if (var && var->isArray() && var->isArgument()) {
sizeofForArrayParameterError(tok); sizeofForArrayParameterError(tok);
} }
@ -613,13 +612,13 @@ void CheckOther::checkSizeofForPointerSize()
// Ensure the variables are in the symbol database // Ensure the variables are in the symbol database
// Also ensure the variables are pointers // Also ensure the variables are pointers
// Only keep variables which are pointers // Only keep variables which are pointers
const Variable *var = symbolDatabase->getVariableFromVarId(variable->varId()); const Variable *var = variable->variable();
if (!var || !var->isPointer() || var->isArray()) { if (!var || !var->isPointer() || var->isArray()) {
variable = 0; variable = 0;
} }
if (variable2) { if (variable2) {
var = symbolDatabase->getVariableFromVarId(variable2->varId()); var = variable2->variable();
if (!var || !var->isPointer() || var->isArray()) { if (!var || !var->isPointer() || var->isArray()) {
variable2 = 0; variable2 = 0;
} }
@ -1187,13 +1186,11 @@ void CheckOther::checkSelfAssignment()
if (!_settings->isEnabled("style")) if (!_settings->isEnabled("style"))
return; return;
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
const Token *tok = findSelfAssignPattern(_tokenizer->tokens()); const Token *tok = findSelfAssignPattern(_tokenizer->tokens());
while (tok) { while (tok) {
if (Token::Match(tok->previous(), "[;{}.]") && if (Token::Match(tok->previous(), "[;{}.]") &&
tok->varId() && tok->varId() == tok->tokAt(2)->varId() && tok->varId() && tok->varId() == tok->tokAt(2)->varId() &&
isTypeWithoutSideEffects(_tokenizer, symbolDatabase->getVariableFromVarId(tok->varId()))) { isTypeWithoutSideEffects(_tokenizer, tok->variable())) {
bool err = true; bool err = true;
// no false positive for 'x = x ? x : 1;' // no false positive for 'x = x ? x : 1;'
@ -1659,19 +1656,19 @@ void CheckOther::checkComparisonOfBoolWithInt()
const Token* numTok = right; const Token* numTok = right;
if (tok->isNumber() && right->varId()) // num with var if (tok->isNumber() && right->varId()) // num with var
std::swap(varTok, numTok); std::swap(varTok, numTok);
if (isBool(symbolDatabase->getVariableFromVarId(varTok->varId())) && // Variable has to be a boolean if (isBool(varTok->variable()) && // Variable has to be a boolean
((tok->strAt(1) != "==" && tok->strAt(1) != "!=") || ((tok->strAt(1) != "==" && tok->strAt(1) != "!=") ||
(MathLib::toLongNumber(numTok->str()) != 0 && MathLib::toLongNumber(numTok->str()) != 1))) { // == 0 and != 0 are allowed, for C also == 1 and != 1 (MathLib::toLongNumber(numTok->str()) != 0 && MathLib::toLongNumber(numTok->str()) != 1))) { // == 0 and != 0 are allowed, for C also == 1 and != 1
comparisonOfBoolWithIntError(varTok, numTok->str(), tok->strAt(1) == "==" || tok->strAt(1) == "!="); comparisonOfBoolWithIntError(varTok, numTok->str(), tok->strAt(1) == "==" || tok->strAt(1) == "!=");
} }
} else if (tok->isBoolean() && right->varId()) { // Comparing boolean constant with variable } else if (tok->isBoolean() && right->varId()) { // Comparing boolean constant with variable
if (isNonBoolStdType(symbolDatabase->getVariableFromVarId(right->varId()))) { // Variable has to be of non-boolean standard type if (isNonBoolStdType(right->variable())) { // Variable has to be of non-boolean standard type
comparisonOfBoolWithIntError(right, tok->str(), false); comparisonOfBoolWithIntError(right, tok->str(), false);
} else if (tok->strAt(1) != "==" && tok->strAt(1) != "!=") { } else if (tok->strAt(1) != "==" && tok->strAt(1) != "!=") {
comparisonOfBoolWithInvalidComparator(right, tok->str()); comparisonOfBoolWithInvalidComparator(right, tok->str());
} }
} else if (tok->varId() && right->isBoolean()) { // Comparing variable with boolean constant } else if (tok->varId() && right->isBoolean()) { // Comparing variable with boolean constant
if (isNonBoolStdType(symbolDatabase->getVariableFromVarId(tok->varId()))) { // Variable has to be of non-boolean standard type if (isNonBoolStdType(tok->variable())) { // Variable has to be of non-boolean standard type
comparisonOfBoolWithIntError(tok, right->str(), false); comparisonOfBoolWithIntError(tok, right->str(), false);
} else if (tok->strAt(1) != "==" && tok->strAt(1) != "!=") { } else if (tok->strAt(1) != "==" && tok->strAt(1) != "!=") {
comparisonOfBoolWithInvalidComparator(right, tok->str()); comparisonOfBoolWithInvalidComparator(right, tok->str());
@ -1681,8 +1678,8 @@ void CheckOther::checkComparisonOfBoolWithInt()
} else if (tok->isBoolean() && right->isNumber()) { // number constant with boolean constant } else if (tok->isBoolean() && right->isNumber()) { // number constant with boolean constant
comparisonOfBoolWithIntError(tok, tok->str(), false); comparisonOfBoolWithIntError(tok, tok->str(), false);
} else if (tok->varId() && right->varId()) { // Comparing two variables, one of them boolean, one of them integer } else if (tok->varId() && right->varId()) { // Comparing two variables, one of them boolean, one of them integer
const Variable* var1 = symbolDatabase->getVariableFromVarId(right->varId()); const Variable* var1 = right->variable();
const Variable* var2 = symbolDatabase->getVariableFromVarId(tok->varId()); const Variable* var2 = tok->variable();
if (isBool(var1) && isNonBoolStdType(var2)) // Comparing boolean with non-bool standard type if (isBool(var1) && isNonBoolStdType(var2)) // Comparing boolean with non-bool standard type
comparisonOfBoolWithIntError(tok, var1->name(), false); comparisonOfBoolWithIntError(tok, var1->name(), false);
else if (isNonBoolStdType(var1) && isBool(var2)) // Comparing non-bool standard type with boolean else if (isNonBoolStdType(var1) && isBool(var2)) // Comparing non-bool standard type with boolean
@ -1833,16 +1830,16 @@ void CheckOther::checkUnsignedDivision()
continue; continue;
if (Token::Match(tok->next(), "%var% / %num%")) { if (Token::Match(tok->next(), "%var% / %num%")) {
if (tok->strAt(3)[0] == '-' && isUnsigned(symbolDatabase->getVariableFromVarId(tok->next()->varId()))) { if (tok->strAt(3)[0] == '-' && isUnsigned(tok->next()->variable())) {
udivError(tok->next(), false); udivError(tok->next(), false);
} }
} else if (Token::Match(tok->next(), "%num% / %var%")) { } else if (Token::Match(tok->next(), "%num% / %var%")) {
if (tok->strAt(1)[0] == '-' && isUnsigned(symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId()))) { if (tok->strAt(1)[0] == '-' && isUnsigned(tok->tokAt(3)->variable())) {
udivError(tok->next(), false); udivError(tok->next(), false);
} }
} else if (Token::Match(tok->next(), "%var% / %var%") && _settings->inconclusive && style && !ifTok) { } else if (Token::Match(tok->next(), "%var% / %var%") && _settings->inconclusive && style && !ifTok) {
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 ((isUnsigned(var1) && isSigned(var2)) || (isUnsigned(var2) && isSigned(var1))) { if ((isUnsigned(var1) && isSigned(var2)) || (isUnsigned(var2) && isSigned(var1))) {
udivError(tok->next(), true); udivError(tok->next(), true);
} }
@ -2108,8 +2105,8 @@ void CheckOther::checkCharVariable()
const Scope * scope = symbolDatabase->functionScopes[i]; const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) { for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
if ((tok->str() != ".") && Token::Match(tok->next(), "%var% [ %var% ]")) { if ((tok->str() != ".") && Token::Match(tok->next(), "%var% [ %var% ]")) {
const Variable* arrayvar = symbolDatabase->getVariableFromVarId(tok->next()->varId()); const Variable* arrayvar = tok->next()->variable();
const Variable* indexvar = symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId()); const Variable* indexvar = tok->tokAt(3)->variable();
const MathLib::bigint arraysize = (arrayvar && arrayvar->isArray()) ? arrayvar->dimension(0U) : 0; const MathLib::bigint arraysize = (arrayvar && arrayvar->isArray()) ? arrayvar->dimension(0U) : 0;
if (isSignedChar(indexvar) && arraysize > 0x80) if (isSignedChar(indexvar) && arraysize > 0x80)
charArrayIndexError(tok->next()); charArrayIndexError(tok->next());
@ -2117,8 +2114,8 @@ void CheckOther::checkCharVariable()
else if (Token::Match(tok, "[;{}] %var% = %any% [&^|] %any% ;")) { else if (Token::Match(tok, "[;{}] %var% = %any% [&^|] %any% ;")) {
// is a char variable used in the calculation? // is a char variable used in the calculation?
if (!isSignedChar(symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId())) && if (!isSignedChar(tok->tokAt(3)->variable()) &&
!isSignedChar(symbolDatabase->getVariableFromVarId(tok->tokAt(5)->varId()))) !isSignedChar(tok->tokAt(5)->variable()))
continue; continue;
// it's ok with a bitwise and where the other operand is 0xff or less.. // it's ok with a bitwise and where the other operand is 0xff or less..
@ -2130,13 +2127,13 @@ void CheckOther::checkCharVariable()
} }
// is the result stored in a short|int|long? // is the result stored in a short|int|long?
const Variable *var = symbolDatabase->getVariableFromVarId(tok->next()->varId()); const Variable *var = tok->next()->variable();
if (var && Token::Match(var->typeStartToken(), "short|int|long") && !var->isPointer() && !var->isArray()) if (var && Token::Match(var->typeStartToken(), "short|int|long") && !var->isPointer() && !var->isArray())
charBitOpError(tok->tokAt(4)); // This is an error.. charBitOpError(tok->tokAt(4)); // This is an error..
} }
else if (Token::Match(tok, "[;{}] %var% = %any% [&^|] ( * %var% ) ;")) { else if (Token::Match(tok, "[;{}] %var% = %any% [&^|] ( * %var% ) ;")) {
const Variable* var = symbolDatabase->getVariableFromVarId(tok->tokAt(7)->varId()); const Variable* var = tok->tokAt(7)->variable();
if (!var || !var->isPointer() || var->typeStartToken()->str() != "char" || var->typeStartToken()->isUnsigned()) if (!var || !var->isPointer() || var->typeStartToken()->str() != "char" || var->typeStartToken()->isUnsigned())
continue; continue;
// it's ok with a bitwise and where the other operand is 0xff or less.. // it's ok with a bitwise and where the other operand is 0xff or less..
@ -2144,7 +2141,7 @@ void CheckOther::checkCharVariable()
continue; continue;
// is the result stored in a short|int|long? // is the result stored in a short|int|long?
var = symbolDatabase->getVariableFromVarId(tok->next()->varId()); var = tok->next()->variable();
if (var && Token::Match(var->typeStartToken(), "short|int|long") && !var->isPointer() && !var->isArray()) if (var && Token::Match(var->typeStartToken(), "short|int|long") && !var->isPointer() && !var->isArray())
charBitOpError(tok->tokAt(4)); // This is an error.. charBitOpError(tok->tokAt(4)); // This is an error..
} }
@ -2241,8 +2238,7 @@ void CheckOther::strPlusChar()
strPlusCharError(tok->next()); strPlusCharError(tok->next());
// char variable.. // char variable..
unsigned int varid = tok->tokAt(3)->varId(); if (isChar(tok->tokAt(3)->variable()))
if (isChar(symbolDatabase->getVariableFromVarId(varid)))
strPlusCharError(tok->next()); strPlusCharError(tok->next());
} }
} }
@ -2499,13 +2495,13 @@ void CheckOther::checkComparisonOfBoolWithBool()
const Token *first_token = tok->previous(); const Token *first_token = tok->previous();
if (first_token->varId()) { if (first_token->varId()) {
if (isBool(symbolDatabase->getVariableFromVarId(first_token->varId()))) { if (isBool(first_token->variable())) {
first_token_bool = true; first_token_bool = true;
} }
} }
const Token *second_token = tok->next(); const Token *second_token = tok->next();
if (second_token->varId()) { if (second_token->varId()) {
if (isBool(symbolDatabase->getVariableFromVarId(second_token->varId()))) { if (isBool(second_token->variable())) {
second_token_bool = true; second_token_bool = true;
} }
} }
@ -2911,8 +2907,7 @@ namespace {
const Token *_tok; const Token *_tok;
}; };
bool inconclusiveFunctionCall(const SymbolDatabase *symbolDatabase, bool inconclusiveFunctionCall(const std::list<const Function*> &constFunctions,
const std::list<const Function*> &constFunctions,
const ExpressionTokens &tokens) const ExpressionTokens &tokens)
{ {
const Token *start = tokens.start; const Token *start = tokens.start;
@ -2932,7 +2927,7 @@ namespace {
const Variable *v = 0; const Variable *v = 0;
if (Token::Match(prev->tokAt(-2), "%var% .")) { if (Token::Match(prev->tokAt(-2), "%var% .")) {
const Token *scope = prev->tokAt(-2); const Token *scope = prev->tokAt(-2);
v = symbolDatabase->getVariableFromVarId(scope->varId()); v = scope->variable();
} }
// hard coded list of safe, no-side-effect functions // hard coded list of safe, no-side-effect functions
if (v == 0 && Token::Match(prev, "strcmp|strncmp|strlen|wcscmp|wcsncmp|wcslen|memcmp|strcasecmp|strncasecmp")) if (v == 0 && Token::Match(prev, "strcmp|strncmp|strlen|wcscmp|wcsncmp|wcslen|memcmp|strcasecmp|strncasecmp"))
@ -2965,7 +2960,7 @@ namespace {
if (it == _expressions.end()) { if (it == _expressions.end()) {
ExpressionTokens exprTokens(_start, end); ExpressionTokens exprTokens(_start, end);
exprTokens.inconclusiveFunction = lastInconclusive || inconclusiveFunctionCall( exprTokens.inconclusiveFunction = lastInconclusive || inconclusiveFunctionCall(
_symbolDatabase, _constFunctions, exprTokens); _constFunctions, exprTokens);
_expressions.insert(std::make_pair(e, exprTokens)); _expressions.insert(std::make_pair(e, exprTokens));
_lastTokens = &_expressions.find(e)->second; _lastTokens = &_expressions.find(e)->second;
} else { } else {
@ -3178,7 +3173,7 @@ void CheckOther::checkDuplicateExpression()
// float == float and float != float are valid NaN checks // float == float and float != float are valid NaN checks
// float - float is a valid Inf check // float - float is a valid Inf check
if (Token::Match(tok->tokAt(2), "==|!=|-") && tok->next()->varId()) { if (Token::Match(tok->tokAt(2), "==|!=|-") && tok->next()->varId()) {
const Variable * var = symbolDatabase->getVariableFromVarId(tok->next()->varId()); const Variable *var = tok->next()->variable();
if (var && var->typeStartToken() == var->typeEndToken()) { if (var && var->typeStartToken() == var->typeEndToken()) {
if (Token::Match(var->typeStartToken(), "float|double")) if (Token::Match(var->typeStartToken(), "float|double"))
continue; continue;
@ -3306,7 +3301,7 @@ void CheckOther::checkSuspiciousStringCompare()
if (varTok->type() == Token::eString) if (varTok->type() == Token::eString)
std::swap(varTok, litTok); std::swap(varTok, litTok);
const Variable* var = symbolDatabase->getVariableFromVarId(varTok->varId()); const Variable *var = varTok->variable();
if (var) { if (var) {
if (_tokenizer->isC() || if (_tokenizer->isC() ||
(var->isPointer() && varTok->strAt(-1) != "*" && !Token::Match(varTok->next(), "[.([]"))) (var->isPointer() && varTok->strAt(-1) != "*" && !Token::Match(varTok->next(), "[.([]")))
@ -3408,12 +3403,10 @@ void CheckOther::suspiciousSizeofCalculation()
if (!_settings->isEnabled("style") || !_settings->inconclusive) if (!_settings->isEnabled("style") || !_settings->inconclusive)
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 (Token::simpleMatch(tok, "sizeof (")) { if (Token::simpleMatch(tok, "sizeof (")) {
const Token* const end = tok->linkAt(1); const Token* const end = tok->linkAt(1);
const Variable* var = symbolDatabase->getVariableFromVarId(end->previous()->varId()); const Variable* var = end->previous()->variable();
if (end->strAt(-1) == "*" || (var && var->isPointer() && !var->isArray())) { if (end->strAt(-1) == "*" || (var && var->isPointer() && !var->isArray())) {
if (end->strAt(1) == "/") if (end->strAt(1) == "/")
divideSizeofError(tok); divideSizeofError(tok);
@ -3447,7 +3440,7 @@ void CheckOther::checkAssignBoolToPointer()
const Scope * scope = symbolDatabase->functionScopes[i]; const Scope * scope = symbolDatabase->functionScopes[i];
for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) { for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "!!* %var% = %bool% ;")) { if (Token::Match(tok, "!!* %var% = %bool% ;")) {
const Variable *var1(symbolDatabase->getVariableFromVarId(tok->next()->varId())); const Variable *var1(tok->next()->variable());
// Is variable a pointer? // Is variable a pointer?
if (var1 && var1->isPointer()) if (var1 && var1->isPointer())
@ -3513,7 +3506,7 @@ void CheckOther::checkComparisonOfBoolExpressionWithInt()
if (numTok->isNumber()) { if (numTok->isNumber()) {
if (((numTok->str() != "0" && numTok->str() != "1") || !Token::Match(opTok, "!=|==")) && !((op == '<' && numTok->str() == "1") || (op == '>' && numTok->str() == "0"))) if (((numTok->str() != "0" && numTok->str() != "1") || !Token::Match(opTok, "!=|==")) && !((op == '<' && numTok->str() == "1") || (op == '>' && numTok->str() == "0")))
comparisonOfBoolExpressionWithIntError(tok, true); comparisonOfBoolExpressionWithIntError(tok, true);
} else if (isNonBoolStdType(symbolDatabase->getVariableFromVarId(numTok->varId()))) } else if (isNonBoolStdType(numTok->variable()))
comparisonOfBoolExpressionWithIntError(tok, false); comparisonOfBoolExpressionWithIntError(tok, false);
} }
} }
@ -3551,25 +3544,25 @@ void CheckOther::checkSignOfUnsignedVariable()
// check all the code in the function // check all the code in the function
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, "%var% <|<= 0") && tok->varId() && !Token::Match(tok->previous(), "++|--|)|+|-|*|/|~|<<|>>") && !Token::Match(tok->tokAt(3), "+|-")) { if (Token::Match(tok, "%var% <|<= 0") && tok->varId() && !Token::Match(tok->previous(), "++|--|)|+|-|*|/|~|<<|>>") && !Token::Match(tok->tokAt(3), "+|-")) {
const Variable * var = symbolDatabase->getVariableFromVarId(tok->varId()); const Variable *var = tok->variable();
if (var && var->typeEndToken()->isUnsigned()) if (var && var->typeEndToken()->isUnsigned())
unsignedLessThanZeroError(tok, var->name(), inconclusive); unsignedLessThanZeroError(tok, var->name(), inconclusive);
else if (var && var->isPointer() && tok->strAt(-1) != "*") else if (var && var->isPointer() && tok->strAt(-1) != "*")
pointerLessThanZeroError(tok, inconclusive); pointerLessThanZeroError(tok, inconclusive);
} else if (Token::Match(tok, "0 >|>= %var%") && tok->tokAt(2)->varId() && !Token::Match(tok->tokAt(3), "+|-|*|/") && !Token::Match(tok->previous(), "+|-|<<|>>|~")) { } else if (Token::Match(tok, "0 >|>= %var%") && tok->tokAt(2)->varId() && !Token::Match(tok->tokAt(3), "+|-|*|/") && !Token::Match(tok->previous(), "+|-|<<|>>|~")) {
const Variable * var = symbolDatabase->getVariableFromVarId(tok->tokAt(2)->varId()); const Variable *var = tok->tokAt(2)->variable();
if (var && var->typeEndToken()->isUnsigned()) if (var && var->typeEndToken()->isUnsigned())
unsignedLessThanZeroError(tok, var->name(), inconclusive); unsignedLessThanZeroError(tok, var->name(), inconclusive);
else if (var && var->isPointer() && !Token::Match(tok->tokAt(3), "[.[]")) else if (var && var->isPointer() && !Token::Match(tok->tokAt(3), "[.[]"))
pointerLessThanZeroError(tok, inconclusive); pointerLessThanZeroError(tok, inconclusive);
} else if (Token::Match(tok, "0 <= %var%") && tok->tokAt(2)->varId() && !Token::Match(tok->tokAt(3), "+|-|*|/") && !Token::Match(tok->previous(), "+|-|<<|>>|~")) { } else if (Token::Match(tok, "0 <= %var%") && tok->tokAt(2)->varId() && !Token::Match(tok->tokAt(3), "+|-|*|/") && !Token::Match(tok->previous(), "+|-|<<|>>|~")) {
const Variable * var = symbolDatabase->getVariableFromVarId(tok->tokAt(2)->varId()); const Variable *var = tok->tokAt(2)->variable();
if (var && var->typeEndToken()->isUnsigned()) if (var && var->typeEndToken()->isUnsigned())
unsignedPositiveError(tok, var->name(), inconclusive); unsignedPositiveError(tok, var->name(), inconclusive);
else if (var && var->isPointer() && !Token::Match(tok->tokAt(3), "[.[]")) else if (var && var->isPointer() && !Token::Match(tok->tokAt(3), "[.[]"))
pointerPositiveError(tok, inconclusive); pointerPositiveError(tok, inconclusive);
} else if (Token::Match(tok, "%var% >= 0") && tok->varId() && !Token::Match(tok->previous(), "++|--|)|+|-|*|/|~|<<|>>") && !Token::Match(tok->tokAt(3), "+|-")) { } else if (Token::Match(tok, "%var% >= 0") && tok->varId() && !Token::Match(tok->previous(), "++|--|)|+|-|*|/|~|<<|>>") && !Token::Match(tok->tokAt(3), "+|-")) {
const Variable * var = symbolDatabase->getVariableFromVarId(tok->varId()); const Variable *var = tok->variable();
if (var && var->typeEndToken()->isUnsigned()) if (var && var->typeEndToken()->isUnsigned())
unsignedPositiveError(tok, var->name(), inconclusive); unsignedPositiveError(tok, var->name(), inconclusive);
else if (var && var->isPointer() && tok->strAt(-1) != "*") else if (var && var->isPointer() && tok->strAt(-1) != "*")
@ -3687,7 +3680,7 @@ void CheckOther::checkNegativeBitwiseShift()
if ((Token::Match(tok,"%var% >>|<< %num%") || Token::Match(tok,"%num% >>|<< %num%")) && !Token::Match(tok->previous(),">>|<<")) { if ((Token::Match(tok,"%var% >>|<< %num%") || Token::Match(tok,"%num% >>|<< %num%")) && !Token::Match(tok->previous(),">>|<<")) {
if (tok->isName()) { if (tok->isName()) {
const Variable* var = symbolDatabase->getVariableFromVarId(tok->varId()); const Variable *var = tok->variable();
if (var && var->typeStartToken()->isStandardType() && (tok->strAt(2))[0] == '-') if (var && var->typeStartToken()->isStandardType() && (tok->strAt(2))[0] == '-')
negativeBitwiseShiftError(tok); negativeBitwiseShiftError(tok);
} else { } else {
@ -3721,7 +3714,7 @@ void CheckOther::checkIncompleteArrayFill()
const Scope * scope = symbolDatabase->functionScopes[i]; const Scope * scope = symbolDatabase->functionScopes[i];
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, "memset|memcpy|memmove ( %var% ,") && Token::Match(tok->linkAt(1)->tokAt(-2), ", %num% )")) { if (Token::Match(tok, "memset|memcpy|memmove ( %var% ,") && Token::Match(tok->linkAt(1)->tokAt(-2), ", %num% )")) {
const Variable* var = symbolDatabase->getVariableFromVarId(tok->tokAt(2)->varId()); const Variable *var = tok->tokAt(2)->variable();
if (!var || !var->isArray() || var->dimensions().empty() || !var->dimension(0)) if (!var || !var->isArray() || var->dimensions().empty() || !var->dimension(0))
continue; continue;

View File

@ -775,7 +775,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
if (Token::Match(tok->previous(), "[;{}]")) { if (Token::Match(tok->previous(), "[;{}]")) {
for (const Token* tok2 = tok->next(); tok2; tok2 = tok2->next()) { for (const Token* tok2 = tok->next(); tok2; tok2 = tok2->next()) {
if (tok2->varId()) { if (tok2->varId()) {
const Variable* var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok2->varId()); const Variable *var = tok2->variable();
if (var && var->nameToken() == tok2) { // Declaration: Skip if (var && var->nameToken() == tok2) { // Declaration: Skip
tok = tok2->next(); tok = tok2->next();
if (Token::Match(tok, "( %var% )")) // Simple initialization through copy ctor if (Token::Match(tok, "( %var% )")) // Simple initialization through copy ctor
@ -889,7 +889,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const
// is it a user defined type? // is it a user defined type?
if (!type->isStandardType()) { if (!type->isStandardType()) {
const Variable* variable = _tokenizer->getSymbolDatabase()->getVariableFromVarId(start->varId()); const Variable *variable = start->variable();
if (!variable || !isRecordTypeWithoutSideEffects(variable->type())) if (!variable || !isRecordTypeWithoutSideEffects(variable->type()))
allocate = false; allocate = false;
} }
@ -1176,7 +1176,7 @@ void CheckUnusedVar::checkStructMemberUsage()
tok2 && tok2->next(); tok2 && tok2->next();
tok2 = Token::findmatch(tok2->next(), (structname + " %var%").c_str())) { tok2 = Token::findmatch(tok2->next(), (structname + " %var%").c_str())) {
const Variable *var = _tokenizer->getSymbolDatabase()->getVariableFromVarId(tok2->next()->varId()); const Variable *var = tok2->next()->variable();
if (var && (var->isExtern() || (var->isGlobal() && !var->isStatic()))) { if (var && (var->isExtern() || (var->isGlobal() && !var->isStatic()))) {
structname.clear(); structname.clear();
break; break;