Dont stop analysis when an unrelated class variable is changed (#3518)
This commit is contained in:
parent
ca83222bae
commit
48fc70b810
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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()
|
||||
|
|
Loading…
Reference in New Issue