diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index a6f96e297..0e7d92f9d 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -26,7 +26,6 @@ #include #include -#include #include //--------------------------------------------------------------------------- @@ -742,10 +741,6 @@ void CheckClass::memsetError(const Token *tok, const std::string &memfunc, const void CheckClass::operatorEq() { - // See #3296 - if (!_settings->inconclusive) - return; - if (!_settings->isEnabled("style")) return; @@ -762,7 +757,7 @@ void CheckClass::operatorEq() for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { if (func->type == Function::eOperatorEqual && func->access != Private) { // use definition for check so we don't have to deal with qualification - if (!(Token::Match(func->tokenDef->tokAt(-3), ";|}|{|public:|protected:|private: %type% &") && + if (!(Token::Match(func->tokenDef->tokAt(-3), ";|}|{|public:|protected:|private:|virtual %type% &") && func->tokenDef->strAt(-2) == scope->className)) { // make sure we really have a copy assignment operator if (Token::Match(func->tokenDef->tokAt(2), "const| %var% &")) { @@ -780,7 +775,7 @@ void CheckClass::operatorEq() void CheckClass::operatorEqReturnError(const Token *tok, const std::string &className) { - reportInconclusiveError(tok, Severity::style, "operatorEq", "Inconclusive: \'" + className + "::operator=' should return \'" + className + " &\'"); + reportInconclusiveError(tok, Severity::style, "operatorEq", "\'" + className + "::operator=' should return \'" + className + " &\'"); } //--------------------------------------------------------------------------- @@ -805,12 +800,10 @@ void CheckClass::operatorEqRetRefThis() for (func = scope->functionList.begin(); func != scope->functionList.end(); ++func) { if (func->type == Function::eOperatorEqual && func->hasBody) { // make sure return signature is correct - if (Token::Match(func->tokenDef->tokAt(-3), ";|}|{|public:|protected:|private: %type% &") && + if (Token::Match(func->tokenDef->tokAt(-3), ";|}|{|public:|protected:|private:|virtual %type% &") && func->tokenDef->strAt(-2) == scope->className) { - // find the ')' - const Token *tok = func->token->next()->link(); - checkReturnPtrThis(&(*scope), &(*func), tok->tokAt(2), tok->next()->link()); + checkReturnPtrThis(&(*scope), &(*func), func->start->next(), func->start->link()); } } } @@ -844,7 +837,7 @@ void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, co if (it->tokenDef->previous()->str() == "&" && it->tokenDef->strAt(-2) == scope->className) { // make sure it's not a const function - if (it->arg->link()->next()->str() != "const") { + if (!it->isConst) { /** @todo make sure argument types match */ // make sure it's not the same function if (&*it != func) @@ -860,8 +853,7 @@ void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, co } // check if *this is returned - else if (!(Token::Match(tok->next(), "(| * this ;|=") || - Token::Match(tok->next(), "(| * this +=") || + else if (!(Token::Match(tok->next(), "(| * this ;|=|+=") || Token::simpleMatch(tok->next(), "operator= (") || Token::simpleMatch(tok->next(), "this . operator= (") || (Token::Match(tok->next(), "%type% :: operator= (") && diff --git a/test/testclass.cpp b/test/testclass.cpp index 553c744e0..0409a07c1 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -110,6 +110,7 @@ private: TEST_CASE(operatorEq2); TEST_CASE(operatorEq3); // ticket #3051 TEST_CASE(operatorEq4); // ticket #3114 + TEST_CASE(operatorEq5); // ticket #3296 TEST_CASE(operatorEqRetRefThis1); TEST_CASE(operatorEqRetRefThis2); // ticket #1323 TEST_CASE(operatorEqRetRefThis3); // ticket #1405 @@ -238,7 +239,7 @@ private: " void goo() {}" " void operator=(const A&);\n" "};\n"); - ASSERT_EQUALS("[test.cpp:4]: (style) Inconclusive: 'A::operator=' should return 'A &'\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (style) 'A::operator=' should return 'A &'\n", errout.str()); checkOpertorEq("class A\n" "{\n" @@ -272,14 +273,14 @@ private: "public:\n" " void operator=(const B&);\n" "};\n"); - ASSERT_EQUALS("[test.cpp:4]: (style) Inconclusive: 'A::operator=' should return 'A &'\n" - "[test.cpp:9]: (style) Inconclusive: 'B::operator=' should return 'B &'\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) Inconclusive: 'A::operator=' should return 'A &'\n", errout.str()); + ASSERT_EQUALS("[test.cpp:3]: (style) 'A::operator=' should return 'A &'\n", errout.str()); } void operatorEq2() { @@ -288,28 +289,28 @@ private: "public:\n" " void * operator=(const A&);\n" "};\n"); - ASSERT_EQUALS("[test.cpp:4]: (style) Inconclusive: 'A::operator=' should return 'A &'\n", errout.str()); + 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) Inconclusive: 'A::operator=' should return 'A &'\n", errout.str()); + 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) Inconclusive: 'A::operator=' should return 'A &'\n", errout.str()); + 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) Inconclusive: 'A::operator=' should return 'A &'\n", errout.str()); + ASSERT_EQUALS("[test.cpp:4]: (style) 'A::operator=' should return 'A &'\n", errout.str()); } void operatorEq3() { // ticket #3051 @@ -329,6 +330,14 @@ private: ASSERT_EQUALS("", errout.str()); } + void operatorEq5() { // ticket #3296 (virtual operator) + checkOpertorEq( + "class A {\n" + " virtual A& operator=(const A &a) {return *this};\n" + "};"); + ASSERT_EQUALS("", errout.str()); + } + // Check that operator Equal returns reference to this void checkOpertorEqRetRefThis(const char code[]) { // Clear the error log @@ -6346,7 +6355,7 @@ private: ASSERT_EQUALS("", errout.str()); } - void constFriend() { // ticket #1921 + void constFriend() { // ticket #1921 const char code[] = "class foo {\n" " friend void f() { }\n" "};";