Dont stop analysis when an unrelated class variable is changed (#3518)

This commit is contained in:
Paul Fultz II 2021-10-23 07:47:10 -05:00 committed by GitHub
parent ca83222bae
commit 48fc70b810
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 27 additions and 10 deletions

View File

@ -720,7 +720,7 @@ bool isAliased(const Variable *var)
return isAliased(start, var->scope()->bodyEnd, var->declarationId());
}
bool exprDependsOnThis(const Token* expr, nonneg int depth)
bool exprDependsOnThis(const Token* expr, bool onVar, nonneg int depth)
{
if (!expr)
return false;
@ -743,13 +743,13 @@ bool exprDependsOnThis(const Token* expr, nonneg int depth)
nestedIn = nestedIn->nestedIn;
}
return nestedIn == expr->function()->nestedIn;
} else if (Token::Match(expr, "%var%") && expr->variable()) {
} else if (onVar && Token::Match(expr, "%var%") && expr->variable()) {
const Variable* var = expr->variable();
return (var->isPrivate() || var->isPublic() || var->isProtected());
}
if (Token::simpleMatch(expr, "."))
return exprDependsOnThis(expr->astOperand1(), depth);
return exprDependsOnThis(expr->astOperand1(), depth) || exprDependsOnThis(expr->astOperand2(), depth);
return exprDependsOnThis(expr->astOperand1(), onVar, depth);
return exprDependsOnThis(expr->astOperand1(), onVar, depth) || exprDependsOnThis(expr->astOperand2(), onVar, depth);
}
static bool hasUnknownVars(const Token* startTok)

View File

@ -144,7 +144,7 @@ bool extractForLoopValues(const Token *forToken,
bool precedes(const Token * tok1, const Token * tok2);
bool exprDependsOnThis(const Token* expr, nonneg int depth = 0);
bool exprDependsOnThis(const Token* expr, bool onVar = true, nonneg int depth = 0);
struct ReferenceToken {
const Token* token;

View File

@ -1938,6 +1938,8 @@ static bool bifurcate(const Token* tok, const std::set<nonneg int>& varids, cons
return false;
}
static bool isContainerSizeChanged(const Token* tok, const Settings* settings = nullptr, int depth = 20);
struct ValueFlowAnalyzer : Analyzer {
const TokenList* tokenlist;
ProgramMemoryState pms;
@ -1977,6 +1979,9 @@ struct ValueFlowAnalyzer : Analyzer {
virtual bool dependsOnThis() const {
return false;
}
virtual bool isVariable() const {
return false;
}
virtual bool invalid() const {
return false;
@ -2330,8 +2335,7 @@ struct ValueFlowAnalyzer : Analyzer {
if (a != Action::None)
return a;
}
if (dependsOnThis() && exprDependsOnThis(tok))
if (dependsOnThis() && exprDependsOnThis(tok, !isVariable()))
return isThisModified(tok);
// bailout: global non-const variables
@ -2674,6 +2678,10 @@ struct ExpressionAnalyzer : SingleValueFlowAnalyzer {
virtual bool isGlobal() const OVERRIDE {
return !local;
}
virtual bool isVariable() const OVERRIDE {
return expr->varId() > 0;
}
};
struct OppositeExpressionAnalyzer : ExpressionAnalyzer {
@ -5910,7 +5918,7 @@ struct MultiValueFlowAnalyzer : ValueFlowAnalyzer {
// ProgramMemory pm = pms.get(endBlock->link()->next(), getProgramState());
for (const auto& p:pm.values) {
nonneg int varid = p.first;
if (!symboldatabase->isVarId(varid))
if (symboldatabase && !symboldatabase->isVarId(varid))
continue;
ValueFlow::Value value = p.second;
if (vars.count(varid) != 0)
@ -6437,8 +6445,6 @@ static void valueFlowUninit(TokenList* tokenlist, SymbolDatabase* /*symbolDataba
}
}
static bool isContainerSizeChanged(const Token* tok, const Settings* settings = nullptr, int depth = 20);
static bool isContainerSizeChanged(nonneg int varId,
const Token* start,
const Token* end,

View File

@ -2464,6 +2464,17 @@ private:
ASSERT_EQUALS(false, testValueOfXKnown(code, 3U, 0));
ASSERT_EQUALS(false, testValueOfXImpossible(code, 3U, 0));
ASSERT_EQUALS(false, testValueOfXImpossible(code, 3U, 1));
code = "struct A {\n"
" int i, j;\n"
" int foo() {\n"
" i = 1;\n"
" j = 2;\n"
" int x = i;\n"
" return x;\n"
" }\n"
"};\n";
ASSERT_EQUALS(true, testValueOfXKnown(code, 7U, 1));
}
void valueFlowAfterSwap()