Skip to content

Commit

Permalink
Fix #11886 performance regression (hang) in 2.12dev
Browse files Browse the repository at this point in the history
  • Loading branch information
chrchr-github committed Aug 21, 2023
1 parent 03b952d commit 5423262
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 1 deletion.
14 changes: 13 additions & 1 deletion lib/symboldatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4350,6 +4350,18 @@ const Function *Function::getOverriddenFunction(bool *foundAllBaseClasses) const
return getOverriddenFunctionRecursive(nestedIn->definedType, foundAllBaseClasses);
}

// prevent recursion if base is the same except for different template parameters
static bool isDerivedFromItself(const std::string& thisName, const std::string& baseName)
{
const auto posThis = thisName.find('<');
if (posThis == std::string::npos)
return false;
const auto posBase = baseName.find('<');
if (posBase == std::string::npos)
return false;
return posThis == posBase && thisName.compare(0, posThis, baseName);
}

const Function * Function::getOverriddenFunctionRecursive(const ::Type* baseType, bool *foundAllBaseClasses) const
{
// check each base class
Expand Down Expand Up @@ -4402,7 +4414,7 @@ const Function * Function::getOverriddenFunctionRecursive(const ::Type* baseType
}
}

if (!derivedFromType->derivedFrom.empty() && !derivedFromType->hasCircularDependencies()) {
if (!derivedFromType->derivedFrom.empty() && !derivedFromType->hasCircularDependencies() && !isDerivedFromItself(baseType->classScope->className, i.name)) {
// avoid endless recursion, see #5289 Crash: Stack overflow in isImplicitlyVirtual_rec when checking SVN and
// #5590 with a loop within the class hierarchy.
const Function *func = getOverriddenFunctionRecursive(derivedFromType, foundAllBaseClasses);
Expand Down
15 changes: 15 additions & 0 deletions test/testclass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ class TestClass : public TestFixture {
TEST_CASE(const89);
TEST_CASE(const90);
TEST_CASE(const91);
TEST_CASE(const92);

TEST_CASE(const_handleDefaultParameters);
TEST_CASE(const_passThisToMemberOfOtherClass);
Expand Down Expand Up @@ -6654,6 +6655,20 @@ class TestClass : public TestFixture {
ASSERT_EQUALS("", errout.str());
}

void const92() { // #11886
checkConst("void g(int);\n"
"template<int n>\n"
"struct S : public S<n - 1> {\n"
" void f() {\n"
" g(n - 1);\n"
" }\n"
"};\n"
"template<>\n"
"struct S<0> {};\n"
"struct D : S<150> {};\n");
// don't hang
}

void const_handleDefaultParameters() {
checkConst("struct Foo {\n"
" void foo1(int i, int j = 0) {\n"
Expand Down

0 comments on commit 5423262

Please sign in to comment.