fix CheckClass::operatorEq to check return type more closely (to match check description)

This commit is contained in:
Robert Reif 2011-03-31 19:40:28 -04:00
parent 0dbf5c6151
commit cf65a73c47
3 changed files with 47 additions and 10 deletions

View File

@ -810,22 +810,27 @@ void CheckClass::operatorEq()
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;
for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func)
{ {
if (func->type == Function::eOperatorEqual && func->access != Private) if (func->type == Function::eOperatorEqual && func->access != Private)
{ {
if (func->token->strAt(-1) == "void") // use definition for check so we don't have to deal with qualification
operatorEqReturnError(func->token->tokAt(-1)); if (!(Token::Match(func->tokenDef->tokAt(-3), ";|}|{|public:|protected:|private: %type% &") &&
func->tokenDef->strAt(-2) == scope->className))
operatorEqReturnError(func->tokenDef->tokAt(-1), scope->className);
} }
} }
} }
} }
void CheckClass::operatorEqReturnError(const Token *tok) void CheckClass::operatorEqReturnError(const Token *tok, const std::string &className)
{ {
reportError(tok, Severity::style, "operatorEq", "'operator=' should return something"); reportError(tok, Severity::style, "operatorEq", "\'" + className + "::operator=' should return \'" + className + " &\'");
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------

View File

@ -119,7 +119,7 @@ private:
void operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname); void operatorEqVarError(const Token *tok, const std::string &classname, const std::string &varname);
void unusedPrivateFunctionError(const Token *tok, const std::string &classname, const std::string &funcname); void unusedPrivateFunctionError(const Token *tok, const std::string &classname, const std::string &funcname);
void memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type); void memsetError(const Token *tok, const std::string &memfunc, const std::string &classname, const std::string &type);
void operatorEqReturnError(const Token *tok); void operatorEqReturnError(const Token *tok, const std::string &className);
void virtualDestructorError(const Token *tok, const std::string &Base, const std::string &Derived); void virtualDestructorError(const Token *tok, const std::string &Base, const std::string &Derived);
void thisSubtractionError(const Token *tok); void thisSubtractionError(const Token *tok);
void operatorEqRetRefThisError(const Token *tok); void operatorEqRetRefThisError(const Token *tok);
@ -135,7 +135,7 @@ private:
c.operatorEqVarError(0, "classname", ""); c.operatorEqVarError(0, "classname", "");
c.unusedPrivateFunctionError(0, "classname", "funcname"); c.unusedPrivateFunctionError(0, "classname", "funcname");
c.memsetError(0, "memfunc", "classname", "class"); c.memsetError(0, "memfunc", "classname", "class");
c.operatorEqReturnError(0); c.operatorEqReturnError(0, "class");
//c.virtualDestructorError(0, "Base", "Derived"); //c.virtualDestructorError(0, "Base", "Derived");
c.thisSubtractionError(0); c.thisSubtractionError(0);
c.operatorEqRetRefThisError(0); c.operatorEqRetRefThisError(0);

View File

@ -99,6 +99,7 @@ private:
TEST_CASE(noConstructor5); TEST_CASE(noConstructor5);
TEST_CASE(operatorEq1); TEST_CASE(operatorEq1);
TEST_CASE(operatorEq2);
TEST_CASE(operatorEqRetRefThis1); TEST_CASE(operatorEqRetRefThis1);
TEST_CASE(operatorEqRetRefThis2); // ticket #1323 TEST_CASE(operatorEqRetRefThis2); // ticket #1323
TEST_CASE(operatorEqRetRefThis3); // ticket #1405 TEST_CASE(operatorEqRetRefThis3); // ticket #1405
@ -236,7 +237,7 @@ private:
" void goo() {}" " void goo() {}"
" void operator=(const A&);\n" " void operator=(const A&);\n"
"};\n"); "};\n");
ASSERT_EQUALS("[test.cpp:4]: (style) 'operator=' should return something\n", errout.str()); ASSERT_EQUALS("[test.cpp:4]: (style) 'A::operator=' should return 'A &'\n", errout.str());
checkOpertorEq("class A\n" checkOpertorEq("class A\n"
"{\n" "{\n"
@ -270,14 +271,45 @@ private:
"public:\n" "public:\n"
" void operator=(const B&);\n" " void operator=(const B&);\n"
"};\n"); "};\n");
ASSERT_EQUALS("[test.cpp:4]: (style) 'operator=' should return something\n" ASSERT_EQUALS("[test.cpp:4]: (style) 'A::operator=' should return 'A &'\n"
"[test.cpp:9]: (style) 'operator=' should return something\n", errout.str()); "[test.cpp:9]: (style) 'B::operator=' should return 'B &'\n", errout.str());
checkOpertorEq("struct A\n" checkOpertorEq("struct A\n"
"{\n" "{\n"
" void operator=(const A&);\n" " void operator=(const A&);\n"
"};\n"); "};\n");
ASSERT_EQUALS("[test.cpp:3]: (style) 'operator=' should return something\n", errout.str()); ASSERT_EQUALS("[test.cpp:3]: (style) 'A::operator=' should return 'A &'\n", errout.str());
}
void operatorEq2()
{
checkOpertorEq("class A\n"
"{\n"
"public:\n"
" void * operator=(const A&);\n"
"};\n");
ASSERT_EQUALS("[test.cpp:4]: (style) 'A::operator=' should return 'A &'\n", errout.str());
checkOpertorEq("class A\n"
"{\n"
"public:\n"
" A * operator=(const A&);\n"
"};\n");
ASSERT_EQUALS("[test.cpp:4]: (style) 'A::operator=' should return 'A &'\n", errout.str());
checkOpertorEq("class A\n"
"{\n"
"public:\n"
" const A & operator=(const A&);\n"
"};\n");
ASSERT_EQUALS("[test.cpp:4]: (style) 'A::operator=' should return 'A &'\n", errout.str());
checkOpertorEq("class A\n"
"{\n"
"public:\n"
" B & operator=(const A&);\n"
"};\n");
ASSERT_EQUALS("[test.cpp:4]: (style) 'A::operator=' should return 'A &'\n", errout.str());
} }
// Check that operator Equal returns reference to this // Check that operator Equal returns reference to this