Fix 10555: FP knownConditionTrueFalse with non-const function in base class (#3559)
This commit is contained in:
parent
49d3e07b59
commit
13f5b560ce
|
@ -751,18 +751,20 @@ bool exprDependsOnThis(const Token* expr, bool onVar, nonneg int depth)
|
||||||
return true;
|
return true;
|
||||||
++depth;
|
++depth;
|
||||||
// calling nonstatic method?
|
// 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?
|
// is it a method of this?
|
||||||
const Scope* fScope = expr->scope();
|
const Scope* fScope = expr->scope();
|
||||||
while (!fScope->functionOf && fScope->nestedIn)
|
while (!fScope->functionOf && fScope->nestedIn)
|
||||||
fScope = fScope->nestedIn;
|
fScope = fScope->nestedIn;
|
||||||
const Scope* nestedIn = fScope->functionOf;
|
|
||||||
if (nestedIn && nestedIn->function)
|
const Scope* classScope = fScope->functionOf;
|
||||||
nestedIn = nestedIn->function->token->scope();
|
if (classScope && classScope->function)
|
||||||
while (nestedIn && nestedIn != expr->function()->nestedIn) {
|
classScope = classScope->function->token->scope();
|
||||||
nestedIn = nestedIn->nestedIn;
|
|
||||||
}
|
if (classScope && classScope->isClassOrStruct())
|
||||||
return nestedIn == expr->function()->nestedIn;
|
return contains(classScope->findAssociatedScopes(), expr->function()->nestedIn);
|
||||||
|
return false;
|
||||||
} else if (onVar && Token::Match(expr, "%var%") && expr->variable()) {
|
} else if (onVar && Token::Match(expr, "%var%") && expr->variable()) {
|
||||||
const Variable* var = expr->variable();
|
const Variable* var = expr->variable();
|
||||||
return (var->isPrivate() || var->isPublic() || var->isProtected());
|
return (var->isPrivate() || var->isPublic() || var->isProtected());
|
||||||
|
|
|
@ -4892,6 +4892,24 @@ const Scope *Scope::findRecordInBase(const std::string & name) const
|
||||||
return nullptr;
|
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)
|
static void checkVariableCallMatch(const Variable* callarg, const Variable* funcarg, size_t& same, size_t& fallback1, size_t& fallback2)
|
||||||
|
|
|
@ -1192,6 +1192,8 @@ public:
|
||||||
|
|
||||||
const Scope *findRecordInBase(const std::string &name) const;
|
const Scope *findRecordInBase(const std::string &name) const;
|
||||||
|
|
||||||
|
std::vector<const Scope*> findAssociatedScopes() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* @brief helper function for getVariableList()
|
* @brief helper function for getVariableList()
|
||||||
|
|
|
@ -3894,6 +3894,25 @@ private:
|
||||||
" return delta;\n"
|
" return delta;\n"
|
||||||
"}\n");
|
"}\n");
|
||||||
ASSERT_EQUALS("", errout.str());
|
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() {
|
void alwaysTrueInfer() {
|
||||||
|
|
Loading…
Reference in New Issue