#5782 Endless recursion in CheckClass::checkReturnPtrThis(). Break endless recursion by remembering the callstack

This commit is contained in:
Alexander Mai 2014-05-11 12:26:24 +02:00
parent 0dfbbd0f80
commit b139ae3209
2 changed files with 30 additions and 5 deletions

View File

@ -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<const Function*>* analyzedFunctions)
{ {
bool foundReturn = false; 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 // make sure it's not a const function
if (!it->isConst) { if (!it->isConst) {
/** @todo make sure argument types match */ /** @todo make sure argument types match */
// make sure it's not the same function // avoid endless recursions
if (&*it != func) if (!analyzedFunctions || analyzedFunctions->find(&*it)==analyzedFunctions->end()) {
checkReturnPtrThis(scope, &*it, it->arg->link()->next(), it->arg->link()->next()->link()); std::set<const Function*> 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 // just bail for now
else else
return; return;

View File

@ -67,6 +67,7 @@ private:
TEST_CASE(operatorEqRetRefThis4); // ticket #1451 TEST_CASE(operatorEqRetRefThis4); // ticket #1451
TEST_CASE(operatorEqRetRefThis5); // ticket #1550 TEST_CASE(operatorEqRetRefThis5); // ticket #1550
TEST_CASE(operatorEqRetRefThis6); // ticket #2479 TEST_CASE(operatorEqRetRefThis6); // ticket #2479
TEST_CASE(operatorEqRetRefThis7); // ticket #5782 endless recursion
TEST_CASE(operatorEqToSelf1); // single class TEST_CASE(operatorEqToSelf1); // single class
TEST_CASE(operatorEqToSelf2); // nested class TEST_CASE(operatorEqToSelf2); // nested class
TEST_CASE(operatorEqToSelf3); // multiple inheritance 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 // Check that operator Equal checks for assignment to self
void checkOpertorEqToSelf(const char code[]) { void checkOpertorEqToSelf(const char code[]) {
// Clear the error log // Clear the error log