From 7701e4594a9d20cea5f2fe20392ff1b7c0b44cff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 24 Feb 2018 22:07:34 +0100 Subject: [PATCH] ValueFlowBeforeCondition: Fix wrong value in do-while condition when there is a break in the loop body --- lib/valueflow.cpp | 30 ++++++++++++++++++++++++++++++ test/testvalueflow.cpp | 10 ++++++++++ 2 files changed, 40 insertions(+) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 317812e92..18572f926 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1126,6 +1126,36 @@ static void valueFlowReverse(TokenList *tokenlist, continue; } + // do-while condition, break in the loop body + { + const Token *parent = tok2->astParent(); + while (parent && !Token::simpleMatch(parent->previous(), "while (")) + parent = parent->astParent(); + if (parent && Token::simpleMatch(parent->tokAt(-2), "} while (") && Token::simpleMatch(parent->linkAt(-2)->previous(), "do {")) { + bool breakBailout = false; + for (const Token *iftok = parent->linkAt(-2); iftok != parent; iftok = iftok->next()) { + if (!Token::simpleMatch(iftok, "if (")) + continue; + if (!Token::Match(iftok->linkAt(1), ") { break")) + continue; + ProgramMemory programMemory; + programMemory.setIntValue(varid, num); + if (conditionIsTrue(iftok->next()->astOperand2(), programMemory)) { + breakBailout = true; + break; + } + } + if (breakBailout) { + if (settings->debugwarnings) + bailout(tokenlist, + errorLogger, + tok2, + "no simplification of " + tok2->str() + " in do-while condition since there is a break in the loop body"); + break; + } + } + } + setTokenValue(tok2, val, settings); if (val2.condition) setTokenValue(tok2,val2, settings); diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 1825c28d9..c839b288d 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -707,6 +707,16 @@ private: " if (x == 123) {}\n" "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 123)); + + // after loop + code = "void f(struct X *x) {\n" + " do {\n" + " if (!x)\n" + " break;\n" + " } while (x->a);\n" + " if (x) {}\n" + "}\n"; + ASSERT_EQUALS(false, testValueOfX(code, 5U, 0)); } void valueFlowBeforeConditionAssignIncDec() { // assignment / increment