Skip to content

Commit 2a0143c

Browse files
Fix #10358 Bad ValueFlow depending on initialization (cppcheck-opensource#5052)
1 parent 59b955e commit 2a0143c

2 files changed

Lines changed: 28 additions & 9 deletions

File tree

lib/valueflow.cpp

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,6 +1336,13 @@ static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, b
13361336
}
13371337
// skip over enum
13381338
tok = tok->linkAt(1);
1339+
} else if (Token::Match(tok, "%name% [{(] [)}]") && (tok->isStandardType() ||
1340+
(tok->variable() && tok->variable()->nameToken() == tok &&
1341+
(tok->variable()->isPointer() || (tok->variable()->valueType() && tok->variable()->valueType()->isIntegral()))))) {
1342+
ValueFlow::Value value(0);
1343+
if (!tok->isTemplateArg())
1344+
value.setKnown();
1345+
setTokenValue(tok->next(), std::move(value), settings, isInitList);
13391346
}
13401347
return tok->next();
13411348
}
@@ -5770,7 +5777,7 @@ static std::list<ValueFlow::Value> truncateValues(std::list<ValueFlow::Value> va
57705777
static bool isVariableInit(const Token *tok)
57715778
{
57725779
return (tok->str() == "(" || tok->str() == "{") &&
5773-
tok->isBinaryOp() &&
5780+
(tok->isBinaryOp() || (tok->astOperand1() && tok->link() == tok->next())) &&
57745781
tok->astOperand1()->variable() &&
57755782
tok->astOperand1()->variable()->nameToken() == tok->astOperand1() &&
57765783
tok->astOperand1()->variable()->valueType() &&
@@ -5803,7 +5810,8 @@ static void valueFlowAfterAssign(TokenList *tokenlist,
58035810
std::unordered_map<nonneg int, std::unordered_set<nonneg int>> backAssigns;
58045811
for (Token* tok = const_cast<Token*>(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) {
58055812
// Assignment
5806-
if (tok->str() != "=" && !isVariableInit(tok))
5813+
bool isInit = false;
5814+
if (tok->str() != "=" && !(isInit = isVariableInit(tok)))
58075815
continue;
58085816

58095817
if (tok->astParent() && !(tok->astParent()->str() == ";" && astIsLHS(tok)))
@@ -5815,11 +5823,14 @@ static void valueFlowAfterAssign(TokenList *tokenlist,
58155823
std::vector<const Variable*> vars = getLHSVariables(tok);
58165824

58175825
// Rhs values..
5818-
if (!tok->astOperand2() || tok->astOperand2()->values().empty())
5826+
Token* rhs = tok->astOperand2();
5827+
if (!rhs && isInit)
5828+
rhs = tok;
5829+
if (!rhs || rhs->values().empty())
58195830
continue;
58205831

58215832
std::list<ValueFlow::Value> values = truncateValues(
5822-
tok->astOperand2()->values(), tok->astOperand1()->valueType(), tok->astOperand2()->valueType(), settings);
5833+
rhs->values(), tok->astOperand1()->valueType(), rhs->valueType(), settings);
58235834
// Remove known values
58245835
std::set<ValueFlow::Value::ValueType> types;
58255836
if (tok->astOperand1()->hasKnownValue()) {
@@ -5874,7 +5885,7 @@ static void valueFlowAfterAssign(TokenList *tokenlist,
58745885
continue;
58755886
const bool init = vars.size() == 1 && (vars.front()->nameToken() == tok->astOperand1() || tok->isSplittedVarDeclEq());
58765887
valueFlowForwardAssign(
5877-
tok->astOperand2(), tok->astOperand1(), vars, values, init, tokenlist, errorLogger, settings);
5888+
rhs, tok->astOperand1(), vars, values, init, tokenlist, errorLogger, settings);
58785889
// Back propagate symbolic values
58795890
if (tok->astOperand1()->exprId() > 0) {
58805891
Token* start = nextAfterAstRightmostLeaf(tok);

test/testvalueflow.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5035,16 +5035,24 @@ class TestValueFlow : public TestFixture {
50355035
" return s == 0;\n" // <- known value
50365036
"}";
50375037
value = valueOfTok(code, "==");
5038-
TODO_ASSERT_EQUALS(true, false, value.isKnown());
5039-
TODO_ASSERT_EQUALS(1, 0, value.intvalue);
5038+
ASSERT_EQUALS(true, value.isKnown());
5039+
ASSERT_EQUALS(1, value.intvalue);
50405040

50415041
code = "bool f() {\n"
50425042
" const int s = int();"
50435043
" return s == 0;\n" // <- known value
50445044
"}";
50455045
value = valueOfTok(code, "==");
5046-
TODO_ASSERT_EQUALS(true, false, value.isKnown());
5047-
TODO_ASSERT_EQUALS(1, 0, value.intvalue);
5046+
ASSERT_EQUALS(true, value.isKnown());
5047+
ASSERT_EQUALS(1, value.intvalue);
5048+
5049+
code = "bool f() {\n"
5050+
" const int s{};"
5051+
" return s == 0;\n" // <- known value
5052+
"}";
5053+
value = valueOfTok(code, "==");
5054+
ASSERT_EQUALS(true, value.isKnown());
5055+
ASSERT_EQUALS(1, value.intvalue);
50485056

50495057
// calculation with known result
50505058
code = "int f(int x) { a = x & 0; }"; // <- & is 0

0 commit comments

Comments
 (0)