diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 2d88ae183..09c72b1ce 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -1182,7 +1182,7 @@ void CheckClass::operatorEqRetRefThis() } } -void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, const Token *tok, const Token *last) +void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, const Token *tok, const Token *last, std::set* analyzedFunctions) { bool foundReturn = false; @@ -1210,10 +1210,15 @@ void CheckClass::checkReturnPtrThis(const Scope *scope, const Function *func, co // make sure it's not a const function if (!it->isConst) { /** @todo make sure argument types match */ - // make sure it's not the same function - if (&*it != func) - checkReturnPtrThis(scope, &*it, it->arg->link()->next(), it->arg->link()->next()->link()); - + // avoid endless recursions + if (!analyzedFunctions || analyzedFunctions->find(&*it)==analyzedFunctions->end()) { + std::set local_analyzedFunctions; + if (!analyzedFunctions) + analyzedFunctions=&local_analyzedFunctions; + analyzedFunctions->insert(&*it); + checkReturnPtrThis(scope, &*it, it->arg->link()->next(), it->arg->link()->next()->link(), + analyzedFunctions); + } // just bail for now else return; diff --git a/test/testclass.cpp b/test/testclass.cpp index b6b376b76..844b3063d 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -67,6 +67,7 @@ private: TEST_CASE(operatorEqRetRefThis4); // ticket #1451 TEST_CASE(operatorEqRetRefThis5); // ticket #1550 TEST_CASE(operatorEqRetRefThis6); // ticket #2479 + TEST_CASE(operatorEqRetRefThis7); // ticket #5782 endless recursion TEST_CASE(operatorEqToSelf1); // single class TEST_CASE(operatorEqToSelf2); // nested class TEST_CASE(operatorEqToSelf3); // multiple inheritance @@ -893,6 +894,25 @@ private: "}"); } + void operatorEqRetRefThis7() { // ticket #5782 Endless recursion in CheckClass::checkReturnPtrThis() + checkOpertorEqRetRefThis( + "class basic_fbstring {\n" + " basic_fbstring& operator=(int il) {\n" + " return assign();\n" + " }\n" + " basic_fbstring& assign() {\n" + " return replace();\n" + " }\n" + " basic_fbstring& replaceImplDiscr() {\n" + " return replace();\n" + " }\n" + " basic_fbstring& replace() {\n" + " return replaceImplDiscr();\n" + " }\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); + } + // Check that operator Equal checks for assignment to self void checkOpertorEqToSelf(const char code[]) { // Clear the error log