diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index b935e8915..ec1e512e9 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -998,15 +998,27 @@ static bool hasAssignSelf(const Token * first, const Token * last, const Token * { 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()) - return true; - } - else if (Token::Match(tok, "if ( & %var% ==|!= this )")) - { - if (tok->tokAt(3)->str() == rhs->str()) - return true; + 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; + } + else if (Token::Match(tok1, "& %var% ==|!= this")) + { + if (tok1->tokAt(1)->str() == rhs->str()) + return true; + } + } + } } } diff --git a/test/testclass.cpp b/test/testclass.cpp index 7986552ea..729c76a89 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -72,6 +72,7 @@ private: TEST_CASE(operatorEqToSelf2); // nested class TEST_CASE(operatorEqToSelf3); // multiple inheritance TEST_CASE(operatorEqToSelf4); // nested class with multiple inheritance + TEST_CASE(operatorEqToSelf5); // ticket # 1233 TEST_CASE(memsetOnStruct); TEST_CASE(memsetOnClass); @@ -681,6 +682,78 @@ private: 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 void checkVirtualDestructor(const char code[]) {