#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;
@ -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<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
else
return;

View File

@ -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