change CheckClass::operatorEqToSelf to make better use of the symbol database

This commit is contained in:
Robert Reif 2011-03-31 19:53:35 -04:00
parent cf65a73c47
commit a39444a40f
2 changed files with 17 additions and 31 deletions

View File

@ -965,6 +965,9 @@ void CheckClass::operatorEqToSelf()
for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope)
{ {
if (!scope->isClassOrStruct())
continue;
std::list<Function>::const_iterator func; std::list<Function>::const_iterator func;
// skip classes with multiple inheritance // skip classes with multiple inheritance
@ -979,32 +982,13 @@ void CheckClass::operatorEqToSelf()
if (Token::Match(func->tokenDef->tokAt(-3), ";|}|{|public:|protected:|private: %type% &") && if (Token::Match(func->tokenDef->tokAt(-3), ";|}|{|public:|protected:|private: %type% &") &&
func->tokenDef->strAt(-2) == scope->className) func->tokenDef->strAt(-2) == scope->className)
{ {
// check for proper function parameter signature // find the parameter name
if ((Token::Match(func->tokenDef->next(), "( const %var% & )") || const Token *rhs = func->argumentList.begin()->nameToken();
Token::Match(func->tokenDef->next(), "( const %var% & %var% )")) &&
func->tokenDef->strAt(3) == scope->className) if (!hasAssignSelf(&(*func), rhs))
{ {
// find the parameter name if (hasDeallocation(&(*func)))
const Token *rhs = func->token; operatorEqToSelfError(func->token);
while (rhs->str() != "&")
rhs = rhs->next();
rhs = rhs->next();
// find the ')'
const Token *tok = func->token->next()->link();
const Token *tok1 = tok;
if (tok1 && tok1->tokAt(1) && tok1->tokAt(1)->str() == "{" && tok1->tokAt(1)->link())
{
const Token *first = tok1->tokAt(1);
const Token *last = first->link();
if (!hasAssignSelf(first, last, rhs))
{
if (hasDeallocation(first, last))
operatorEqToSelfError(tok);
}
}
} }
} }
} }
@ -1012,7 +996,7 @@ void CheckClass::operatorEqToSelf()
} }
} }
bool CheckClass::hasDeallocation(const Token *first, const Token *last) bool CheckClass::hasDeallocation(const Function *func)
{ {
// This function is called when no simple check was found for assignment // This function is called when no simple check was found for assignment
// to self. We are currently looking for a specific sequence of: // to self. We are currently looking for a specific sequence of:
@ -1021,7 +1005,8 @@ bool CheckClass::hasDeallocation(const Token *first, const Token *last)
// Unfortunately, this is necessary to prevent false positives. // Unfortunately, this is necessary to prevent false positives.
// This check needs to do careful analysis someday to get this // This check needs to do careful analysis someday to get this
// correct with a high degree of certainty. // correct with a high degree of certainty.
for (const Token *tok = first; tok && (tok != last); tok = tok->next()) const Token *last = func->start->link();
for (const Token *tok = func->start; tok && (tok != last); tok = tok->next())
{ {
// check for deallocating memory // check for deallocating memory
if (Token::Match(tok, "{|;|, free ( %var%")) if (Token::Match(tok, "{|;|, free ( %var%"))
@ -1086,9 +1071,10 @@ bool CheckClass::hasDeallocation(const Token *first, const Token *last)
return false; return false;
} }
bool CheckClass::hasAssignSelf(const Token *first, const Token *last, const Token *rhs) bool CheckClass::hasAssignSelf(const Function *func, const Token *rhs)
{ {
for (const Token *tok = first; tok && tok != last; tok = tok->next()) const Token *last = func->start->link();
for (const Token *tok = func->start; tok && tok != last; tok = tok->next())
{ {
if (Token::simpleMatch(tok, "if (")) if (Token::simpleMatch(tok, "if ("))
{ {

View File

@ -165,8 +165,8 @@ private:
void checkReturnPtrThis(const Scope *scope, const Function *func, const Token *tok, const Token *last); void checkReturnPtrThis(const Scope *scope, const Function *func, const Token *tok, const Token *last);
// operatorEqToSelf helper functions // operatorEqToSelf helper functions
bool hasDeallocation(const Token *first, const Token *last); bool hasDeallocation(const Function *func);
bool hasAssignSelf(const Token *first, const Token *last, const Token *rhs); bool hasAssignSelf(const Function *func, const Token *rhs);
// checkConst helper functions // checkConst helper functions
bool isMemberVar(const Scope *scope, const Token *tok); bool isMemberVar(const Scope *scope, const Token *tok);