From 13f5b560ce363ef9fb9bb93b48425fd6f4f50780 Mon Sep 17 00:00:00 2001 From: Paul Fultz II Date: Fri, 12 Nov 2021 13:05:43 -0600 Subject: [PATCH] Fix 10555: FP knownConditionTrueFalse with non-const function in base class (#3559) --- lib/astutils.cpp | 18 ++++++++++-------- lib/symboldatabase.cpp | 18 ++++++++++++++++++ lib/symboldatabase.h | 2 ++ test/testcondition.cpp | 19 +++++++++++++++++++ 4 files changed, 49 insertions(+), 8 deletions(-) mode change 100644 => 100755 lib/symboldatabase.cpp mode change 100644 => 100755 test/testcondition.cpp diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 31a81accd..253a23401 100755 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -751,18 +751,20 @@ bool exprDependsOnThis(const Token* expr, bool onVar, nonneg int depth) return true; ++depth; // calling nonstatic method? - if (Token::Match(expr->previous(), "!!:: %name% (") && expr->function() && expr->function()->nestedIn && expr->function()->nestedIn->isClassOrStruct()) { + if (Token::Match(expr->previous(), "!!:: %name% (") && expr->function() && expr->function()->nestedIn && + expr->function()->nestedIn->isClassOrStruct()) { // is it a method of this? const Scope* fScope = expr->scope(); while (!fScope->functionOf && fScope->nestedIn) fScope = fScope->nestedIn; - const Scope* nestedIn = fScope->functionOf; - if (nestedIn && nestedIn->function) - nestedIn = nestedIn->function->token->scope(); - while (nestedIn && nestedIn != expr->function()->nestedIn) { - nestedIn = nestedIn->nestedIn; - } - return nestedIn == expr->function()->nestedIn; + + const Scope* classScope = fScope->functionOf; + if (classScope && classScope->function) + classScope = classScope->function->token->scope(); + + if (classScope && classScope->isClassOrStruct()) + return contains(classScope->findAssociatedScopes(), expr->function()->nestedIn); + return false; } else if (onVar && Token::Match(expr, "%var%") && expr->variable()) { const Variable* var = expr->variable(); return (var->isPrivate() || var->isPublic() || var->isProtected()); diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp old mode 100644 new mode 100755 index e0a560726..28b87b053 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -4892,6 +4892,24 @@ const Scope *Scope::findRecordInBase(const std::string & name) const return nullptr; } +std::vector Scope::findAssociatedScopes() const +{ + std::vector result = {this}; + if (isClassOrStruct() && definedType && !definedType->derivedFrom.empty()) { + const std::vector& derivedFrom = definedType->derivedFrom; + for (const Type::BaseInfo& i : derivedFrom) { + const Type* base = i.type; + if (base && base->classScope) { + if (contains(result, base->classScope)) + continue; + std::vector baseScopes = base->classScope->findAssociatedScopes(); + result.insert(result.end(), baseScopes.begin(), baseScopes.end()); + } + } + } + return result; +} + //--------------------------------------------------------------------------- static void checkVariableCallMatch(const Variable* callarg, const Variable* funcarg, size_t& same, size_t& fallback1, size_t& fallback2) diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 904a3698f..23a13738f 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -1192,6 +1192,8 @@ public: const Scope *findRecordInBase(const std::string &name) const; + std::vector findAssociatedScopes() const; + private: /** * @brief helper function for getVariableList() diff --git a/test/testcondition.cpp b/test/testcondition.cpp old mode 100644 new mode 100755 index 3452076c1..0021d4633 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -3894,6 +3894,25 @@ private: " return delta;\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + // #10555 + check("struct C {\n" + " int GetI() const { return i; }\n" + " int i{};\n" + "};\n" + "struct B {\n" + " C *m_PC{};\n" + " Modify();\n" + "};\n" + "struct D : B {\n" + " void test(); \n" + "};\n" + "void D::test() {\n" + " const int I = m_PC->GetI();\n" + " Modify();\n" + " if (m_PC->GetI() != I) {}\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); } void alwaysTrueInfer() {