diff --git a/lib/astutils.cpp b/lib/astutils.cpp index b1c8b862b..a2a15ce25 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 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) diff --git a/lib/astutils.h b/lib/astutils.h index 1756fbe11..483708b47 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 onVar = true, nonneg int depth = 0); struct ReferenceToken { const Token* token; diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 45a0a27ba..485344975 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1938,6 +1938,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; @@ -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, diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 477bf0f03..428e4bddd 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -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()