diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 4c2f335d8..f3778a28b 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2202,6 +2202,8 @@ void Tokenizer::simplifyLabelsCaseDefault() if (Token::Match(tok->next(),"[:{};]")) break; } + if (!tok) + break; if (tok->str() != "case" && tok->next() && tok->next()->str() == ":") { tok = tok->next(); if (tok->next()->str() != ";") diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 4ab39a13c..247983215 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -704,6 +704,17 @@ static bool valueFlowForward(Token * const startToken, // TODO: don't check noreturn scopes if (read && (number_of_if > 0U || Token::findmatch(tok2, "%varid%", start, varid))) { + // Set values in condition + const Token * const condend = tok2->linkAt(1); + for (Token *condtok = tok2; condtok != condend; condtok = condtok->next()) { + if (condtok->varId() == varid) { + std::list::const_iterator it; + for (it = values.begin(); it != values.end(); ++it) + setTokenValue(condtok, *it); + } + if (Token::Match(condtok, "%oror%|&&")) + break; + } if (settings->debugwarnings) bailout(tokenlist, errorLogger, tok2, "variable " + var->nameToken()->str() + " is assigned in conditional code"); return false; @@ -896,13 +907,15 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg if (Token::Match(tok,"==|!=|>=|<=")) { if (!tok->astOperand1() || !tok->astOperand2()) continue; - if (tok->astOperand1()->isName()) { - vartok = tok->astOperand1(); - numtok = tok->astOperand2(); - } else { - vartok = tok->astOperand2(); + if (tok->astOperand1()->isNumber()) { numtok = tok->astOperand1(); + vartok = tok->astOperand2(); + } else { + numtok = tok->astOperand2(); + vartok = tok->astOperand1(); } + if (vartok->str() == "=" && vartok->astOperand1() && vartok->astOperand2()) + vartok = vartok->astOperand1(); if (!vartok->isName() || !numtok->isNumber() || !MathLib::isInt(numtok->str())) continue; } else if (tok->str() == "!") { @@ -913,7 +926,7 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg } else if (tok->isName() && (Token::Match(tok->astParent(), "%oror%|&&") || - Token::Match(tok->tokAt(-2), "if|while ( %var% )"))) { + Token::Match(tok->tokAt(-2), "if|while ( %var% [)=]"))) { vartok = tok; numtok = nullptr; @@ -964,7 +977,9 @@ static void valueFlowAfterCondition(TokenList *tokenlist, ErrorLogger *errorLogg const Token *top = tok->astTop(); if (top && Token::Match(top->previous(), "if|while (") && !top->previous()->isExpandedMacro()) { // does condition reassign variable? - if (isVariableChanged(top,top->link(),varid)) { + if (tok != top->astOperand2() && + Token::Match(top->astOperand2(), "%oror%|&&") && + isVariableChanged(top,top->link(),varid)) { if (settings->debugwarnings) bailout(tokenlist, errorLogger, tok, "assignment in condition"); continue; diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index f034fa011..1c043931e 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -907,6 +907,45 @@ private: "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 3)); + code = "void f(int x) {\n" + " while (11 != (x = dostuff())) {}\n" + " a = x;\n" + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 3U, 11)); + + code = "void f(int x) {\n" + " while (11 != (x = dostuff()) && y) {}\n" + " a = x;\n" + "}"; + TODO_ASSERT_EQUALS(true, false, testValueOfX(code, 3U, 11)); + + code = "void f(int x) {\n" + " while (x = dostuff()) {}\n" + " a = x;\n" + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 3U, 0)); + + code = "void f(const Token *x) {\n" // #5866 + " x = x->next();\n" + " while (x) { x = x->next(); }\n" + " if (x->str()) {}\n" + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 4U, 0)); + + code = "void f(const Token *x) {\n" + " while (0 != (x = x->next)) {}\n" + " x->ab = 0;\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfX(code, 3U, 0)); + + code = "void f(const Token* x) {\n" + " while (0 != (x = x->next)) {}\n" + " if (x->str) {\n" // <- possible value 0 + " x = y;\n" // <- this caused some problem + " }\n" + "}\n"; + ASSERT_EQUALS(true, testValueOfX(code, 3U, 0)); + // conditional code after if/else/while code = "void f(int x) {\n" " if (x == 2) {}\n"