diff --git a/cfg/std.cfg b/cfg/std.cfg index b30583835..c1ba3c546 100644 --- a/cfg/std.cfg +++ b/cfg/std.cfg @@ -450,7 +450,6 @@ malloc calloc - realloc diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp index b87ff5150..ef6fd380d 100644 --- a/lib/checkmemoryleak.cpp +++ b/lib/checkmemoryleak.cpp @@ -506,45 +506,6 @@ const char *CheckMemoryLeak::functionArgAlloc(const Function *func, unsigned int } -void CheckMemoryLeakInFunction::parse_noreturn() -{ - if (noreturn.empty()) { - noreturn.insert("exit"); - noreturn.insert("_exit"); - noreturn.insert("_Exit"); - noreturn.insert("abort"); - noreturn.insert("err"); - noreturn.insert("verr"); - noreturn.insert("errx"); - noreturn.insert("verrx"); - noreturn.insert("ExitProcess"); - noreturn.insert("ExitThread"); - noreturn.insert("pthread_exit"); - } - - // only check functions - const std::size_t functionsCount = symbolDatabase->functionScopes.size(); - for (std::size_t i = 0; i < functionsCount; ++i) { - const Scope * scope = symbolDatabase->functionScopes[i]; - - // parse this function to check if it contains an "exit" call.. - bool isNoreturn = false; - for (const Token *tok2 = scope->classStart->next(); tok2 != scope->classEnd; tok2 = tok2->next()) { - if (Token::Match(tok2->previous(), "[;{}] exit (")) { - isNoreturn = true; - break; - } - } - - // This function is not a noreturn function - if (isNoreturn) - noreturn.insert(scope->className); - else - notnoreturn.insert(scope->className); - } -} - - bool CheckMemoryLeakInFunction::notvar(const Token *tok, unsigned int varid, bool endpar) { const std::string end(endpar ? " &&|)" : " [;)&|]"); @@ -609,7 +570,7 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::liststr()) != noreturn.end() && tok->strAt(-1) != "=") + if (_settings->library.isnoreturn(tok->str()) && tok->strAt(-1) != "=") return "exit"; if (varid > 0 && (getReallocationType(tok, varid) != No || getDeallocationType(tok, varid) != No)) @@ -650,7 +611,11 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::listfunction()) { + std::string temp; + if (!_settings->library.isScopeNoReturn(tok->function()->functionScope->classEnd, &temp) && temp.empty()) + return nullptr; + } else if (_settings->library.isnotnoreturn(funcname)) return nullptr; return "callfunc"; @@ -1309,7 +1274,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::liststr()) != noreturn.end()) + if (_settings->library.isnoreturn(tok->str())) addtoken(&rettail, tok, "exit"); else if (!test_white_list_with_lib(tok->str(), _settings)) { @@ -2233,9 +2198,6 @@ static bool isInMemberFunc(const Scope* scope) void CheckMemoryLeakInFunction::check() { - // fill the "noreturn" - parse_noreturn(); - // Check locking/unlocking of global resources.. const std::size_t functions = symbolDatabase->functionScopes.size(); for (std::size_t i = 0; i < functions; ++i) { diff --git a/lib/checkmemoryleak.h b/lib/checkmemoryleak.h index 4de0527f9..bef7bfb4a 100644 --- a/lib/checkmemoryleak.h +++ b/lib/checkmemoryleak.h @@ -296,9 +296,6 @@ public: */ void checkScope(const Token *Tok1, const std::string &varname, unsigned int varid, bool classmember, unsigned int sz); - /** parse tokens to see what functions are "noreturn" */ - void parse_noreturn(); - private: /** Report all possible errors (for the --errorlist) */ void getErrorMessages(ErrorLogger *e, const Settings *settings) const { @@ -331,12 +328,6 @@ private: return "Is there any allocated memory when a function goes out of scope\n"; } - /** Function names for functions that are "noreturn" */ - std::set noreturn; - - /** Function names for functions that are not "noreturn" */ - std::set notnoreturn; - const SymbolDatabase *symbolDatabase; }; diff --git a/test/testmemleak.cpp b/test/testmemleak.cpp index e492d1fb2..541ce038c 100644 --- a/test/testmemleak.cpp +++ b/test/testmemleak.cpp @@ -148,6 +148,7 @@ private: void run() { + LOAD_LIB_2(settings1.library, "std.cfg"); LOAD_LIB_2(settings1.library, "gtk.cfg"); // Check that getcode works correctly.. @@ -366,7 +367,9 @@ private: TEST_CASE(posixcfg); } - + void loadlib(Library& library) { + LOAD_LIB_2(library, "std.cfg"); + } std::string getcode(const char code[], const char varname[], bool classfunc=false) { // Clear the error buffer.. @@ -374,6 +377,7 @@ private: Settings settings; settings.standards.posix = true; + loadlib(settings.library); // Tokenize.. Tokenizer tokenizer(&settings, this); @@ -386,7 +390,6 @@ private: // getcode.. CheckMemoryLeakInFunction checkMemoryLeak(&tokenizer, &settings, nullptr); - checkMemoryLeak.parse_noreturn(); std::list callstack; callstack.push_back(0); CheckMemoryLeak::AllocType allocType, deallocType; @@ -539,9 +542,9 @@ private: // exit.. ASSERT_EQUALS(";;exit;", getcode("char *s; exit(0);", "s")); - ASSERT_EQUALS(";;exit;", getcode("char *s; _exit(0);", "s")); + ASSERT_EQUALS(";;callfunc;", getcode("char *s; _exit(0);", "s")); // not in std.cfg nor in gtk.cfg ASSERT_EQUALS(";;exit;", getcode("char *s; abort();", "s")); - ASSERT_EQUALS(";;exit;", getcode("char *s; err(0);", "s")); + ASSERT_EQUALS(";;callfunc;", getcode("char *s; err(0);", "s")); // not in std.cfg nor in gtk.cfg ASSERT_EQUALS(";;if{exit;}", getcode("char *s; if (a) { exit(0); }", "s")); // list_for_each