From 75f911177506659ec773954b3409d5650be1222b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 11 Jan 2014 15:36:09 +0100 Subject: [PATCH] value flow: bailout when variable is used in assignment to itself --- lib/valueflow.cpp | 25 +++++++++++++++++++++++++ test/testvalueflow.cpp | 8 ++++++++ 2 files changed, 33 insertions(+) diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index f5eac13a9..675258db6 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -82,6 +82,24 @@ static const Token * skipValueInConditionalExpression(const Token *tok) return tok; } +static bool bailoutSelfAssignment(const Token * const tok) +{ + const Token *parent = tok; + while (parent) { + const Token *op = parent; + parent = parent->astParent(); + + // Assignment where lhs variable exists in rhs => return true + if (parent != NULL && + parent->astOperand2() == op && + parent->astOperand1() != NULL && + parent->str() == "=" && + parent->astOperand1()->str() == tok->str()) + return true; + } + return false; +} + static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLogger, const Settings *settings) { for (Token *tok = tokenlist->front(); tok; tok = tok->next()) { @@ -152,6 +170,13 @@ static void valueFlowBeforeCondition(TokenList *tokenlist, ErrorLogger *errorLog break; } + // bailout: variable is used in rhs in assignment to itself + if (bailoutSelfAssignment(tok2)) { + if (settings->debugwarnings) + bailout(tokenlist, errorLogger, tok2, "variable " + tok2->str() + " is used in rhs in assignment to itself"); + break; + } + // assigned by subfunction? if (bailoutFunctionPar(tok2)) { if (settings->debugwarnings) diff --git a/test/testvalueflow.cpp b/test/testvalueflow.cpp index e12c712ee..78324fb1f 100644 --- a/test/testvalueflow.cpp +++ b/test/testvalueflow.cpp @@ -104,6 +104,14 @@ private: "}"; ASSERT_EQUALS(true, testValueOfX(code, 3U, 123)); + // assignment + code = "void f(int x) {\n" + " x = 2 + x;\n" + " if (x == 65);\n" + "}"; + ASSERT_EQUALS(false, testValueOfX(code, 2U, 65)); + + // guarding by && code = "void f(int x) {\n" " if (!x || \n" // <- x can be 0