Fixed #7968 (valueFlowBeforeCondition: better handling of compound assignments)

This commit is contained in:
Daniel Marjamäki 2017-04-25 20:45:02 +02:00
parent 537045b176
commit 89532cf8b9
2 changed files with 52 additions and 0 deletions

View File

@ -940,6 +940,29 @@ static void valueFlowReverse(TokenList *tokenlist,
break; 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 // bailout: variable is used in rhs in assignment to itself
if (bailoutSelfAssignment(tok2)) { if (bailoutSelfAssignment(tok2)) {
if (settings->debugwarnings) if (settings->debugwarnings)

View File

@ -628,6 +628,35 @@ private:
"}"; "}";
ASSERT_EQUALS(true, testValueOfX(code, 2U, 3)); 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: assignment
bailout("void f(int x) {\n" bailout("void f(int x) {\n"
" x = y;\n" " x = y;\n"