speed up checks by caching commonly looked up stuff in the symbol database (CheckOther). Ticket: #4266
This commit is contained in:
parent
04d04c33c2
commit
09eed80938
|
@ -1532,43 +1532,46 @@ void CheckOther::checkComparisonOfBoolWithInt()
|
|||
return;
|
||||
|
||||
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
if (tok->next() && tok->next()->type() == Token::eComparisonOp && (!tok->previous() || !tok->previous()->isArithmeticalOp()) && (!tok->tokAt(3) || !tok->tokAt(3)->isArithmeticalOp())) {
|
||||
const Token* const right = tok->tokAt(2);
|
||||
if ((tok->varId() && right->isNumber()) || (tok->isNumber() && right->varId())) { // Comparing variable with number
|
||||
const Token* varTok = tok;
|
||||
const Token* numTok = right;
|
||||
if (tok->isNumber() && right->varId()) // num with var
|
||||
std::swap(varTok, numTok);
|
||||
if (isBool(symbolDatabase->getVariableFromVarId(varTok->varId())) && // Variable has to be a boolean
|
||||
((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
|
||||
comparisonOfBoolWithIntError(varTok, numTok->str(), tok->strAt(1) == "==" || tok->strAt(1) == "!=");
|
||||
}
|
||||
} 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
|
||||
comparisonOfBoolWithIntError(right, tok->str(), false);
|
||||
} else if (tok->strAt(1) != "==" && tok->strAt(1) != "!=") {
|
||||
comparisonOfBoolWithInvalidComparator(right, tok->str());
|
||||
}
|
||||
} 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
|
||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||
if (tok->next() && tok->next()->type() == Token::eComparisonOp && (!tok->previous() || !tok->previous()->isArithmeticalOp()) && (!tok->tokAt(3) || !tok->tokAt(3)->isArithmeticalOp())) {
|
||||
const Token* const right = tok->tokAt(2);
|
||||
if ((tok->varId() && right->isNumber()) || (tok->isNumber() && right->varId())) { // Comparing variable with number
|
||||
const Token* varTok = tok;
|
||||
const Token* numTok = right;
|
||||
if (tok->isNumber() && right->varId()) // num with var
|
||||
std::swap(varTok, numTok);
|
||||
if (isBool(symbolDatabase->getVariableFromVarId(varTok->varId())) && // Variable has to be a boolean
|
||||
((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
|
||||
comparisonOfBoolWithIntError(varTok, numTok->str(), tok->strAt(1) == "==" || tok->strAt(1) == "!=");
|
||||
}
|
||||
} 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
|
||||
comparisonOfBoolWithIntError(right, tok->str(), false);
|
||||
} else if (tok->strAt(1) != "==" && tok->strAt(1) != "!=") {
|
||||
comparisonOfBoolWithInvalidComparator(right, tok->str());
|
||||
}
|
||||
} 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
|
||||
comparisonOfBoolWithIntError(tok, right->str(), false);
|
||||
} else if (tok->strAt(1) != "==" && tok->strAt(1) != "!=") {
|
||||
comparisonOfBoolWithInvalidComparator(right, tok->str());
|
||||
}
|
||||
} else if (tok->isNumber() && right->isBoolean()) { // number constant with boolean constant
|
||||
comparisonOfBoolWithIntError(tok, right->str(), false);
|
||||
} else if (tok->strAt(1) != "==" && tok->strAt(1) != "!=") {
|
||||
comparisonOfBoolWithInvalidComparator(right, tok->str());
|
||||
} else if (tok->isBoolean() && right->isNumber()) { // number constant with boolean constant
|
||||
comparisonOfBoolWithIntError(tok, tok->str(), false);
|
||||
} 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* var2 = symbolDatabase->getVariableFromVarId(tok->varId());
|
||||
if (isBool(var1) && isNonBoolStdType(var2)) // Comparing boolean with non-bool standard type
|
||||
comparisonOfBoolWithIntError(tok, var1->name(), false);
|
||||
else if (isNonBoolStdType(var1) && isBool(var2)) // Comparing non-bool standard type with boolean
|
||||
comparisonOfBoolWithIntError(tok, var2->name(), false);
|
||||
}
|
||||
} else if (tok->isNumber() && right->isBoolean()) { // number constant with boolean constant
|
||||
comparisonOfBoolWithIntError(tok, right->str(), false);
|
||||
} else if (tok->isBoolean() && right->isNumber()) { // number constant with boolean constant
|
||||
comparisonOfBoolWithIntError(tok, tok->str(), false);
|
||||
} 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* var2 = symbolDatabase->getVariableFromVarId(tok->varId());
|
||||
if (isBool(var1) && isNonBoolStdType(var2)) // Comparing boolean with non-bool standard type
|
||||
comparisonOfBoolWithIntError(tok, var1->name(), false);
|
||||
else if (isNonBoolStdType(var1) && isBool(var2)) // Comparing non-bool standard type with boolean
|
||||
comparisonOfBoolWithIntError(tok, var2->name(), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1700,33 +1703,38 @@ static bool isSigned(const Variable* var)
|
|||
|
||||
void CheckOther::checkUnsignedDivision()
|
||||
{
|
||||
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
bool style = _settings->isEnabled("style");
|
||||
|
||||
const Token* ifTok = 0;
|
||||
// Check for "ivar / uvar" and "uvar / ivar"
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
if (Token::Match(tok, "[).]")) // Don't check members or casted variables
|
||||
continue;
|
||||
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
const Token* ifTok = 0;
|
||||
// Check for "ivar / uvar" and "uvar / ivar"
|
||||
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||
|
||||
if (Token::Match(tok->next(), "%var% / %num%")) {
|
||||
if (tok->strAt(3)[0] == '-' && isUnsigned(symbolDatabase->getVariableFromVarId(tok->next()->varId()))) {
|
||||
udivError(tok->next(), false);
|
||||
}
|
||||
} else if (Token::Match(tok->next(), "%num% / %var%")) {
|
||||
if (tok->strAt(1)[0] == '-' && isUnsigned(symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId()))) {
|
||||
udivError(tok->next(), false);
|
||||
}
|
||||
} else if (Token::Match(tok->next(), "%var% / %var%") && _settings->inconclusive && style && !ifTok) {
|
||||
const Variable* var1 = symbolDatabase->getVariableFromVarId(tok->next()->varId());
|
||||
const Variable* var2 = symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId());
|
||||
if ((isUnsigned(var1) && isSigned(var2)) || (isUnsigned(var2) && isSigned(var1))) {
|
||||
udivError(tok->next(), true);
|
||||
}
|
||||
} else if (!ifTok && Token::simpleMatch(tok, "if ("))
|
||||
ifTok = tok->next()->link()->next()->link();
|
||||
else if (ifTok == tok)
|
||||
ifTok = 0;
|
||||
if (Token::Match(tok, "[).]")) // Don't check members or casted variables
|
||||
continue;
|
||||
|
||||
if (Token::Match(tok->next(), "%var% / %num%")) {
|
||||
if (tok->strAt(3)[0] == '-' && isUnsigned(symbolDatabase->getVariableFromVarId(tok->next()->varId()))) {
|
||||
udivError(tok->next(), false);
|
||||
}
|
||||
} else if (Token::Match(tok->next(), "%num% / %var%")) {
|
||||
if (tok->strAt(1)[0] == '-' && isUnsigned(symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId()))) {
|
||||
udivError(tok->next(), false);
|
||||
}
|
||||
} else if (Token::Match(tok->next(), "%var% / %var%") && _settings->inconclusive && style && !ifTok) {
|
||||
const Variable* var1 = symbolDatabase->getVariableFromVarId(tok->next()->varId());
|
||||
const Variable* var2 = symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId());
|
||||
if ((isUnsigned(var1) && isSigned(var2)) || (isUnsigned(var2) && isSigned(var1))) {
|
||||
udivError(tok->next(), true);
|
||||
}
|
||||
} else if (!ifTok && Token::simpleMatch(tok, "if ("))
|
||||
ifTok = tok->next()->link()->next()->link();
|
||||
else if (ifTok == tok)
|
||||
ifTok = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1746,11 +1754,16 @@ void CheckOther::checkMemsetZeroBytes()
|
|||
if (!_settings->isEnabled("style"))
|
||||
return;
|
||||
|
||||
for (const Token* tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
if (Token::simpleMatch(tok, "memset (")) {
|
||||
const Token* lastParamTok = tok->next()->link()->previous();
|
||||
if (lastParamTok->str() == "0")
|
||||
memsetZeroBytesError(tok, tok->strAt(2));
|
||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||
if (Token::simpleMatch(tok, "memset (")) {
|
||||
const Token* lastParamTok = tok->next()->link()->previous();
|
||||
if (lastParamTok->str() == "0")
|
||||
memsetZeroBytesError(tok, tok->strAt(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1974,48 +1987,51 @@ void CheckOther::checkCharVariable()
|
|||
return;
|
||||
|
||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
if ((tok->str() != ".") && Token::Match(tok->next(), "%var% [ %var% ]")) {
|
||||
const Variable* arrayvar = symbolDatabase->getVariableFromVarId(tok->next()->varId());
|
||||
const Variable* indexvar = symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId());
|
||||
const MathLib::bigint arraysize = (arrayvar && arrayvar->isArray()) ? arrayvar->dimension(0U) : 0;
|
||||
if (isSignedChar(indexvar) && arraysize > 0x80)
|
||||
charArrayIndexError(tok->next());
|
||||
}
|
||||
|
||||
else if (Token::Match(tok, "[;{}] %var% = %any% [&^|] %any% ;")) {
|
||||
// is a char variable used in the calculation?
|
||||
if (!isSignedChar(symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId())) &&
|
||||
!isSignedChar(symbolDatabase->getVariableFromVarId(tok->tokAt(5)->varId())))
|
||||
continue;
|
||||
|
||||
// it's ok with a bitwise and where the other operand is 0xff or less..
|
||||
if (tok->strAt(4) == "&") {
|
||||
if (tok->tokAt(3)->isNumber() && MathLib::isGreater("0x100", tok->strAt(3)))
|
||||
continue;
|
||||
if (tok->tokAt(5)->isNumber() && MathLib::isGreater("0x100", tok->strAt(5)))
|
||||
continue;
|
||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
|
||||
if ((tok->str() != ".") && Token::Match(tok->next(), "%var% [ %var% ]")) {
|
||||
const Variable* arrayvar = symbolDatabase->getVariableFromVarId(tok->next()->varId());
|
||||
const Variable* indexvar = symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId());
|
||||
const MathLib::bigint arraysize = (arrayvar && arrayvar->isArray()) ? arrayvar->dimension(0U) : 0;
|
||||
if (isSignedChar(indexvar) && arraysize > 0x80)
|
||||
charArrayIndexError(tok->next());
|
||||
}
|
||||
|
||||
// is the result stored in a short|int|long?
|
||||
const Variable *var = symbolDatabase->getVariableFromVarId(tok->next()->varId());
|
||||
if (var && Token::Match(var->typeStartToken(), "short|int|long") && !var->isPointer() && !var->isArray())
|
||||
charBitOpError(tok->tokAt(4)); // This is an error..
|
||||
}
|
||||
else if (Token::Match(tok, "[;{}] %var% = %any% [&^|] %any% ;")) {
|
||||
// is a char variable used in the calculation?
|
||||
if (!isSignedChar(symbolDatabase->getVariableFromVarId(tok->tokAt(3)->varId())) &&
|
||||
!isSignedChar(symbolDatabase->getVariableFromVarId(tok->tokAt(5)->varId())))
|
||||
continue;
|
||||
|
||||
else if (Token::Match(tok, "[;{}] %var% = %any% [&^|] ( * %var% ) ;")) {
|
||||
const Variable* var = symbolDatabase->getVariableFromVarId(tok->tokAt(7)->varId());
|
||||
if (!var || !var->isPointer() || var->typeStartToken()->str() != "char" || var->typeStartToken()->isUnsigned())
|
||||
continue;
|
||||
// it's ok with a bitwise and where the other operand is 0xff or less..
|
||||
if (tok->strAt(4) == "&" && tok->tokAt(3)->isNumber() && MathLib::isGreater("0x100", tok->strAt(3)))
|
||||
continue;
|
||||
// it's ok with a bitwise and where the other operand is 0xff or less..
|
||||
if (tok->strAt(4) == "&") {
|
||||
if (tok->tokAt(3)->isNumber() && MathLib::isGreater("0x100", tok->strAt(3)))
|
||||
continue;
|
||||
if (tok->tokAt(5)->isNumber() && MathLib::isGreater("0x100", tok->strAt(5)))
|
||||
continue;
|
||||
}
|
||||
|
||||
// is the result stored in a short|int|long?
|
||||
var = symbolDatabase->getVariableFromVarId(tok->next()->varId());
|
||||
if (var && Token::Match(var->typeStartToken(), "short|int|long") && !var->isPointer() && !var->isArray())
|
||||
charBitOpError(tok->tokAt(4)); // This is an error..
|
||||
// is the result stored in a short|int|long?
|
||||
const Variable *var = symbolDatabase->getVariableFromVarId(tok->next()->varId());
|
||||
if (var && Token::Match(var->typeStartToken(), "short|int|long") && !var->isPointer() && !var->isArray())
|
||||
charBitOpError(tok->tokAt(4)); // This is an error..
|
||||
}
|
||||
|
||||
else if (Token::Match(tok, "[;{}] %var% = %any% [&^|] ( * %var% ) ;")) {
|
||||
const Variable* var = symbolDatabase->getVariableFromVarId(tok->tokAt(7)->varId());
|
||||
if (!var || !var->isPointer() || var->typeStartToken()->str() != "char" || var->typeStartToken()->isUnsigned())
|
||||
continue;
|
||||
// it's ok with a bitwise and where the other operand is 0xff or less..
|
||||
if (tok->strAt(4) == "&" && tok->tokAt(3)->isNumber() && MathLib::isGreater("0x100", tok->strAt(3)))
|
||||
continue;
|
||||
|
||||
// is the result stored in a short|int|long?
|
||||
var = symbolDatabase->getVariableFromVarId(tok->next()->varId());
|
||||
if (var && Token::Match(var->typeStartToken(), "short|int|long") && !var->isPointer() && !var->isArray())
|
||||
charBitOpError(tok->tokAt(4)); // This is an error..
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2099,17 +2115,20 @@ void CheckOther::constStatementError(const Token *tok, const std::string &type)
|
|||
void CheckOther::strPlusChar()
|
||||
{
|
||||
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||
if (Token::Match(tok, "[=(] %str% + %any%")) {
|
||||
// char constant..
|
||||
if (tok->tokAt(3)->type() == Token::eChar)
|
||||
strPlusCharError(tok->next());
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
if (Token::Match(tok, "[=(] %str% + %any%")) {
|
||||
// char constant..
|
||||
if (tok->tokAt(3)->type() == Token::eChar)
|
||||
strPlusCharError(tok->next());
|
||||
|
||||
// char variable..
|
||||
unsigned int varid = tok->tokAt(3)->varId();
|
||||
if (isChar(symbolDatabase->getVariableFromVarId(varid)))
|
||||
strPlusCharError(tok->next());
|
||||
// char variable..
|
||||
unsigned int varid = tok->tokAt(3)->varId();
|
||||
if (isChar(symbolDatabase->getVariableFromVarId(varid)))
|
||||
strPlusCharError(tok->next());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2145,14 +2164,11 @@ void CheckOther::zerodivError(const Token *tok)
|
|||
//---------------------------------------------------------------------------
|
||||
void CheckOther::checkMathFunctions()
|
||||
{
|
||||
const SymbolDatabase *db = _tokenizer->getSymbolDatabase();
|
||||
|
||||
std::list<Scope>::const_iterator scope;
|
||||
for (scope = db->scopeList.begin(); scope != db->scopeList.end(); ++scope) {
|
||||
if (scope->type != Scope::eFunction)
|
||||
continue;
|
||||
|
||||
for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) {
|
||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||
if (tok->varId())
|
||||
continue;
|
||||
if (Token::Match(tok, "log|log10 ( %num% )")) {
|
||||
|
@ -2240,12 +2256,9 @@ void CheckOther::checkMisusedScopedObject()
|
|||
}
|
||||
|
||||
const SymbolDatabase * const symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
||||
for (std::list<Scope>::const_iterator scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) {
|
||||
// only check functions
|
||||
if (scope->type != Scope::eFunction)
|
||||
continue;
|
||||
|
||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
for (const Token *tok = scope->classStart; tok && tok != scope->classEnd; tok = tok->next()) {
|
||||
if (Token::Match(tok, "[;{}] %var% (")
|
||||
&& Token::simpleMatch(tok->linkAt(2), ") ;")
|
||||
|
@ -2403,29 +2416,34 @@ void CheckOther::checkIncorrectStringCompare()
|
|||
if (!_settings->isEnabled("style"))
|
||||
return;
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
if (Token::Match(tok, ". substr ( %any% , %num% ) ==|!= %str%")) {
|
||||
MathLib::bigint clen = MathLib::toLongNumber(tok->strAt(5));
|
||||
std::size_t slen = Token::getStrLength(tok->tokAt(8));
|
||||
if (clen != (int)slen) {
|
||||
incorrectStringCompareError(tok->next(), "substr", tok->strAt(8));
|
||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||
if (Token::Match(tok, ". substr ( %any% , %num% ) ==|!= %str%")) {
|
||||
MathLib::bigint clen = MathLib::toLongNumber(tok->strAt(5));
|
||||
std::size_t slen = Token::getStrLength(tok->tokAt(8));
|
||||
if (clen != (int)slen) {
|
||||
incorrectStringCompareError(tok->next(), "substr", tok->strAt(8));
|
||||
}
|
||||
} else if (Token::Match(tok, "%str% ==|!= %var% . substr ( %any% , %num% )")) {
|
||||
MathLib::bigint clen = MathLib::toLongNumber(tok->strAt(8));
|
||||
std::size_t slen = Token::getStrLength(tok);
|
||||
if (clen != (int)slen) {
|
||||
incorrectStringCompareError(tok->next(), "substr", tok->str());
|
||||
}
|
||||
} else if (Token::Match(tok, "&&|%oror% %str% &&|%oror%|)")) {
|
||||
// assert(condition && "debug message") would be considered a fp.
|
||||
if (tok->str() == "&&" && tok->strAt(2) == ")" && tok->linkAt(2)->previous()->str() == "assert")
|
||||
continue;
|
||||
incorrectStringBooleanError(tok->next(), tok->strAt(1));
|
||||
} else if (Token::Match(tok, "if|while|assert ( %str% &&|%oror%|)")) {
|
||||
// assert("debug message" && condition) would be considered a fp.
|
||||
if (tok->strAt(3) == "&&" && tok->str() == "assert")
|
||||
continue;
|
||||
incorrectStringBooleanError(tok->tokAt(2), tok->strAt(2));
|
||||
}
|
||||
} else if (Token::Match(tok, "%str% ==|!= %var% . substr ( %any% , %num% )")) {
|
||||
MathLib::bigint clen = MathLib::toLongNumber(tok->strAt(8));
|
||||
std::size_t slen = Token::getStrLength(tok);
|
||||
if (clen != (int)slen) {
|
||||
incorrectStringCompareError(tok->next(), "substr", tok->str());
|
||||
}
|
||||
} else if (Token::Match(tok, "&&|%oror% %str% &&|%oror%|)")) {
|
||||
// assert(condition && "debug message") would be considered a fp.
|
||||
if (tok->str() == "&&" && tok->strAt(2) == ")" && tok->linkAt(2)->previous()->str() == "assert")
|
||||
continue;
|
||||
incorrectStringBooleanError(tok->next(), tok->strAt(1));
|
||||
} else if (Token::Match(tok, "if|while|assert ( %str% &&|%oror%|)")) {
|
||||
// assert("debug message" && condition) would be considered a fp.
|
||||
if (tok->strAt(3) == "&&" && tok->str() == "assert")
|
||||
continue;
|
||||
incorrectStringBooleanError(tok->tokAt(2), tok->strAt(2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3195,10 +3213,16 @@ void CheckOther::suspiciousStringCompareError(const Token* tok, const std::strin
|
|||
//-----------------------------------------------------------------------------
|
||||
void CheckOther::checkModuloAlwaysTrueFalse()
|
||||
{
|
||||
for (const Token* tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
if (Token::Match(tok, "% %num% ==|!=|<=|<|>|>= %num%") && (!tok->tokAt(4) || !tok->tokAt(4)->isArithmeticalOp())) {
|
||||
if (MathLib::isLessEqual(tok->strAt(1), tok->strAt(3)))
|
||||
moduloAlwaysTrueFalseError(tok, tok->strAt(1));
|
||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||
if ((Token::Match(tok, "% %num% %op% %num%") && tok->tokAt(2)->isComparisonOp()) &&
|
||||
(!tok->tokAt(4) || !tok->tokAt(4)->isArithmeticalOp())) {
|
||||
if (MathLib::isLessEqual(tok->strAt(1), tok->strAt(3)))
|
||||
moduloAlwaysTrueFalseError(tok, tok->strAt(1));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3302,15 +3326,18 @@ void CheckOther::divideSizeofError(const Token *tok)
|
|||
//-----------------------------------------------------------------------------
|
||||
void CheckOther::checkAssignBoolToPointer()
|
||||
{
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
if (Token::Match(tok, "!!* %var% = %bool% ;")) {
|
||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
for (const Token* tok = scope->classStart; tok != scope->classEnd; tok = tok->next()) {
|
||||
if (Token::Match(tok, "!!* %var% = %bool% ;")) {
|
||||
const Variable *var1(symbolDatabase->getVariableFromVarId(tok->next()->varId()));
|
||||
|
||||
const Variable *var1(symbolDatabase->getVariableFromVarId(tok->next()->varId()));
|
||||
|
||||
// Is variable a pointer?
|
||||
if (var1 && var1->isPointer())
|
||||
assignBoolToPointerError(tok->next());
|
||||
// Is variable a pointer?
|
||||
if (var1 && var1->isPointer())
|
||||
assignBoolToPointerError(tok->next());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3330,46 +3357,50 @@ void CheckOther::checkComparisonOfBoolExpressionWithInt()
|
|||
|
||||
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
// Skip template parameters
|
||||
if (tok->str() == "<" && tok->link()) {
|
||||
tok = tok->link();
|
||||
continue;
|
||||
}
|
||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
|
||||
// Skip template parameters
|
||||
if (tok->str() == "<" && tok->link()) {
|
||||
tok = tok->link();
|
||||
continue;
|
||||
}
|
||||
|
||||
const Token* numTok = 0;
|
||||
const Token* opTok = 0;
|
||||
char op = 0;
|
||||
if (Token::Match(tok, "&&|%oror% %any% ) >|>=|==|!=|<=|< %any%")) {
|
||||
numTok = tok->tokAt(4);
|
||||
opTok = tok->tokAt(3);
|
||||
if (Token::Match(opTok, "<|>"))
|
||||
op = opTok->str()[0];
|
||||
} else if (Token::Match(tok, "%any% >|>=|==|!=|<=|< ( %any% &&|%oror%")) {
|
||||
numTok = tok;
|
||||
opTok = tok->next();
|
||||
if (Token::Match(opTok, "<|>"))
|
||||
op = opTok->str()[0]=='>'?'<':'>';
|
||||
}
|
||||
const Token* numTok = 0;
|
||||
const Token* opTok = 0;
|
||||
char op = 0;
|
||||
if (Token::Match(tok, "&&|%oror% %any% ) %op% %any%") && tok->tokAt(3)->isComparisonOp()) {
|
||||
numTok = tok->tokAt(4);
|
||||
opTok = tok->tokAt(3);
|
||||
if (Token::Match(opTok, "<|>"))
|
||||
op = opTok->str()[0];
|
||||
} else if (Token::Match(tok, "%any% %op% ( %any% &&|%oror%") && tok->next()->isComparisonOp()) {
|
||||
numTok = tok;
|
||||
opTok = tok->next();
|
||||
if (Token::Match(opTok, "<|>"))
|
||||
op = opTok->str()[0]=='>'?'<':'>';
|
||||
}
|
||||
|
||||
else if (Token::Match(tok, "! %var% >|>=|==|!=|<=|< %any%")) {
|
||||
numTok = tok->tokAt(3);
|
||||
opTok = tok->tokAt(2);
|
||||
if (Token::Match(opTok, "<|>"))
|
||||
op = opTok->str()[0];
|
||||
} else if (Token::Match(tok, "%any% >|>=|==|!=|<=|< ! %var%")) {
|
||||
numTok = tok;
|
||||
opTok = tok->next();
|
||||
if (Token::Match(opTok, "<|>"))
|
||||
op = opTok->str()[0]=='>'?'<':'>';
|
||||
}
|
||||
else if (Token::Match(tok, "! %var% %op% %any%") && tok->tokAt(2)->isComparisonOp()) {
|
||||
numTok = tok->tokAt(3);
|
||||
opTok = tok->tokAt(2);
|
||||
if (Token::Match(opTok, "<|>"))
|
||||
op = opTok->str()[0];
|
||||
} else if (Token::Match(tok, "%any% %op% ! %var%") && tok->next()->isComparisonOp()) {
|
||||
numTok = tok;
|
||||
opTok = tok->next();
|
||||
if (Token::Match(opTok, "<|>"))
|
||||
op = opTok->str()[0]=='>'?'<':'>';
|
||||
}
|
||||
|
||||
if (numTok && opTok) {
|
||||
if (numTok->isNumber()) {
|
||||
if (((numTok->str() != "0" && numTok->str() != "1") || !Token::Match(opTok, "!=|==")) && !((op == '<' && numTok->str() == "1") || (op == '>' && numTok->str() == "0")))
|
||||
comparisonOfBoolExpressionWithIntError(tok, true);
|
||||
} else if (isNonBoolStdType(symbolDatabase->getVariableFromVarId(numTok->varId())))
|
||||
comparisonOfBoolExpressionWithIntError(tok, false);
|
||||
if (numTok && opTok) {
|
||||
if (numTok->isNumber()) {
|
||||
if (((numTok->str() != "0" && numTok->str() != "1") || !Token::Match(opTok, "!=|==")) && !((op == '<' && numTok->str() == "1") || (op == '>' && numTok->str() == "0")))
|
||||
comparisonOfBoolExpressionWithIntError(tok, true);
|
||||
} else if (isNonBoolStdType(symbolDatabase->getVariableFromVarId(numTok->varId())))
|
||||
comparisonOfBoolExpressionWithIntError(tok, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3399,15 +3430,11 @@ void CheckOther::checkSignOfUnsignedVariable()
|
|||
|
||||
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
|
||||
|
||||
std::list<Scope>::const_iterator scope;
|
||||
|
||||
for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) {
|
||||
// only check functions
|
||||
if (scope->type != Scope::eFunction)
|
||||
continue;
|
||||
|
||||
const std::size_t functions = symbolDatabase->functionScopes.size();
|
||||
for (std::size_t i = 0; i < functions; ++i) {
|
||||
const Scope * scope = symbolDatabase->functionScopes[i];
|
||||
// check all the code in the function
|
||||
for (const Token *tok = scope->classStart; tok && 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), "+|-")) {
|
||||
const Variable * var = symbolDatabase->getVariableFromVarId(tok->varId());
|
||||
if (var && var->typeEndToken()->isUnsigned())
|
||||
|
|
Loading…
Reference in New Issue