From 89532cf8b922da365abe1b16b118125a88c1ffc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Tue, 25 Apr 2017 20:45:02 +0200 Subject: [PATCH] Fixed #7968 (valueFlowBeforeCondition: better handling of compound assignments) --- lib/valueflow.cpp | 23 +++++++++++++++++++++++ test/testvalueflow.cpp | 29 +++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 0b32323b3..bcfc161b8 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -940,6 +940,29 @@ static void valueFlowReverse(TokenList *tokenlist, break; } + // compound assignment + if (Token::Match(tok2->previous(), "[;{}] %var% %assign%") && tok2->next()->str() != "=") { + const Token * const assignToken = tok2->next(); + const Token * const rhsToken = assignToken->astOperand2(); + if (!rhsToken || !rhsToken->hasKnownIntValue()) { + if (settings->debugwarnings) + bailout(tokenlist, errorLogger, tok2, "compound assignment, rhs value is not known"); + break; + } + const MathLib::bigint rhsValue = rhsToken->values().front().intvalue; + if (assignToken->str() == "+=") + val.intvalue -= rhsValue; + else if (assignToken->str() == "-=") + val.intvalue += rhsValue; + else if (assignToken->str() == "*=") + val.intvalue /= rhsValue; + else { + if (settings->debugwarnings) + bailout(tokenlist, errorLogger, tok2, "compound assignment " + tok2->str()); + break; + } + } + // bailout: variable is used in rhs in assignment to itself if (bailoutSelfAssignment(tok2)) { if (settings->debugwarnings) diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index 3bf51af4a..00d111f94 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -628,6 +628,35 @@ private: "}"; ASSERT_EQUALS(true, testValueOfX(code, 2U, 3)); + // compound assignment += , -= , ... + code = "void f(int x) {\n" + " a = x;\n" + " x += 2;\n" + " if (x == 4);\n" + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 2U, 2)); + + code = "void f(int x) {\n" + " a = x;\n" + " x -= 2;\n" + " if (x == 4);\n" + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 2U, 6)); + + code = "void f(int x) {\n" + " a = x;\n" + " x *= 2;\n" + " if (x == 42);\n" + "}"; + ASSERT_EQUALS(true, testValueOfX(code, 2U, 21)); + + code = "void f(int x) {\n" + " a = x;\n" + " x /= 5;\n" + " if (x == 42);\n" + "}"; + ASSERT(tokenValues(code, "x ;").empty()); + // bailout: assignment bailout("void f(int x) {\n" " x = y;\n"