#6298 stack overflow in Scope::findFunctionInBase (endless recursion). Fix handling of circular class hierarchy

This commit is contained in:
amai2012 2015-07-01 00:04:01 +02:00
parent 108b035af2
commit 480a5672b0
5 changed files with 47 additions and 6 deletions

View File

@ -844,8 +844,16 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
// fill in base class info
for (std::list<Type>::iterator it = typeList.begin(); it != typeList.end(); ++it) {
// finish filling in base class info
for (unsigned int i = 0; i < it->derivedFrom.size(); ++i)
it->derivedFrom[i].type = findType(it->derivedFrom[i].nameTok, it->enclosingScope);
for (unsigned int i = 0; i < it->derivedFrom.size(); ++i) {
const Type* found = findType(it->derivedFrom[i].nameTok, it->enclosingScope);
if (found && found->findDependency(&(*it))) {
// circular dependency
//_tokenizer->syntaxError(nullptr);
}
else {
it->derivedFrom[i].type = found;
}
}
}
// fill in friend info
@ -2054,6 +2062,16 @@ bool Type::hasCircularDependencies(std::set<BaseInfo>* anchestors) const
return false;
}
bool Type::findDependency(const Type* anchestor) const {
if (this==anchestor)
return true;
for (std::vector<BaseInfo>::const_iterator parent=derivedFrom.begin(); parent!=derivedFrom.end(); ++parent) {
if (parent->type && parent->type->findDependency(anchestor))
return true;
}
return false;
}
bool Variable::arrayDimensions(const Library* lib)
{
const Library::Container* container = lib->detectContainer(_start);

View File

@ -122,7 +122,14 @@ public:
* @param anchestors list of anchestors. For internal usage only, clients should not supply this argument.
* @return true if there is a circular dependency
*/
bool hasCircularDependencies(std::set<BaseInfo>* anchestors = 0) const;
bool hasCircularDependencies(std::set<BaseInfo>* anchestors = nullptr) const;
/**
* Check for dependency
* @param anchestor potential anchestor
* @return true if there is a dependency
*/
bool findDependency(const Type* anchestor) const;
};
/** @brief Information about a member variable. */

View File

@ -4929,14 +4929,14 @@ private:
"int MixerParticipant::GetAudioFrame() {\n"
" return 0;\n"
"}");
ASSERT_EQUALS("[test.cpp:4] -> [test.cpp:2]: (performance, inconclusive) Technically the member function 'MixerParticipant::GetAudioFrame' can be static.\n", errout.str());
ASSERT_EQUALS("", errout.str());
checkConst("class MixerParticipant : public MixerParticipant {\n"
" bool InitializeFileReader() {\n"
" printf(\"music\");\n"
" }\n"
"};");
ASSERT_EQUALS("[test.cpp:2]: (performance, inconclusive) Technically the member function 'MixerParticipant::InitializeFileReader' can be static.\n", errout.str());
ASSERT_EQUALS("", errout.str());
// Based on an example from SVN source code causing an endless recursion within CheckClass::isConstMemberFunc()
// A more complete example including a template declaration like

View File

@ -260,6 +260,7 @@ private:
TEST_CASE(functionPrototype); // ticket #5867
TEST_CASE(lambda); // ticket #5867
TEST_CASE(circularDependencies); // 6298
}
void array() const {
@ -2914,6 +2915,21 @@ private:
ASSERT_EQUALS(Scope::eLambda, scope->type);
}
}
// #6298 "stack overflow in Scope::findFunctionInBase (endless recursion)"
void circularDependencies() {
check("template<template<class> class E,class D> class C : E<D> {\n"
" public:\n"
" int f();\n"
"};\n"
"class E : C<D,int> {\n"
" public:\n"
" int f() { return C< ::D,int>::f(); }\n"
"};\n"
"int main() {\n"
" E c;\n"
" c.f();\n"
"}");
}
};
REGISTER_TEST(TestSymbolDatabase)

View File

@ -722,7 +722,7 @@ private:
" C a;\n"
"}");
ASSERT_EQUALS("[test.cpp:10]: (style) Unused private function: 'InfiniteA::foo'\n", errout.str());
ASSERT_EQUALS("", errout.str());
}
void staticVariable() {