From cf65a73c473cb5f27fb4c861fea5a59154dbdc44 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Thu, 31 Mar 2011 19:40:28 -0400 Subject: [PATCH] fix CheckClass::operatorEq to check return type more closely (to match check description) --- lib/checkclass.cpp | 13 +++++++++---- lib/checkclass.h | 4 ++-- test/testclass.cpp | 40 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 47 insertions(+), 10 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 1c2d673d3..890cbbb2c 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -810,22 +810,27 @@ void CheckClass::operatorEq() for (scope = symbolDatabase->scopeList.begin(); scope != symbolDatabase->scopeList.end(); ++scope) { + if (!scope->isClassOrStruct()) + continue; + std::list::const_iterator func; for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { if (func->type == Function::eOperatorEqual && func->access != Private) { - if (func->token->strAt(-1) == "void") - operatorEqReturnError(func->token->tokAt(-1)); + // use definition for check so we don't have to deal with qualification + 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 + " &\'"); } //--------------------------------------------------------------------------- diff --git a/lib/checkclass.h b/lib/checkclass.h index 25f2eddae..738cbb891 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -119,7 +119,7 @@ private: 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 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 thisSubtractionError(const Token *tok); void operatorEqRetRefThisError(const Token *tok); @@ -135,7 +135,7 @@ private: c.operatorEqVarError(0, "classname", ""); c.unusedPrivateFunctionError(0, "classname", "funcname"); c.memsetError(0, "memfunc", "classname", "class"); - c.operatorEqReturnError(0); + c.operatorEqReturnError(0, "class"); //c.virtualDestructorError(0, "Base", "Derived"); c.thisSubtractionError(0); c.operatorEqRetRefThisError(0); diff --git a/test/testclass.cpp b/test/testclass.cpp index 57eacf3c7..dfbf2c4c8 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -99,6 +99,7 @@ private: TEST_CASE(noConstructor5); TEST_CASE(operatorEq1); + TEST_CASE(operatorEq2); TEST_CASE(operatorEqRetRefThis1); TEST_CASE(operatorEqRetRefThis2); // ticket #1323 TEST_CASE(operatorEqRetRefThis3); // ticket #1405 @@ -236,7 +237,7 @@ private: " void goo() {}" " void operator=(const A&);\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" "{\n" @@ -270,14 +271,45 @@ private: "public:\n" " void operator=(const B&);\n" "};\n"); - ASSERT_EQUALS("[test.cpp:4]: (style) 'operator=' should return something\n" - "[test.cpp:9]: (style) 'operator=' should return something\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (style) 'A::operator=' should return 'A &'\n" + "[test.cpp:9]: (style) 'B::operator=' should return 'B &'\n", errout.str()); checkOpertorEq("struct A\n" "{\n" " void operator=(const A&);\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