From c418a8656326476214101f3df18cab41bfdcb683 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 21 Oct 2021 22:16:42 -0500 Subject: [PATCH 1/4] Dont stop analysis when a unrelated class variable is changed --- lib/astutils.cpp | 8 ++++---- lib/astutils.h | 2 +- lib/valueflow.cpp | 14 ++++++++++---- test/testvalueflow.cpp | 11 +++++++++++ 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index b1c8b862b88..45a72716ee8 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -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 var, 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 (var && 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(), var, depth); + return exprDependsOnThis(expr->astOperand1(), var, depth) || exprDependsOnThis(expr->astOperand2(), var, depth); } static bool hasUnknownVars(const Token* startTok) diff --git a/lib/astutils.h b/lib/astutils.h index 1756fbe11d3..80d8d33b80b 100644 --- a/lib/astutils.h +++ b/lib/astutils.h @@ -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 var = true, nonneg int depth = 0); struct ReferenceToken { const Token* token; diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index c0dae5b3330..03b8355e291 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1936,6 +1936,8 @@ static bool bifurcate(const Token* tok, const std::set& 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; @@ -1975,6 +1977,9 @@ struct ValueFlowAnalyzer : Analyzer { virtual bool dependsOnThis() const { return false; } + virtual bool isVariable() const { + return false; + } virtual bool invalid() const { return false; @@ -2328,8 +2333,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 @@ -2672,6 +2676,10 @@ struct ExpressionAnalyzer : SingleValueFlowAnalyzer { virtual bool isGlobal() const OVERRIDE { return !local; } + + virtual bool isVariable() const OVERRIDE { + return expr->varId() > 0; + } }; struct OppositeExpressionAnalyzer : ExpressionAnalyzer { @@ -6354,8 +6362,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, diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 477bf0f0328..1daacc25305 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -2464,6 +2464,17 @@ class TestValueFlow : public TestFixture { 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() From a3da556bc72cae2dbc994d5bf4ad8cfa6822af22 Mon Sep 17 00:00:00 2001 From: Paul Date: Thu, 21 Oct 2021 22:17:42 -0500 Subject: [PATCH 2/4] Format --- test/testvalueflow.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 1daacc25305..428e4bdddf9 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -2466,14 +2466,14 @@ class TestValueFlow : public TestFixture { 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"; + " 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)); } From ee5bd115066d7e37bba8b30d43aa6d7f581fabae Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 22 Oct 2021 09:46:37 -0500 Subject: [PATCH 3/4] Fix cppcheck errors --- lib/astutils.cpp | 8 ++++---- lib/astutils.h | 2 +- lib/valueflow.cpp | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/lib/astutils.cpp b/lib/astutils.cpp index 45a72716ee8..a2a15ce25b5 100644 --- a/lib/astutils.cpp +++ b/lib/astutils.cpp @@ -720,7 +720,7 @@ bool isAliased(const Variable *var) return isAliased(start, var->scope()->bodyEnd, var->declarationId()); } -bool exprDependsOnThis(const Token* expr, bool var, 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, bool var, nonneg int depth) nestedIn = nestedIn->nestedIn; } return nestedIn == expr->function()->nestedIn; - } else if (var && 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(), var, depth); - return exprDependsOnThis(expr->astOperand1(), var, depth) || exprDependsOnThis(expr->astOperand2(), var, depth); + return exprDependsOnThis(expr->astOperand1(), onVar, depth); + return exprDependsOnThis(expr->astOperand1(), onVar, depth) || exprDependsOnThis(expr->astOperand2(), onVar, depth); } static bool hasUnknownVars(const Token* startTok) diff --git a/lib/astutils.h b/lib/astutils.h index 80d8d33b80b..57d2d3cb158 100644 --- a/lib/astutils.h +++ b/lib/astutils.h @@ -144,7 +144,7 @@ bool extractForLoopValues(const Token *forToken, bool precedes(const Token * tok1, const Token * tok2); -bool exprDependsOnThis(const Token* expr, bool var = true, nonneg int depth = 0); +bool exprDependsOnThis(const Token* expr, bool OnVar = true, nonneg int depth = 0); struct ReferenceToken { const Token* token; diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 03b8355e291..8caccde4ce6 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -5871,7 +5871,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) From 1789e63963be3ee1d225bf9cb8b33532ebdc1008 Mon Sep 17 00:00:00 2001 From: Paul Date: Fri, 22 Oct 2021 21:48:31 -0500 Subject: [PATCH 4/4] Fix varname --- lib/astutils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/astutils.h b/lib/astutils.h index 57d2d3cb158..483708b473f 100644 --- a/lib/astutils.h +++ b/lib/astutils.h @@ -144,7 +144,7 @@ bool extractForLoopValues(const Token *forToken, bool precedes(const Token * tok1, const Token * tok2); -bool exprDependsOnThis(const Token* expr, bool OnVar = true, nonneg int depth = 0); +bool exprDependsOnThis(const Token* expr, bool onVar = true, nonneg int depth = 0); struct ReferenceToken { const Token* token;