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()); 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) if (!expr)
return false; return false;
@ -743,13 +743,13 @@ bool exprDependsOnThis(const Token* expr, nonneg int depth)
nestedIn = nestedIn->nestedIn; nestedIn = nestedIn->nestedIn;
} }
return nestedIn == expr->function()->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(); const Variable* var = expr->variable();
return (var->isPrivate() || var->isPublic() || var->isProtected()); return (var->isPrivate() || var->isPublic() || var->isProtected());
} }
if (Token::simpleMatch(expr, ".")) if (Token::simpleMatch(expr, "."))
return exprDependsOnThis(expr->astOperand1(), depth); return exprDependsOnThis(expr->astOperand1(), onVar, depth);
return exprDependsOnThis(expr->astOperand1(), depth) || exprDependsOnThis(expr->astOperand2(), depth); return exprDependsOnThis(expr->astOperand1(), onVar, depth) || exprDependsOnThis(expr->astOperand2(), onVar, depth);
} }
static bool hasUnknownVars(const Token* startTok) 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 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 { struct ReferenceToken {
const Token* token; const Token* token;

View File

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

View File

@ -2464,6 +2464,17 @@ private:
ASSERT_EQUALS(false, testValueOfXKnown(code, 3U, 0)); ASSERT_EQUALS(false, testValueOfXKnown(code, 3U, 0));
ASSERT_EQUALS(false, testValueOfXImpossible(code, 3U, 0)); ASSERT_EQUALS(false, testValueOfXImpossible(code, 3U, 0));
ASSERT_EQUALS(false, testValueOfXImpossible(code, 3U, 1)); 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() void valueFlowAfterSwap()