Refactorization in checkmemoryleak.cpp:
- Use Library to detect noreturn/notnoreturn functions - Removed realloc from std.cfg as long as there is no proper way to configure such functions
This commit is contained in:
parent
c92230dfee
commit
40e5dab9dc
|
@ -450,7 +450,6 @@
|
|||
|
||||
<alloc init="false">malloc</alloc>
|
||||
<alloc init="true">calloc</alloc>
|
||||
<alloc init="true">realloc</alloc>
|
||||
</memory>
|
||||
|
||||
<resource>
|
||||
|
|
|
@ -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::list<co
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (noreturn.find(tok->str()) != 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::list<co
|
|||
return nullptr;
|
||||
|
||||
// Function is not noreturn
|
||||
if (notnoreturn.find(funcname) != notnoreturn.end())
|
||||
if (tok->function()) {
|
||||
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::list<const Toke
|
|||
// just add a "::use"
|
||||
// The "::use" means that a member function was probably called but it wasn't analysed further
|
||||
else if (classmember) {
|
||||
if (noreturn.find(tok->str()) != 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) {
|
||||
|
|
|
@ -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<std::string> noreturn;
|
||||
|
||||
/** Function names for functions that are not "noreturn" */
|
||||
std::set<std::string> notnoreturn;
|
||||
|
||||
const SymbolDatabase *symbolDatabase;
|
||||
};
|
||||
|
||||
|
|
|
@ -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<const Token *> 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
|
||||
|
|
Loading…
Reference in New Issue