From 2a0143c8e12c60f6c03b49f4e5a860b2844e002e Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Fri, 12 May 2023 07:19:44 +0200 Subject: [PATCH] Fix #10358 Bad ValueFlow depending on initialization (#5052) --- lib/valueflow.cpp | 21 ++++++++++++++++----- test/testvalueflow.cpp | 16 ++++++++++++---- 2 files changed, 28 insertions(+), 9 deletions(-) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 3ef0133d0..3ac36a696 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1336,6 +1336,13 @@ static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, b } // skip over enum tok = tok->linkAt(1); + } else if (Token::Match(tok, "%name% [{(] [)}]") && (tok->isStandardType() || + (tok->variable() && tok->variable()->nameToken() == tok && + (tok->variable()->isPointer() || (tok->variable()->valueType() && tok->variable()->valueType()->isIntegral()))))) { + ValueFlow::Value value(0); + if (!tok->isTemplateArg()) + value.setKnown(); + setTokenValue(tok->next(), std::move(value), settings, isInitList); } return tok->next(); } @@ -5770,7 +5777,7 @@ static std::list truncateValues(std::list va static bool isVariableInit(const Token *tok) { return (tok->str() == "(" || tok->str() == "{") && - tok->isBinaryOp() && + (tok->isBinaryOp() || (tok->astOperand1() && tok->link() == tok->next())) && tok->astOperand1()->variable() && tok->astOperand1()->variable()->nameToken() == tok->astOperand1() && tok->astOperand1()->variable()->valueType() && @@ -5803,7 +5810,8 @@ static void valueFlowAfterAssign(TokenList *tokenlist, std::unordered_map> backAssigns; for (Token* tok = const_cast(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) { // Assignment - if (tok->str() != "=" && !isVariableInit(tok)) + bool isInit = false; + if (tok->str() != "=" && !(isInit = isVariableInit(tok))) continue; if (tok->astParent() && !(tok->astParent()->str() == ";" && astIsLHS(tok))) @@ -5815,11 +5823,14 @@ static void valueFlowAfterAssign(TokenList *tokenlist, std::vector vars = getLHSVariables(tok); // Rhs values.. - if (!tok->astOperand2() || tok->astOperand2()->values().empty()) + Token* rhs = tok->astOperand2(); + if (!rhs && isInit) + rhs = tok; + if (!rhs || rhs->values().empty()) continue; std::list values = truncateValues( - tok->astOperand2()->values(), tok->astOperand1()->valueType(), tok->astOperand2()->valueType(), settings); + rhs->values(), tok->astOperand1()->valueType(), rhs->valueType(), settings); // Remove known values std::set types; if (tok->astOperand1()->hasKnownValue()) { @@ -5874,7 +5885,7 @@ static void valueFlowAfterAssign(TokenList *tokenlist, continue; const bool init = vars.size() == 1 && (vars.front()->nameToken() == tok->astOperand1() || tok->isSplittedVarDeclEq()); valueFlowForwardAssign( - tok->astOperand2(), tok->astOperand1(), vars, values, init, tokenlist, errorLogger, settings); + rhs, tok->astOperand1(), vars, values, init, tokenlist, errorLogger, settings); // Back propagate symbolic values if (tok->astOperand1()->exprId() > 0) { Token* start = nextAfterAstRightmostLeaf(tok); diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 02d72a0c4..350716a79 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -5035,16 +5035,24 @@ private: " return s == 0;\n" // <- known value "}"; value = valueOfTok(code, "=="); - TODO_ASSERT_EQUALS(true, false, value.isKnown()); - TODO_ASSERT_EQUALS(1, 0, value.intvalue); + ASSERT_EQUALS(true, value.isKnown()); + ASSERT_EQUALS(1, value.intvalue); code = "bool f() {\n" " const int s = int();" " return s == 0;\n" // <- known value "}"; value = valueOfTok(code, "=="); - TODO_ASSERT_EQUALS(true, false, value.isKnown()); - TODO_ASSERT_EQUALS(1, 0, value.intvalue); + ASSERT_EQUALS(true, value.isKnown()); + ASSERT_EQUALS(1, value.intvalue); + + code = "bool f() {\n" + " const int s{};" + " return s == 0;\n" // <- known value + "}"; + value = valueOfTok(code, "=="); + ASSERT_EQUALS(true, value.isKnown()); + ASSERT_EQUALS(1, value.intvalue); // calculation with known result code = "int f(int x) { a = x & 0; }"; // <- & is 0