speed up checks by caching commonly looked up stuff in the symbol database (CheckOther). Ticket: #4266

This commit is contained in:
Robert Reif 2012-11-15 07:11:45 +01:00 committed by Daniel Marjamäki
parent 04d04c33c2
commit 09eed80938
1 changed files with 232 additions and 205 deletions

View File

@ -1532,8 +1532,10 @@ void CheckOther::checkComparisonOfBoolWithInt()
return;
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
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
@ -1572,6 +1574,7 @@ void CheckOther::checkComparisonOfBoolWithInt()
}
}
}
}
}
void CheckOther::comparisonOfBoolWithIntError(const Token *tok, const std::string &expression, bool n0o1)
@ -1700,12 +1703,16 @@ static bool isSigned(const Variable* var)
void CheckOther::checkUnsignedDivision()
{
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
bool style = _settings->isEnabled("style");
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 = _tokenizer->tokens(); tok; tok = tok->next()) {
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "[).]")) // Don't check members or casted variables
continue;
@ -1728,6 +1735,7 @@ void CheckOther::checkUnsignedDivision()
else if (ifTok == tok)
ifTok = 0;
}
}
}
void CheckOther::udivError(const Token *tok, bool inconclusive)
@ -1746,13 +1754,18 @@ void CheckOther::checkMemsetZeroBytes()
if (!_settings->isEnabled("style"))
return;
for (const Token* tok = _tokenizer->tokens(); tok; 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 (Token::simpleMatch(tok, "memset (")) {
const Token* lastParamTok = tok->next()->link()->previous();
if (lastParamTok->str() == "0")
memsetZeroBytesError(tok, tok->strAt(2));
}
}
}
}
void CheckOther::memsetZeroBytesError(const Token *tok, const std::string &varname)
@ -1974,8 +1987,10 @@ void CheckOther::checkCharVariable()
return;
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
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());
@ -2018,6 +2033,7 @@ void CheckOther::checkCharVariable()
charBitOpError(tok->tokAt(4)); // This is an error..
}
}
}
}
void CheckOther::charArrayIndexError(const Token *tok)
@ -2099,8 +2115,10 @@ void CheckOther::constStatementError(const Token *tok, const std::string &type)
void CheckOther::strPlusChar()
{
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
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)
@ -2112,6 +2130,7 @@ void CheckOther::strPlusChar()
strPlusCharError(tok->next());
}
}
}
}
void CheckOther::strPlusCharError(const Token *tok)
@ -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,7 +2416,11 @@ void CheckOther::checkIncorrectStringCompare()
if (!_settings->isEnabled("style"))
return;
for (const Token *tok = _tokenizer->tokens(); tok; 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 (Token::Match(tok, ". substr ( %any% , %num% ) ==|!= %str%")) {
MathLib::bigint clen = MathLib::toLongNumber(tok->strAt(5));
std::size_t slen = Token::getStrLength(tok->tokAt(8));
@ -2428,6 +2445,7 @@ void CheckOther::checkIncorrectStringCompare()
incorrectStringBooleanError(tok->tokAt(2), tok->strAt(2));
}
}
}
}
void CheckOther::incorrectStringCompareError(const Token *tok, const std::string& func, const std::string &string)
@ -3195,12 +3213,18 @@ 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())) {
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));
}
}
}
}
void CheckOther::moduloAlwaysTrueFalseError(const Token* tok, const std::string& maxVal)
@ -3302,10 +3326,12 @@ 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 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()));
// Is variable a pointer?
@ -3313,6 +3339,7 @@ void CheckOther::checkAssignBoolToPointer()
assignBoolToPointerError(tok->next());
}
}
}
}
void CheckOther::assignBoolToPointerError(const Token *tok)
@ -3330,7 +3357,10 @@ void CheckOther::checkComparisonOfBoolExpressionWithInt()
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
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();
@ -3340,24 +3370,24 @@ void CheckOther::checkComparisonOfBoolExpressionWithInt()
const Token* numTok = 0;
const Token* opTok = 0;
char op = 0;
if (Token::Match(tok, "&&|%oror% %any% ) >|>=|==|!=|<=|< %any%")) {
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% >|>=|==|!=|<=|< ( %any% &&|%oror%")) {
} 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%")) {
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% >|>=|==|!=|<=|< ! %var%")) {
} else if (Token::Match(tok, "%any% %op% ! %var%") && tok->next()->isComparisonOp()) {
numTok = tok;
opTok = tok->next();
if (Token::Match(opTok, "<|>"))
@ -3372,6 +3402,7 @@ void CheckOther::checkComparisonOfBoolExpressionWithInt()
comparisonOfBoolExpressionWithIntError(tok, false);
}
}
}
}
void CheckOther::comparisonOfBoolExpressionWithIntError(const Token *tok, bool n0o1)
@ -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())