Fix 10555: FP knownConditionTrueFalse with non-const function in base class (#3559)

This commit is contained in:
Paul Fultz II 2021-11-12 13:05:43 -06:00 committed by GitHub
parent 49d3e07b59
commit 13f5b560ce
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 49 additions and 8 deletions

View File

@ -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());

18
lib/symboldatabase.cpp Normal file → Executable file
View File

@ -4892,6 +4892,24 @@ const Scope *Scope::findRecordInBase(const std::string & name) const
return nullptr;
}
std::vector<const Scope*> Scope::findAssociatedScopes() const
{
std::vector<const Scope*> result = {this};
if (isClassOrStruct() && definedType && !definedType->derivedFrom.empty()) {
const std::vector<Type::BaseInfo>& 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<const Scope*> 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)

View File

@ -1192,6 +1192,8 @@ public:
const Scope *findRecordInBase(const std::string &name) const;
std::vector<const Scope*> findAssociatedScopes() const;
private:
/**
* @brief helper function for getVariableList()

19
test/testcondition.cpp Normal file → Executable file
View File

@ -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() {