Fix #11886 performance regression (hang) in 2.12dev (#5355)

Or maybe we should just limit the recursion depth.
This commit is contained in:
chrchr-github 2023-08-22 21:01:52 +02:00 committed by GitHub
parent af46c68a94
commit 6ffe08c9b3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 2 deletions

View File

@ -4350,6 +4350,17 @@ 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)
{
if (thisName.back() != '>')
return false;
const auto pos = thisName.find('<');
if (pos == std::string::npos)
return false;
return thisName.compare(0, pos + 1, baseName, 0, pos + 1) == 0;
}
const Function * Function::getOverriddenFunctionRecursive(const ::Type* baseType, bool *foundAllBaseClasses) const
{
// check each base class
@ -4402,7 +4413,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);

View File

@ -5548,7 +5548,7 @@ static void valueFlowSymbolicOperators(const SymbolDatabase& symboldatabase, con
ValueFlow::Value v = value;
v.bound = ValueFlow::Value::Bound::Point;
v.valueType = ValueFlow::Value::ValueType::INT;
v.errorPath.emplace_back(strlenTok, "Return index of string to the first element that is 0");
v.errorPath.emplace_back(strlenTok, "Return index of first '\\0' character in string");
setTokenValue(tok, std::move(v), settings);
}
}

View File

@ -183,6 +183,7 @@ private:
TEST_CASE(const89);
TEST_CASE(const90);
TEST_CASE(const91);
TEST_CASE(const92);
TEST_CASE(const_handleDefaultParameters);
TEST_CASE(const_passThisToMemberOfOtherClass);
@ -6654,6 +6655,20 @@ private:
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"