From f2d69acbfdc4068eefb7bf38f0c6415b95fb042e Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Thu, 16 Dec 2010 19:04:47 +0100 Subject: [PATCH] Symbol database: reuse in CheckOther. Ticket: #2318 --- lib/checkother.cpp | 145 ++++++++++++++++++++++------------------- lib/symboldatabase.cpp | 53 +++++++++++++-- 2 files changed, 128 insertions(+), 70 deletions(-) diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 8aa8cc49a..d441f2400 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -20,6 +20,7 @@ //--------------------------------------------------------------------------- #include "checkother.h" #include "mathlib.h" +#include "symboldatabase.h" #include // std::isupper #include // fabs() @@ -1192,17 +1193,20 @@ void CheckOther::functionVariableUsage() return; // Parse all executing scopes.. - for (const Token *token = Token::findmatch(_tokenizer->tokens(), ") const| {"); token;) + SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); + + std::list::const_iterator i; + + for (i = symbolDatabase->spaceInfoList.begin(); i != symbolDatabase->spaceInfoList.end(); ++i) { - // goto "{" - while (token->str() != "{") - token = token->next(); + SymbolDatabase::SpaceInfo *info = *i; + + // only check functions + if (info->type != SymbolDatabase::SpaceInfo::Function) + continue; // First token for the current scope.. - const Token *const tok1 = token; - - // Find next scope that will be checked next time.. - token = Token::findmatch(token->link(), ") const| {"); + const Token *const tok1 = info->classStart; // varId, usage {read, write, modified} Variables variables; @@ -1820,74 +1824,83 @@ void CheckOther::checkVariableScope() if (!_settings->_checkCodingStyle) return; - // Walk through all tokens.. - bool func = false; - int indentlevel = 0; - for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) + SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); + + std::list::const_iterator i; + + for (i = symbolDatabase->spaceInfoList.begin(); i != symbolDatabase->spaceInfoList.end(); ++i) { - // Skip class and struct declarations.. - if ((tok->str() == "class") || (tok->str() == "struct")) + SymbolDatabase::SpaceInfo *info = *i; + + // only check functions + if (info->type != SymbolDatabase::SpaceInfo::Function) + continue; + + // Walk through all tokens.. + int indentlevel = 0; + for (const Token *tok = info->classStart; tok; tok = tok->next()) { - for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) + // Skip function local class and struct declarations.. + if ((tok->str() == "class") || (tok->str() == "struct") || (tok->str() == "union")) { - if (tok2->str() == "{") + for (const Token *tok2 = tok; tok2; tok2 = tok2->next()) { - tok = tok2->link(); + if (tok2->str() == "{") + { + tok = tok2->link(); + break; + } + if (Token::Match(tok2, "[,);]")) + { + break; + } + } + if (! tok) break; - } - if (Token::Match(tok2, "[,);]")) - { - break; - } } - if (! tok) - break; - } - else if (tok->str() == "{") - { - ++indentlevel; - } - else if (tok->str() == "}") - { - --indentlevel; - if (indentlevel == 0) - func = false; - } - if (indentlevel == 0 && Token::simpleMatch(tok, ") {")) - { - func = true; - } - if (indentlevel > 0 && func && Token::Match(tok, "[{};]")) - { - // First token of statement.. - const Token *tok1 = tok->next(); - if (! tok1) - continue; - - if ((tok1->str() == "return") || - (tok1->str() == "throw") || - (tok1->str() == "delete") || - (tok1->str() == "goto") || - (tok1->str() == "else")) - continue; - - // Variable declaration? - if (Token::Match(tok1, "%type% %var% ; %var% = %num% ;")) + else if (tok->str() == "{") { - // Tokenizer modify "int i = 0;" to "int i; i = 0;", - // so to handle this situation we just skip - // initialization (see ticket #272). - const unsigned int firstVarId = tok1->next()->varId(); - const unsigned int secondVarId = tok1->tokAt(3)->varId(); - if (firstVarId > 0 && firstVarId == secondVarId) - { - lookupVar(tok1->tokAt(6), tok1->strAt(1)); - } + ++indentlevel; } - else if (tok1->isStandardType() && Token::Match(tok1, "%type% %var% [;=]")) + else if (tok->str() == "}") { - lookupVar(tok1, tok1->strAt(1)); + --indentlevel; + if (indentlevel == 0) + break;; + } + + if (indentlevel > 0 && Token::Match(tok, "[{};]")) + { + // First token of statement.. + const Token *tok1 = tok->next(); + if (! tok1) + continue; + + if ((tok1->str() == "return") || + (tok1->str() == "throw") || + (tok1->str() == "delete") || + (tok1->str() == "goto") || + (tok1->str() == "else")) + continue; + + // Variable declaration? + if (Token::Match(tok1, "%type% %var% ; %var% = %num% ;")) + { + // Tokenizer modify "int i = 0;" to "int i; i = 0;", + // so to handle this situation we just skip + // initialization (see ticket #272). + const unsigned int firstVarId = tok1->next()->varId(); + const unsigned int secondVarId = tok1->tokAt(3)->varId(); + if (firstVarId > 0 && firstVarId == secondVarId) + { + lookupVar(tok1->tokAt(6), tok1->strAt(1)); + } + } + else if (tok1->isStandardType() && Token::Match(tok1, "%type% %var% [;=]")) + { + lookupVar(tok1, tok1->strAt(1)); + } } } } diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 712cebcff..e9dfe9c9f 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -59,6 +59,13 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti new_info->classStart = tok2; new_info->classEnd = tok2->link(); + // make sure we have valid code + if (!new_info->classEnd) + { + delete new_info; + break; + } + info = new_info; // add namespace @@ -221,7 +228,8 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti SpaceInfo *functionOf = info; addNewFunction(&info, &tok2); - info->functionOf = functionOf; + if (info) + info->functionOf = functionOf; tok = tok2; } @@ -283,9 +291,19 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti function.arg = function.argDef; function.type = Func::Function; - info->functionList.push_back(function); + SpaceInfo *old_info = info; addNewFunction(&info, &tok); + + if (info) + old_info->functionList.push_back(function); + + // syntax error + else + { + info = old_info; + break; + } } } @@ -294,6 +312,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti Token::Match(argStart->link()->tokAt(2)->link(), ") const| {")) { const Token *tok1 = funcStart; + SpaceInfo *old_info = info; // class function if (tok1->previous()->str() == "::") @@ -303,6 +322,10 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti else addNewFunction(&info, &tok1); + // syntax error? + if (!info) + info = old_info; + tok = tok1; } } @@ -747,8 +770,11 @@ void SymbolDatabase::addFunction(SpaceInfo **info, const Token **tok, const Toke if (func->hasBody) { addNewFunction(info, tok); - (*info)->functionOf = info1; - added = true; + if (info) + { + (*info)->functionOf = info1; + added = true; + } break; } } @@ -775,6 +801,17 @@ void SymbolDatabase::addNewFunction(SymbolDatabase::SpaceInfo **info, const Toke new_info->classStart = tok1; new_info->classEnd = tok1->link(); + // syntax error? + if (!new_info->classEnd) + { + delete new_info; + while (tok1->next()) + tok1 = tok1->next(); + *info = NULL; + *tok = tok1; + return; + } + *info = new_info; // add space @@ -933,13 +970,21 @@ void SymbolDatabase::SpaceInfo::getVarList() for (const Token *tok = start; tok; tok = tok->next()) { + // end of space? if (tok->str() == "}") break; + // syntax error? + else if (tok->next() == NULL) + break; + // Is it a function? else if (tok->str() == "{") { tok = tok->link(); + // syntax error? + if (!tok) + return; continue; }