Fixed #1233 (false positive: operator = should check for assignment to self)

This commit is contained in:
Robert Reif 2010-01-08 19:15:24 +01:00 committed by Daniel Marjamäki
parent 686137415f
commit 60ef3ef872
2 changed files with 93 additions and 8 deletions

View File

@ -998,17 +998,29 @@ static bool hasAssignSelf(const Token * first, const Token * last, const Token *
{ {
for (const Token * tok = first; tok && tok != last; tok = tok->next()) for (const Token * tok = first; tok && tok != last; tok = tok->next())
{ {
if (Token::Match(tok, "if ( this ==|!= & %var% )")) if (Token::Match(tok, "if ("))
{ {
if (tok->tokAt(5)->str() == rhs->str()) const Token * tok1 = tok->tokAt(2);
const Token * tok2 = tok->tokAt(1)->link();
if (tok1 && tok2)
{
for (; tok1 && tok1 != tok2; tok1 = tok1->next())
{
if (Token::Match(tok1, "this ==|!= & %var%"))
{
if (tok1->tokAt(3)->str() == rhs->str())
return true; return true;
} }
else if (Token::Match(tok, "if ( & %var% ==|!= this )")) else if (Token::Match(tok1, "& %var% ==|!= this"))
{ {
if (tok->tokAt(3)->str() == rhs->str()) if (tok1->tokAt(1)->str() == rhs->str())
return true; return true;
} }
} }
}
}
}
return false; return false;
} }

View File

@ -72,6 +72,7 @@ private:
TEST_CASE(operatorEqToSelf2); // nested class TEST_CASE(operatorEqToSelf2); // nested class
TEST_CASE(operatorEqToSelf3); // multiple inheritance TEST_CASE(operatorEqToSelf3); // multiple inheritance
TEST_CASE(operatorEqToSelf4); // nested class with multiple inheritance TEST_CASE(operatorEqToSelf4); // nested class with multiple inheritance
TEST_CASE(operatorEqToSelf5); // ticket # 1233
TEST_CASE(memsetOnStruct); TEST_CASE(memsetOnStruct);
TEST_CASE(memsetOnClass); TEST_CASE(memsetOnClass);
@ -681,6 +682,78 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void operatorEqToSelf5()
{
// ticket # 1233
checkOpertorEqToSelf(
"class A\n"
"{\n"
"public:\n"
" char *s;\n"
" A & operator=(const A &a)\n"
" {\n"
" if((&a!=this))\n"
" {\n"
" free(s);\n"
" s = strdup(a.s);\n"
" }\n"
" return *this;\n"
" }\n"
"};");
ASSERT_EQUALS("", errout.str());
checkOpertorEqToSelf(
"class A\n"
"{\n"
"public:\n"
" char *s;\n"
" A & operator=(const A &a)\n"
" {\n"
" if(!(&a==this))\n"
" {\n"
" free(s);\n"
" s = strdup(a.s);\n"
" }\n"
" return *this;\n"
" }\n"
"};");
ASSERT_EQUALS("", errout.str());
checkOpertorEqToSelf(
"class A\n"
"{\n"
"public:\n"
" char *s;\n"
" A & operator=(const A &a)\n"
" {\n"
" if(false==(&a==this))\n"
" {\n"
" free(s);\n"
" s = strdup(a.s);\n"
" }\n"
" return *this;\n"
" }\n"
"};");
ASSERT_EQUALS("", errout.str());
checkOpertorEqToSelf(
"class A\n"
"{\n"
"public:\n"
" char *s;\n"
" A & operator=(const A &a)\n"
" {\n"
" if(true!=(&a==this))\n"
" {\n"
" free(s);\n"
" s = strdup(a.s);\n"
" }\n"
" return *this;\n"
" }\n"
"};");
ASSERT_EQUALS("", errout.str());
}
// Check that base classes have virtual destructors // Check that base classes have virtual destructors
void checkVirtualDestructor(const char code[]) void checkVirtualDestructor(const char code[])
{ {