Refactoring: Removed possibleError messages from CheckMemoryLeaks

This commit is contained in:
Daniel Marjamäki 2010-05-16 19:55:16 +02:00
parent 19aaa32a99
commit d0e122079f
3 changed files with 63 additions and 117 deletions

View File

@ -286,15 +286,15 @@ CheckMemoryLeak::AllocType CheckMemoryLeak::getDeallocationType(const Token *tok
//-------------------------------------------------------------------------- //--------------------------------------------------------------------------
void CheckMemoryLeak::memoryLeak(const Token *tok, const std::string &varname, AllocType alloctype, bool all) void CheckMemoryLeak::memoryLeak(const Token *tok, const std::string &varname, AllocType alloctype)
{ {
if (alloctype == CheckMemoryLeak::File || if (alloctype == CheckMemoryLeak::File ||
alloctype == CheckMemoryLeak::Pipe || alloctype == CheckMemoryLeak::Pipe ||
alloctype == CheckMemoryLeak::Fd || alloctype == CheckMemoryLeak::Fd ||
alloctype == CheckMemoryLeak::Dir) alloctype == CheckMemoryLeak::Dir)
resourceLeakError(tok, varname.c_str(), all); resourceLeakError(tok, varname.c_str());
else else
memleakError(tok, varname.c_str(), all); memleakError(tok, varname.c_str());
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
@ -332,17 +332,17 @@ void CheckMemoryLeak::reportErr(const std::list<const Token *> &callstack, Sever
std::cout << errmsg.toXML() << std::endl; std::cout << errmsg.toXML() << std::endl;
} }
void CheckMemoryLeak::memleakError(const Token *tok, const std::string &varname, bool all) void CheckMemoryLeak::memleakError(const Token *tok, const std::string &varname)
{ {
reportErr(tok, all ? Severity::possibleError : Severity::error, "memleak", "Memory leak: " + varname); reportErr(tok, Severity::error, "memleak", "Memory leak: " + varname);
} }
void CheckMemoryLeak::resourceLeakError(const Token *tok, const std::string &varname, bool all) void CheckMemoryLeak::resourceLeakError(const Token *tok, const std::string &varname)
{ {
std::string errmsg("Resource leak"); std::string errmsg("Resource leak");
if (!varname.empty()) if (!varname.empty())
errmsg += ": " + varname; errmsg += ": " + varname;
reportErr(tok, all ? Severity::possibleError : Severity::error, "resourceLeak", errmsg); reportErr(tok, Severity::error, "resourceLeak", errmsg);
} }
void CheckMemoryLeak::deallocDeallocError(const Token *tok, const std::string &varname) void CheckMemoryLeak::deallocDeallocError(const Token *tok, const std::string &varname)
@ -360,9 +360,9 @@ void CheckMemoryLeak::mismatchSizeError(const Token *tok, const std::string &sz)
reportErr(tok, Severity::error, "mismatchSize", "The given size " + sz + " is mismatching"); reportErr(tok, Severity::error, "mismatchSize", "The given size " + sz + " is mismatching");
} }
void CheckMemoryLeak::mismatchAllocDealloc(const std::list<const Token *> &callstack, const std::string &varname, bool all) void CheckMemoryLeak::mismatchAllocDealloc(const std::list<const Token *> &callstack, const std::string &varname)
{ {
reportErr(callstack, all ? Severity::possibleError : Severity::error, "mismatchAllocDealloc", "Mismatching allocation and deallocation: " + varname); reportErr(callstack, Severity::error, "mismatchAllocDealloc", "Mismatching allocation and deallocation: " + varname);
} }
CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Token *tok) const CheckMemoryLeak::AllocType CheckMemoryLeak::functionReturnType(const Token *tok) const
@ -550,7 +550,7 @@ bool CheckMemoryLeakInFunction::test_white_list(const std::string &funcname)
sizeof(call_func_white_list[0]), call_func_white_list_compare) != NULL); sizeof(call_func_white_list[0]), call_func_white_list_compare) != NULL);
} }
const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, bool &all, unsigned int sz) const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, unsigned int sz)
{ {
if (test_white_list(tok->str())) if (test_white_list(tok->str()))
return 0; return 0;
@ -581,8 +581,8 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<co
if (!ftok) if (!ftok)
return 0; return 0;
Token *func = getcode(ftok->tokAt(1), callstack, 0, alloctype, dealloctype, false, all, 1); Token *func = getcode(ftok->tokAt(1), callstack, 0, alloctype, dealloctype, false, 1);
simplifycode(func, all); simplifycode(func);
const char *ret = 0; const char *ret = 0;
if (Token::simpleMatch(func, "; alloc ; }")) if (Token::simpleMatch(func, "; alloc ; }"))
ret = "alloc"; ret = "alloc";
@ -660,7 +660,7 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<co
// Check if the function deallocates the variable.. // Check if the function deallocates the variable..
while (ftok && (ftok->str() != "{")) while (ftok && (ftok->str() != "{"))
ftok = ftok->next(); ftok = ftok->next();
Token *func = getcode(ftok->tokAt(1), callstack, parameterVarid, alloctype, dealloctype, false, all, sz); Token *func = getcode(ftok->tokAt(1), callstack, parameterVarid, alloctype, dealloctype, false, sz);
//simplifycode(func, all); //simplifycode(func, all);
const Token *func_ = func; const Token *func_ = func;
while (func_ && func_->str() == ";") while (func_ && func_->str() == ";")
@ -685,7 +685,7 @@ const char * CheckMemoryLeakInFunction::call_func(const Token *tok, std::list<co
Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, CheckMemoryLeak::AllocType &alloctype, CheckMemoryLeak::AllocType &dealloctype, bool classmember, bool &all, unsigned int sz) Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, CheckMemoryLeak::AllocType &alloctype, CheckMemoryLeak::AllocType &dealloctype, bool classmember, unsigned int sz)
{ {
Token *rethead = 0, *rettail = 0; Token *rethead = 0, *rettail = 0;
#define addtoken(_str) \ #define addtoken(_str) \
@ -838,7 +838,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
if (alloc != Many && dealloctype != No && dealloctype != Many && dealloctype != alloc) if (alloc != Many && dealloctype != No && dealloctype != Many && dealloctype != alloc)
{ {
callstack.push_back(tok); callstack.push_back(tok);
mismatchAllocDealloc(callstack, Token::findmatch(_tokenizer->tokens(), "%varid%", varid)->str(), false); mismatchAllocDealloc(callstack, Token::findmatch(_tokenizer->tokens(), "%varid%", varid)->str());
callstack.pop_back(); callstack.pop_back();
} }
@ -884,7 +884,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
if (dealloc != Many && alloctype != No && alloctype != Many && alloctype != dealloc) if (dealloc != Many && alloctype != No && alloctype != Many && alloctype != dealloc)
{ {
callstack.push_back(tok); callstack.push_back(tok);
mismatchAllocDealloc(callstack, Token::findmatch(_tokenizer->tokens(), "%varid%", varid)->str(), false); mismatchAllocDealloc(callstack, Token::findmatch(_tokenizer->tokens(), "%varid%", varid)->str());
callstack.pop_back(); callstack.pop_back();
} }
dealloctype = dealloc; dealloctype = dealloc;
@ -1189,7 +1189,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
continue; continue;
} }
const char *str = call_func(tok, callstack, varid, alloctype, dealloctype, all, sz); const char *str = call_func(tok, callstack, varid, alloctype, dealloctype, sz);
if (str) if (str)
{ {
if (varid == 0) if (varid == 0)
@ -1256,7 +1256,7 @@ Token *CheckMemoryLeakInFunction::getcode(const Token *tok, std::list<const Toke
void CheckMemoryLeakInFunction::simplifycode(Token *tok, bool &all) void CheckMemoryLeakInFunction::simplifycode(Token *tok)
{ {
// Replace "throw" that is not in a try block with "return" // Replace "throw" that is not in a try block with "return"
int indentlevel = 0; int indentlevel = 0;
@ -1429,23 +1429,6 @@ void CheckMemoryLeakInFunction::simplifycode(Token *tok, bool &all)
} }
// Reduce "if assign|dealloc|use ;" that is not followed by an else..
// If "--all" has been given these are deleted
// Otherwise, only the "if" will be deleted
else if (Token::Match(tok2, "[;{}] if assign|dealloc|use ; !!else"))
{
if (_settings->inconclusive && tok2->tokAt(2)->str() != "assign" && !Token::simpleMatch(tok2->tokAt(2), "dealloc ; dealloc"))
{
Token::eraseTokens(tok2, tok2->tokAt(3));
all = true;
}
else
{
tok2->deleteNext();
}
done = false;
}
// Reduce "if return ; alloc ;" => "alloc ;" // Reduce "if return ; alloc ;" => "alloc ;"
else if (Token::Match(tok2, "[;{}] if return ; alloc|return ;")) else if (Token::Match(tok2, "[;{}] if return ; alloc|return ;"))
{ {
@ -1510,7 +1493,6 @@ void CheckMemoryLeakInFunction::simplifycode(Token *tok, bool &all)
{ {
if (Token::Match(tok2, "[;{}] if { assign|dealloc|use ; return ; } !!else")) if (Token::Match(tok2, "[;{}] if { assign|dealloc|use ; return ; } !!else"))
{ {
all = true;
Token::eraseTokens(tok2, tok2->tokAt(8)); Token::eraseTokens(tok2, tok2->tokAt(8));
done = false; done = false;
} }
@ -1923,7 +1905,6 @@ void CheckMemoryLeakInFunction::simplifycode(Token *tok, bool &all)
if (tok2->str() == "callfunc") if (tok2->str() == "callfunc")
{ {
tok2->deleteThis(); tok2->deleteThis();
all = true;
done = false; done = false;
} }
} }
@ -1935,7 +1916,7 @@ void CheckMemoryLeakInFunction::simplifycode(Token *tok, bool &all)
const Token *CheckMemoryLeakInFunction::findleak(const Token *tokens, bool all) const Token *CheckMemoryLeakInFunction::findleak(const Token *tokens)
{ {
const Token *result; const Token *result;
@ -1954,11 +1935,6 @@ const Token *CheckMemoryLeakInFunction::findleak(const Token *tokens, bool all)
return result->tokAt(3); return result->tokAt(3);
} }
if (all && (result = Token::findmatch(tokens, "alloc ; ifv break|continue|return ;")) != NULL)
{
return result->tokAt(3);
}
if ((result = Token::findmatch(tokens, "alloc ; alloc|assign|return callfunc| ;")) != NULL) if ((result = Token::findmatch(tokens, "alloc ; alloc|assign|return callfunc| ;")) != NULL)
{ {
return result->tokAt(2); return result->tokAt(2);
@ -2015,11 +1991,9 @@ void CheckMemoryLeakInFunction::checkScope(const Token *Tok1, const std::string
AllocType alloctype = No; AllocType alloctype = No;
AllocType dealloctype = No; AllocType dealloctype = No;
bool all = false;
const Token *result; const Token *result;
Token *tok = getcode(Tok1, callstack, varid, alloctype, dealloctype, classmember, all, sz); Token *tok = getcode(Tok1, callstack, varid, alloctype, dealloctype, classmember, sz);
//tok->printOut((std::string("Checkmemoryleak: getcode result for: ") + varname).c_str()); //tok->printOut((std::string("Checkmemoryleak: getcode result for: ") + varname).c_str());
// Simplify the code and check if freed memory is used.. // Simplify the code and check if freed memory is used..
@ -2061,7 +2035,7 @@ void CheckMemoryLeakInFunction::checkScope(const Token *Tok1, const std::string
return; return;
} }
simplifycode(tok, all); simplifycode(tok);
if (_settings->_debug && _settings->_verbose) if (_settings->_debug && _settings->_verbose)
{ {
@ -2082,9 +2056,9 @@ void CheckMemoryLeakInFunction::checkScope(const Token *Tok1, const std::string
return; return;
} }
if ((result = findleak(tok, _settings->inconclusive)) != NULL) if ((result = findleak(tok)) != NULL)
{ {
memoryLeak(result, varname, alloctype, all); memoryLeak(result, varname, alloctype);
} }
else if ((result = Token::findmatch(tok, "dealloc ; dealloc ;")) != NULL) else if ((result = Token::findmatch(tok, "dealloc ; dealloc ;")) != NULL)
@ -2417,7 +2391,7 @@ void CheckMemoryLeakInClass::variable(const std::string &classname, const Token
if (alloc != CheckMemoryLeak::Many && Dealloc != CheckMemoryLeak::No && Dealloc != CheckMemoryLeak::Many && Dealloc != alloc) if (alloc != CheckMemoryLeak::Many && Dealloc != CheckMemoryLeak::No && Dealloc != CheckMemoryLeak::Many && Dealloc != alloc)
{ {
callstack.push_back(tok); callstack.push_back(tok);
mismatchAllocDealloc(callstack, classname + "::" + varname, true); mismatchAllocDealloc(callstack, classname + "::" + varname);
callstack.pop_back(); callstack.pop_back();
} }
@ -2451,7 +2425,7 @@ void CheckMemoryLeakInClass::variable(const std::string &classname, const Token
if (dealloc != CheckMemoryLeak::Many && Alloc != CheckMemoryLeak::No && Alloc != Many && Alloc != dealloc) if (dealloc != CheckMemoryLeak::Many && Alloc != CheckMemoryLeak::No && Alloc != Many && Alloc != dealloc)
{ {
callstack.push_back(tok); callstack.push_back(tok);
mismatchAllocDealloc(callstack, classname + "::" + varname, true); mismatchAllocDealloc(callstack, classname + "::" + varname);
callstack.pop_back(); callstack.pop_back();
} }
@ -2476,11 +2450,11 @@ void CheckMemoryLeakInClass::variable(const std::string &classname, const Token
if (allocInConstructor && !deallocInDestructor) if (allocInConstructor && !deallocInDestructor)
{ {
memoryLeak(tokVarname, (classname + "::" + varname).c_str(), Alloc, true); memoryLeak(tokVarname, (classname + "::" + varname).c_str(), Alloc);
} }
else if (Alloc != CheckMemoryLeak::No && Dealloc == CheckMemoryLeak::No) else if (Alloc != CheckMemoryLeak::No && Dealloc == CheckMemoryLeak::No)
{ {
memoryLeak(tokVarname, (classname + "::" + varname).c_str(), Alloc, true); memoryLeak(tokVarname, (classname + "::" + varname).c_str(), Alloc);
} }
} }
@ -2623,7 +2597,7 @@ void CheckMemoryLeakStructMember::check()
{ {
if (indentlevel3 == 0) if (indentlevel3 == 0)
{ {
memoryLeak(tok3, (vartok->str() + "." + tok2->strAt(2)).c_str(), Malloc, false); memoryLeak(tok3, (vartok->str() + "." + tok2->strAt(2)).c_str(), Malloc);
break; break;
} }
--indentlevel3; --indentlevel3;
@ -2658,7 +2632,7 @@ void CheckMemoryLeakStructMember::check()
// Deallocating the struct.. // Deallocating the struct..
else if (indentlevel2 == 0 && Token::Match(tok3, "free|kfree ( %varid% )", structid)) else if (indentlevel2 == 0 && Token::Match(tok3, "free|kfree ( %varid% )", structid))
{ {
memoryLeak(tok3, (vartok->str() + "." + tok2->strAt(2)).c_str(), Malloc, false); memoryLeak(tok3, (vartok->str() + "." + tok2->strAt(2)).c_str(), Malloc);
break; break;
} }
@ -2711,7 +2685,7 @@ void CheckMemoryLeakStructMember::check()
// Returning from function without deallocating struct member? // Returning from function without deallocating struct member?
if (!Token::Match(tok3, "return %varid% ;", structid)) if (!Token::Match(tok3, "return %varid% ;", structid))
{ {
memoryLeak(tok3, (vartok->str() + "." + tok2->strAt(2)).c_str(), Malloc, false); memoryLeak(tok3, (vartok->str() + "." + tok2->strAt(2)).c_str(), Malloc);
} }
break; break;
} }
@ -2857,7 +2831,7 @@ private:
CheckMemoryLeakInFunction *checkMemleak = reinterpret_cast<CheckMemoryLeakInFunction *>(C->owner); CheckMemoryLeakInFunction *checkMemleak = reinterpret_cast<CheckMemoryLeakInFunction *>(C->owner);
if (checkMemleak) if (checkMemleak)
{ {
checkMemleak->memleakError(tok, C->varname, false); checkMemleak->memleakError(tok, C->varname);
break; break;
} }
} }

View File

@ -92,7 +92,7 @@ public:
/** @brief What type of allocation are used.. the "Many" means that several types of allocation and deallocation are used */ /** @brief What type of allocation are used.. the "Many" means that several types of allocation and deallocation are used */
enum AllocType { No, Malloc, gMalloc, New, NewArray, File, Fd, Pipe, Dir, Many }; enum AllocType { No, Malloc, gMalloc, New, NewArray, File, Fd, Pipe, Dir, Many };
void memoryLeak(const Token *tok, const std::string &varname, AllocType alloctype, bool all); void memoryLeak(const Token *tok, const std::string &varname, AllocType alloctype);
/** /**
* @brief Get type of deallocation at given position * @brief Get type of deallocation at given position
@ -128,8 +128,8 @@ public:
*/ */
bool isclass(const Tokenizer *_tokenizer, const Token *typestr) const; bool isclass(const Tokenizer *_tokenizer, const Token *typestr) const;
void memleakError(const Token *tok, const std::string &varname, bool all); void memleakError(const Token *tok, const std::string &varname);
void resourceLeakError(const Token *tok, const std::string &varname, bool all); void resourceLeakError(const Token *tok, const std::string &varname);
/** /**
* @brief Report error: deallocating a deallocated pointer * @brief Report error: deallocating a deallocated pointer
@ -139,7 +139,7 @@ public:
void deallocDeallocError(const Token *tok, const std::string &varname); void deallocDeallocError(const Token *tok, const std::string &varname);
void deallocuseError(const Token *tok, const std::string &varname); void deallocuseError(const Token *tok, const std::string &varname);
void mismatchSizeError(const Token *tok, const std::string &sz); void mismatchSizeError(const Token *tok, const std::string &sz);
void mismatchAllocDealloc(const std::list<const Token *> &callstack, const std::string &varname, bool all); void mismatchAllocDealloc(const std::list<const Token *> &callstack, const std::string &varname);
/** What type of allocated memory does the given function return? */ /** What type of allocated memory does the given function return? */
AllocType functionReturnType(const Token *tok) const; AllocType functionReturnType(const Token *tok) const;
@ -222,7 +222,6 @@ public:
* @param varid variable id to check * @param varid variable id to check
* @param alloctype if memory is allocated, this indicates the type of allocation * @param alloctype if memory is allocated, this indicates the type of allocation
* @param dealloctype if memory is deallocated, this indicates the type of deallocation * @param dealloctype if memory is deallocated, this indicates the type of deallocation
* @param all is the code simplified according to the "--all" rules or not?
* @param sz not used by call_func - see getcode * @param sz not used by call_func - see getcode
* @return These are the possible return values: * @return These are the possible return values:
* - NULL : no significant code * - NULL : no significant code
@ -234,7 +233,7 @@ public:
* - "callfunc" : a function call with unknown side effects * - "callfunc" : a function call with unknown side effects
* - "&use" * - "&use"
*/ */
const char * call_func(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, bool &all, unsigned int sz); const char * call_func(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, unsigned int sz);
/** /**
* Extract a new tokens list that is easier to parse than the "_tokenizer->tokens()", the * Extract a new tokens list that is easier to parse than the "_tokenizer->tokens()", the
@ -246,7 +245,6 @@ public:
* @param alloctype keep track of what type of allocation is used * @param alloctype keep track of what type of allocation is used
* @param dealloctype keeps track of what type of deallocation is used * @param dealloctype keeps track of what type of deallocation is used
* @param classmember should be set if the inspected function is a class member * @param classmember should be set if the inspected function is a class member
* @param all has the getcode been simplified according to the "--all" rules?
* @param sz size of type, used to check for mismatching size of allocation. for example "int *a;" => the sz is "sizeof(int)" * @param sz size of type, used to check for mismatching size of allocation. for example "int *a;" => the sz is "sizeof(int)"
* @return Newly allocated token array. Caller needs to release reserved * @return Newly allocated token array. Caller needs to release reserved
* memory by calling Tokenizer::deleteTokens(returnValue); * memory by calling Tokenizer::deleteTokens(returnValue);
@ -269,16 +267,15 @@ public:
* - &use : the address of the variable is taken * - &use : the address of the variable is taken
* - ::use : calling member function of class * - ::use : calling member function of class
*/ */
Token *getcode(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, bool classmember, bool &all, unsigned int sz); Token *getcode(const Token *tok, std::list<const Token *> callstack, const unsigned int varid, AllocType &alloctype, AllocType &dealloctype, bool classmember, unsigned int sz);
/** /**
* Simplify code e.g. by replacing empty "{ }" with ";" * Simplify code e.g. by replacing empty "{ }" with ";"
* @param tok first token. The tokens list can be modified. * @param tok first token. The tokens list can be modified.
* @param all is the code simplified according to the "--all" rules or not
*/ */
void simplifycode(Token *tok, bool &all); void simplifycode(Token *tok);
static const Token *findleak(const Token *tokens, bool all); static const Token *findleak(const Token *tokens);
/** /**
* Checking the variable varname * Checking the variable varname
@ -293,14 +290,14 @@ public:
/** Report all possible errors (for the --errorlist) */ /** Report all possible errors (for the --errorlist) */
void getErrorMessages() void getErrorMessages()
{ {
memleakError(0, "varname", false); memleakError(0, "varname");
resourceLeakError(0, "varname", false); resourceLeakError(0, "varname");
deallocDeallocError(0, "varname"); deallocDeallocError(0, "varname");
deallocuseError(0, "varname"); deallocuseError(0, "varname");
mismatchSizeError(0, "sz"); mismatchSizeError(0, "sz");
std::list<const Token *> callstack; std::list<const Token *> callstack;
mismatchAllocDealloc(callstack, "varname", false); mismatchAllocDealloc(callstack, "varname");
} }
/** /**

View File

@ -402,8 +402,7 @@ private:
callstack.push_back(0); callstack.push_back(0);
CheckMemoryLeak::AllocType allocType, deallocType; CheckMemoryLeak::AllocType allocType, deallocType;
allocType = deallocType = CheckMemoryLeak::No; allocType = deallocType = CheckMemoryLeak::No;
bool all = false; Token *tokens = checkMemoryLeak.getcode(tokenizer.tokens(), callstack, varId, allocType, deallocType, false, 1);
Token *tokens = checkMemoryLeak.getcode(tokenizer.tokens(), callstack, varId, allocType, deallocType, false, all, 1);
// stringify.. // stringify..
std::ostringstream ret; std::ostringstream ret;
@ -577,7 +576,7 @@ private:
} }
std::string simplifycode(const char code[], bool &all) const std::string simplifycode(const char code[]) const
{ {
// Tokenize.. // Tokenize..
Tokenizer tokenizer; Tokenizer tokenizer;
@ -602,10 +601,8 @@ private:
} }
Settings settings; Settings settings;
settings.inconclusive = all;
CheckMemoryLeakInFunction checkMemoryLeak(&tokenizer, &settings, NULL); CheckMemoryLeakInFunction checkMemoryLeak(&tokenizer, &settings, NULL);
all = false; checkMemoryLeak.simplifycode(tokens);
checkMemoryLeak.simplifycode(tokens, all);
std::ostringstream ret; std::ostringstream ret;
for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next()) for (const Token *tok = tokenizer.tokens(); tok; tok = tok->next())
@ -614,20 +611,6 @@ private:
return ret.str(); return ret.str();
} }
std::string simplifycode(const char code[])
{
bool all = false;
const std::string str1 = simplifycode(code, all);
ASSERT_EQUALS(0, (unsigned int)(all ? 1 : 0));
all = true;
const std::string str2 = simplifycode(code, all);
ASSERT_EQUALS((unsigned int)(all ? 1 : 0), (unsigned int)((str1 != str2) ? 1 : 0));
return all ? (str1 + "\n" + str2) : str1;
}
// Test that the CheckMemoryLeaksInFunction::simplifycode works // Test that the CheckMemoryLeaksInFunction::simplifycode works
void simplifycode() void simplifycode()
@ -649,7 +632,7 @@ private:
ASSERT_EQUALS("; alloc ; if return ;", simplifycode("; alloc ; loop { if return ; if continue ; }")); ASSERT_EQUALS("; alloc ; if return ;", simplifycode("; alloc ; loop { if return ; if continue ; }"));
ASSERT_EQUALS("; alloc ; if return ;", simplifycode("; alloc ; loop { if continue ; else return ; }")); ASSERT_EQUALS("; alloc ; if return ;", simplifycode("; alloc ; loop { if continue ; else return ; }"));
ASSERT_EQUALS("; alloc ; dealloc ;\n; alloc ;", simplifycode("; alloc ; if(!var) { return ; } if { dealloc ; }")); ASSERT_EQUALS("; alloc ; if dealloc ;", simplifycode("; alloc ; if(!var) { return ; } if { dealloc ; }"));
ASSERT_EQUALS("; if alloc ; else assign ; return use ;", simplifycode("; callfunc ; if callfunc { alloc ; } else { assign ; } return use ;")); ASSERT_EQUALS("; if alloc ; else assign ; return use ;", simplifycode("; callfunc ; if callfunc { alloc ; } else { assign ; } return use ;"));
ASSERT_EQUALS("; dealloc ; return ;", simplifycode("; while1 { if callfunc { dealloc ; return ; } else { continue ; } }")); ASSERT_EQUALS("; dealloc ; return ;", simplifycode("; while1 { if callfunc { dealloc ; return ; } else { continue ; } }"));
@ -662,7 +645,7 @@ private:
ASSERT_EQUALS("; alloc ;", simplifycode("; alloc; if { dealloc; return; }")); ASSERT_EQUALS("; alloc ;", simplifycode("; alloc; if { dealloc; return; }"));
ASSERT_EQUALS("; alloc ;", simplifycode("; alloc; if { return use; }")); ASSERT_EQUALS("; alloc ;", simplifycode("; alloc; if { return use; }"));
ASSERT_EQUALS("; alloc ; return ;", simplifycode(";alloc;if{return;}return;")); ASSERT_EQUALS("; alloc ; return ;", simplifycode(";alloc;if{return;}return;"));
ASSERT_EQUALS("; alloc ; assign ; dealloc ;", simplifycode(";alloc;if{assign;}dealloc;")); ASSERT_EQUALS("; alloc ; if assign ; dealloc ;", simplifycode(";alloc;if{assign;}dealloc;"));
// if(var) // if(var)
ASSERT_EQUALS("; alloc ; return use ;", simplifycode("; alloc ; return use ;")); ASSERT_EQUALS("; alloc ; return use ;", simplifycode("; alloc ; return use ;"));
@ -698,7 +681,7 @@ private:
TODO_ASSERT_EQUALS("; assign ; if alloc ; }", simplifycode("; assign ; { dealloc ; if alloc ; } }")); TODO_ASSERT_EQUALS("; assign ; if alloc ; }", simplifycode("; assign ; { dealloc ; if alloc ; } }"));
// callfunc.. // callfunc..
ASSERT_EQUALS("; callfunc ;\n;", simplifycode(";callfunc;")); ASSERT_EQUALS("; callfunc ;", simplifycode(";callfunc;"));
// exit.. // exit..
ASSERT_EQUALS("; exit ;", simplifycode("; alloc; exit;")); ASSERT_EQUALS("; exit ;", simplifycode("; alloc; exit;"));
@ -710,13 +693,13 @@ private:
TODO_ASSERT_EQUALS(";\n; alloc ;", simplifycode("; alloc ; ifv { exit; }")); TODO_ASSERT_EQUALS(";\n; alloc ;", simplifycode("; alloc ; ifv { exit; }"));
// dealloc; dealloc; // dealloc; dealloc;
ASSERT_EQUALS("; alloc ; dealloc ; dealloc ;", simplifycode("; alloc ; if { dealloc ; } dealloc ;")); ASSERT_EQUALS("; alloc ; if dealloc ; dealloc ;", simplifycode("; alloc ; if { dealloc ; } dealloc ;"));
} }
// is there a leak in given code? if so, return the linenr // is there a leak in given code? if so, return the linenr
unsigned int dofindleak(const char code[], bool all = false) const unsigned int dofindleak(const char code[]) const
{ {
// Tokenize.. // Tokenize..
Settings settings; Settings settings;
@ -746,7 +729,7 @@ private:
} }
} }
const Token *tok = CheckMemoryLeakInFunction::findleak(tokenizer.tokens(), all); const Token *tok = CheckMemoryLeakInFunction::findleak(tokenizer.tokens());
return (tok ? tok->linenr() : (unsigned int)(-1)); return (tok ? tok->linenr() : (unsigned int)(-1));
} }
@ -1247,8 +1230,6 @@ private:
"}\n"); "}\n");
check(code.c_str(), false); check(code.c_str(), false);
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
check(code.c_str(), true);
ASSERT_EQUALS("[test.cpp:12]: (possible error) Memory leak: str\n", errout.str());
} }
void switch3() void switch3()
@ -1863,14 +1844,8 @@ private:
" free(buf);\n" " free(buf);\n"
" else\n" " else\n"
" free(new_buf);\n" " free(new_buf);\n"
"}\n", true); "}\n", false);
ASSERT_EQUALS("", errout.str());
// There isn't a memory leak in the code
TODO_ASSERT_EQUALS("", errout.str());
// This assertion checks that the message stays the same. Upon changes in the error message
// we will be notified
ASSERT_EQUALS("[test.cpp:11]: (possible error) Memory leak: buf\n", errout.str());
} }
void realloc6() void realloc6()
@ -2725,9 +2700,9 @@ private:
/** /**
* Tokenize and execute leak check for given code * Tokenize and execute leak check for given code
* @param code Source code * @param code Source code
* @param showAll Not used * @param inconclusive inconclusive checking
*/ */
void check(const char code[], bool = false) void check(const char code[], bool inconclusive = false)
{ {
// Tokenize.. // Tokenize..
Tokenizer tokenizer; Tokenizer tokenizer;
@ -2741,7 +2716,7 @@ private:
// Check for memory leaks.. // Check for memory leaks..
Settings settings; Settings settings;
settings.inconclusive = true; settings.inconclusive = inconclusive;
settings._checkCodingStyle = true; settings._checkCodingStyle = true;
tokenizer.fillFunctionList(); tokenizer.fillFunctionList();
CheckMemoryLeakInClass checkMemoryLeak(&tokenizer, &settings, this); CheckMemoryLeakInClass checkMemoryLeak(&tokenizer, &settings, this);
@ -2800,7 +2775,7 @@ private:
" delete [] str2;\n" " delete [] str2;\n"
"}\n", true); "}\n", true);
ASSERT_EQUALS("[test.cpp:4]: (possible error) Memory leak: Fred::str1\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: Fred::str1\n", errout.str());
} }
@ -2825,7 +2800,7 @@ private:
" free(str1);\n" " free(str1);\n"
"}\n", true); "}\n", true);
ASSERT_EQUALS("[test.cpp:17]: (possible error) Mismatching allocation and deallocation: Fred::str1\n", errout.str()); ASSERT_EQUALS("[test.cpp:17]: (error) Mismatching allocation and deallocation: Fred::str1\n", errout.str());
} }
void class3() void class3()
@ -2972,7 +2947,7 @@ private:
" int * p;\n" " int * p;\n"
" A() { p = new int; }\n" " A() { p = new int; }\n"
"};\n", true); "};\n", true);
ASSERT_EQUALS("[test.cpp:4]: (possible error) Memory leak: A::p\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: A::p\n", errout.str());
} }
void class11() void class11()
@ -2985,7 +2960,7 @@ private:
"};\n" "};\n"
"A::A() : p(new int[10])\n" "A::A() : p(new int[10])\n"
"{ }", true); "{ }", true);
ASSERT_EQUALS("[test.cpp:4]: (possible error) Memory leak: A::p\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: A::p\n", errout.str());
} }
void class12() void class12()
@ -3008,7 +2983,7 @@ private:
"\n" "\n"
"void A::cleanup()\n" "void A::cleanup()\n"
"{ delete [] p; }\n", true); "{ delete [] p; }\n", true);
ASSERT_EQUALS("[test.cpp:4]: (possible error) Memory leak: A::p\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (error) Memory leak: A::p\n", errout.str());
} }
void class13() void class13()
@ -3045,7 +3020,7 @@ private:
"\n" "\n"
"void A::init()\n" "void A::init()\n"
"{ p = new int[10]; }\n", true); "{ p = new int[10]; }\n", true);
ASSERT_EQUALS("[test.cpp:3]: (possible error) Memory leak: A::p\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (error) Memory leak: A::p\n", errout.str());
} }
void class15() void class15()
@ -3162,7 +3137,7 @@ private:
"A::~A() {\n" "A::~A() {\n"
" delete [] pkt_buffer;\n" " delete [] pkt_buffer;\n"
"}\n", true); "}\n", true);
ASSERT_EQUALS("[test.cpp:14]: (possible error) Mismatching allocation and deallocation: A::pkt_buffer\n", errout.str()); ASSERT_EQUALS("[test.cpp:14]: (error) Mismatching allocation and deallocation: A::pkt_buffer\n", errout.str());
} }
void func1() void func1()