From c6e67d4aad6825337e9a95c7c1e4608be1388ae7 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Wed, 8 Dec 2010 07:49:01 +0100 Subject: [PATCH] Symbol database: use symbol database in the memory leaks function checking. Ticket: #2219 --- lib/checkmemoryleak.cpp | 102 ++++++++++++++++++---------------------- lib/checkmemoryleak.h | 9 +++- lib/symboldatabase.cpp | 6 ++- lib/symboldatabase.h | 1 + 4 files changed, 60 insertions(+), 58 deletions(-) diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index 96b60bb3d..8679353f1 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -563,36 +563,32 @@ void CheckMemoryLeakInFunction::parse_noreturn() noreturn.insert("errx"); noreturn.insert("verrx"); - for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) + std::list::const_iterator i; + + for (i = symbolDatabase->spaceInfoList.begin(); i != symbolDatabase->spaceInfoList.end(); ++i) { - if (tok->str() == "{") - tok = tok->link(); - if (tok->str() == "(") + SymbolDatabase::SpaceInfo *info = *i; + + // only check functions + if (info->type != SymbolDatabase::SpaceInfo::Function) + continue; + + // parse this function to check if it contains an "exit" call.. + unsigned int indentlevel = 1; + for (const Token *tok2 = info->classStart->next(); tok2; tok2 = tok2->next()) { - const std::string function_name((tok->previous() && tok->previous()->isName()) ? tok->strAt(-1).c_str() : ""); - - tok = tok->link(); - - if (!function_name.empty() && Token::simpleMatch(tok, ") {")) + if (tok2->str() == "{") + ++indentlevel; + else if (tok2->str() == "}") { - // parse this function to check if it contains an "exit" call.. - unsigned int indentlevel = 0; - for (const Token *tok2 = tok->next(); tok2; tok2 = tok2->next()) - { - if (tok2->str() == "{") - ++indentlevel; - else if (tok2->str() == "}") - { - if (indentlevel <= 1) - break; - --indentlevel; - } - if (Token::Match(tok2, "[;{}] exit (")) - { - noreturn.insert(function_name); - break; - } - } + --indentlevel; + if (indentlevel == 0) + break; + } + if (Token::Match(tok2, "[;{}] exit (")) + { + noreturn.insert(info->className); + break; } } } @@ -2374,32 +2370,38 @@ void CheckMemoryLeakInFunction::checkScope(const Token *Tok1, const std::string //--------------------------------------------------------------------------- void CheckMemoryLeakInFunction::checkReallocUsage() { - const Token *tok = _tokenizer->tokens(); - while (NULL != (tok = Token::findmatch(tok, ") const| {"))) + std::list::const_iterator i; + + for (i = symbolDatabase->spaceInfoList.begin(); i != symbolDatabase->spaceInfoList.end(); ++i) { + SymbolDatabase::SpaceInfo *info = *i; + + // only check functions + if (info->type != SymbolDatabase::SpaceInfo::Function) + continue; + // Record the varid's of the function parameters std::set parameterVarIds; - for (const Token *tok2 = tok->link(); tok2 && tok2->str() != ")"; tok2 = tok2->next()) + for (const Token *tok2 = info->classDef->next(); tok2 && tok2->str() != ")"; tok2 = tok2->next()) { if (tok2->varId() != 0) parameterVarIds.insert(tok2->varId()); } - while (tok->str() != "{") - tok = tok->next(); + const Token *tok = info->classStart; const Token *startOfFunction = tok; // Search for the "var = realloc(var, 100);" pattern within this function - unsigned int indentlevel = 0; + unsigned int indentlevel = 1; for (tok = tok->next(); tok; tok = tok->next()) { if (tok->str() == "{") ++indentlevel; else if (tok->str() == "}") { + --indentlevel; if (indentlevel == 0) break; - --indentlevel; } if (tok->varId() > 0 && @@ -2507,34 +2509,24 @@ void CheckMemoryLeakInFunction::parseFunctionScope(const Token *tok, const Token void CheckMemoryLeakInFunction::check() { - // Parse the tokens and fill the "noreturn" + // fill the "noreturn" parse_noreturn(); - bool classmember = false; - for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) + std::list::const_iterator i; + + for (i = symbolDatabase->spaceInfoList.begin(); i != symbolDatabase->spaceInfoList.end(); ++i) { - if (tok->str() == "(") - { - tok = tok->link(); - } + SymbolDatabase::SpaceInfo *info = *i; - // Found a function scope - if (Token::Match(tok, ") const| {")) - { - const Token * const tok1 = tok->link(); - while (tok->str() != "{") - tok = tok->next(); - parseFunctionScope(tok, tok1, classmember); - tok = tok->link(); - classmember = false; + // only check functions + if (info->type != SymbolDatabase::SpaceInfo::Function) continue; - } - if (tok->str() == "::") - classmember = true; + const Token *tok = info->classStart; + const Token *tok1 = info->classDef->next(); + bool classmember = info->functionOf != NULL; - if (Token::Match(tok, "[;}]")) - classmember = false; + parseFunctionScope(tok, tok1, classmember); } } //--------------------------------------------------------------------------- diff --git a/lib/checkmemoryleak.h b/lib/checkmemoryleak.h index aea47bac5..2281b934f 100644 --- a/lib/checkmemoryleak.h +++ b/lib/checkmemoryleak.h @@ -172,13 +172,16 @@ class CheckMemoryLeakInFunction : private Check, public CheckMemoryLeak { public: /** @brief This constructor is used when registering this class */ - CheckMemoryLeakInFunction() : Check(), CheckMemoryLeak(0, 0) + CheckMemoryLeakInFunction() : Check(), CheckMemoryLeak(0, 0), symbolDatabase(NULL) { } /** @brief This constructor is used when running checks */ CheckMemoryLeakInFunction(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog) : Check(tokenizr, settings, errLog), CheckMemoryLeak(tokenizr, errLog) - { } + { + // get the symbol database + symbolDatabase = tokenizr->getSymbolDatabase(); + } /** @brief run all simplified checks */ void runSimplifiedChecks(const Tokenizer *tokenizr, const Settings *settings, ErrorLogger *errLog) @@ -340,6 +343,8 @@ public: /** Function names for functions that are "noreturn" */ std::set noreturn; + + SymbolDatabase *symbolDatabase; }; diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 75b77087e..bf92eb7e4 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -218,8 +218,10 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti info->functionList.push_back(function); const Token *tok2 = funcStart; + SpaceInfo *functionOf = info; addNewFunction(&info, &tok2); + info->functionOf = functionOf; tok = tok2; } @@ -745,6 +747,7 @@ void SymbolDatabase::addFunction(SpaceInfo **info, const Token **tok, const Toke if (func->hasBody) { addNewFunction(info, tok); + (*info)->functionOf = info1; added = true; break; } @@ -874,7 +877,8 @@ SymbolDatabase::SpaceInfo::SpaceInfo(SymbolDatabase *check_, const Token *classD classEnd(NULL), nestedIn(nestedIn_), numConstructors(0), - needInitialization(SpaceInfo::Unknown) + needInitialization(SpaceInfo::Unknown), + functionOf(NULL) { if (!classDef) { diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 4c3a1ae11..53543dd15 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -171,6 +171,7 @@ public: AccessControl access; unsigned int numConstructors; NeedInitialization needInitialization; + SpaceInfo * functionOf; // class/struct this function belongs to bool isClassOrStruct() const {