speed up checks by caching commonly looked up stuff in the symbol database (checkother, checkstl, checkunusedvar). Ticket: #4266

This commit is contained in:
Robert Reif 2012-11-16 06:50:49 +01:00 committed by Daniel Marjamäki
parent a2febc49d6
commit 6b8e83a181
3 changed files with 316 additions and 278 deletions

View File

@ -3180,8 +3180,10 @@ void CheckOther::checkSuspiciousStringCompare()
return; return;
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase(); const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
const std::size_t functions = symbolDatabase->functionScopes.size();
for (const Token* tok = _tokenizer->list.front(); tok && tok->tokAt(3); tok = tok->next()) { 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()->type() != Token::eComparisonOp) if (tok->next()->type() != Token::eComparisonOp)
continue; continue;
@ -3204,6 +3206,7 @@ void CheckOther::checkSuspiciousStringCompare()
} }
} }
} }
}
void CheckOther::suspiciousStringCompareError(const Token* tok, const std::string& var) void CheckOther::suspiciousStringCompareError(const Token* tok, const std::string& var)
{ {
@ -3568,7 +3571,11 @@ void CheckOther::checkNegativeBitwiseShift()
{ {
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); 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,"%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 = symbolDatabase->getVariableFromVarId(tok->varId());
@ -3581,6 +3588,7 @@ void CheckOther::checkNegativeBitwiseShift()
} }
} }
} }
}
void CheckOther::negativeBitwiseShiftError(const Token *tok) void CheckOther::negativeBitwiseShiftError(const Token *tok)
@ -3599,7 +3607,10 @@ void CheckOther::checkIncompleteArrayFill()
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
for (const Token* tok = _tokenizer->list.front(); 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, "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 = symbolDatabase->getVariableFromVarId(tok->tokAt(2)->varId());
if (!var || !var->isArray() || var->dimensions().empty() || !var->dimension(0)) if (!var || !var->isArray() || var->dimensions().empty() || !var->dimension(0))
@ -3615,6 +3626,7 @@ void CheckOther::checkIncompleteArrayFill()
} }
} }
} }
}
void CheckOther::incompleteArrayFillError(const Token* tok, const std::string& buffer, const std::string& function, bool boolean) void CheckOther::incompleteArrayFillError(const Token* tok, const std::string& buffer, const std::string& function, bool boolean)
{ {

View File

@ -238,7 +238,11 @@ void CheckStl::mismatchingContainers()
static const std::string pattern2 = pattern1x1_1 + pattern1x1_2; static const std::string pattern2 = pattern1x1_1 + pattern1x1_2;
// Check if different containers are used in various calls of standard functions // Check if different containers are used in various calls of standard functions
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 ii = 0; ii < functions; ++ii) {
const Scope * scope = symbolDatabase->functionScopes[ii];
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (!Token::Match(tok, "std :: %type% ( !!)")) if (!Token::Match(tok, "std :: %type% ( !!)"))
continue; continue;
const Token* arg1 = tok->tokAt(4); const Token* arg1 = tok->tokAt(4);
@ -269,13 +273,14 @@ void CheckStl::mismatchingContainers()
tok = arg1->linkAt(-1); tok = arg1->linkAt(-1);
} }
} }
}
void CheckStl::stlOutOfBounds() void CheckStl::stlOutOfBounds()
{ {
const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase(); const SymbolDatabase* const symbolDatabase = _tokenizer->getSymbolDatabase();
// Scan through all tokens.. // Scan through all scopes..
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) { for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.begin(); i != symbolDatabase->scopeList.end(); ++i) {
const Token* const tok = i->classDef; const Token* const tok = i->classDef;
// only interested in "for" loops // only interested in "for" loops
@ -511,7 +516,11 @@ void CheckStl::erase()
void CheckStl::pushback() void CheckStl::pushback()
{ {
// Pointer can become invalid after push_back, push_front, reserve or resize.. // Pointer can become invalid after push_back, push_front, reserve or resize..
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { const SymbolDatabase* const 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, "%var% = & %var% [")) { if (Token::Match(tok, "%var% = & %var% [")) {
// Variable id for pointer // Variable id for pointer
const unsigned int pointerId(tok->varId()); const unsigned int pointerId(tok->varId());
@ -553,9 +562,12 @@ void CheckStl::pushback()
} }
} }
} }
}
// Iterator becomes invalid after reserve, resize, insert, push_back or push_front.. // Iterator becomes invalid after reserve, resize, insert, push_back or push_front..
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { 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, "vector <")) if (!Token::simpleMatch(tok, "vector <"))
continue; continue;
@ -674,6 +686,7 @@ void CheckStl::pushback()
} }
} }
} }
}
// Error message for bad iterator usage.. // Error message for bad iterator usage..
@ -697,7 +710,11 @@ void CheckStl::stlBoundries()
// containers (not the vector).. // containers (not the vector)..
static const char STL_CONTAINER_LIST[] = "bitset|deque|list|forward_list|map|multimap|multiset|priority_queue|queue|set|stack|hash_map|hash_multimap|hash_set|unordered_map|unordered_multimap|unordered_set|unordered_multiset"; static const char STL_CONTAINER_LIST[] = "bitset|deque|list|forward_list|map|multimap|multiset|priority_queue|queue|set|stack|hash_map|hash_multimap|hash_set|unordered_map|unordered_multimap|unordered_set|unordered_multiset";
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { const SymbolDatabase* const 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()) {
// Declaring iterator.. // Declaring iterator..
if (tok->str() == "<" && Token::Match(tok->previous(), STL_CONTAINER_LIST)) { if (tok->str() == "<" && Token::Match(tok->previous(), STL_CONTAINER_LIST)) {
const std::string& container_name(tok->strAt(-1)); const std::string& container_name(tok->strAt(-1));
@ -727,6 +744,7 @@ void CheckStl::stlBoundries()
} }
} }
} }
}
// Error message for bad boundary usage.. // Error message for bad boundary usage..
void CheckStl::stlBoundriesError(const Token *tok, const std::string &container_name) void CheckStl::stlBoundriesError(const Token *tok, const std::string &container_name)
@ -916,7 +934,11 @@ void CheckStl::size()
if (!_settings->isEnabled("performance")) if (!_settings->isEnabled("performance"))
return; return;
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { const SymbolDatabase* const 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, "%var% . size ( )") || if (Token::Match(tok, "%var% . size ( )") ||
Token::Match(tok, "%var% . %var% . size ( )")) { Token::Match(tok, "%var% . %var% . size ( )")) {
const Token *tok1 = tok; const Token *tok1 = tok;
@ -972,6 +994,7 @@ void CheckStl::size()
} }
} }
} }
}
void CheckStl::sizeError(const Token *tok) void CheckStl::sizeError(const Token *tok)
{ {
@ -1358,8 +1381,10 @@ void CheckStl::uselessCalls()
return; return;
const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase(); const SymbolDatabase* symbolDatabase = _tokenizer->getSymbolDatabase();
const std::size_t functions = symbolDatabase->functionScopes.size();
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { 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->varId() && Token::Match(tok, "%var% . compare|find|rfind|find_first_not_of|find_first_of|find_last_not_of|find_last_of ( %var% [,)]") && if (tok->varId() && Token::Match(tok, "%var% . compare|find|rfind|find_first_not_of|find_first_of|find_last_not_of|find_last_of ( %var% [,)]") &&
tok->varId() == tok->tokAt(4)->varId() && style) { tok->varId() == tok->tokAt(4)->varId() && style) {
uselessCallsReturnValueError(tok->tokAt(4), tok->str(), tok->strAt(2)); uselessCallsReturnValueError(tok->tokAt(4), tok->str(), tok->strAt(2));
@ -1380,6 +1405,7 @@ void CheckStl::uselessCalls()
uselessCallsRemoveError(tok->next(), tok->strAt(3)); uselessCallsRemoveError(tok->next(), tok->strAt(3));
} }
} }
}
void CheckStl::uselessCallsReturnValueError(const Token *tok, const std::string &varname, const std::string &function) void CheckStl::uselessCallsReturnValueError(const Token *tok, const std::string &varname, const std::string &function)

View File

@ -968,10 +968,10 @@ void CheckUnusedVar::checkFunctionVariableUsage()
// Parse all executing scopes.. // Parse all executing scopes..
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
for (std::list<Scope>::const_iterator scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) {
// only check functions // only check functions
if (scope->type != Scope::eFunction) const std::size_t functions = symbolDatabase->functionScopes.size();
continue; for (std::size_t i = 0; i < functions; ++i) {
const Scope * scope = symbolDatabase->functionScopes[i];
// varId, usage {read, write, modified} // varId, usage {read, write, modified}
Variables variables; Variables variables;