Fix false positives with condition with || and &&

The value of something in the middle of a condition with mixed || and &&
gives no information on which branch will be taken.
For instance with:
```
int f(int a, int b, bool x) {\n"
  if (a == 1 && (!(b == 2 && x))) {
  } else {
    if (x) {
    }
  }

  return 0;
}
```
We can enter the if part whether x is true or false, and similarly,
enter the else part whether x is true or false. Same thing with the
value of b.

This fixes the following false positive with above code:
```
:4:13: style: Condition 'x' is always true [knownConditionTrueFalse]
        if (x) {
            ^
:2:33: note: Assuming that condition 'x' is not redundant
    if (a == 6 && (!(b == 21 && x))) {
                                ^

```
This commit is contained in:
Ken-Patrick Lehrmann 2020-09-10 16:18:30 +02:00
parent 6c53cdd6f9
commit a114bf0293
2 changed files with 41 additions and 0 deletions

View File

@ -4424,6 +4424,31 @@ struct ValueFlowConditionHandler {
}
}
{
const Token *tok2 = tok;
std::string op;
bool mixedOperators = false;
while (tok2->astParent()) {
const Token *parent = tok2->astParent();
if (Token::Match(parent, "%oror%|&&")) {
if (op.empty()) {
op = parent->str() == "&&" ? "&&" : "||";
} else if (op != parent->str()) {
mixedOperators = true;
break;
}
}
if (parent->str()=="!") {
op = (op == "&&" ? "||" : "&&");
}
tok2 = parent;
}
if (mixedOperators) {
continue;
}
}
if (top && Token::Match(top->previous(), "if|while (") && !top->previous()->isExpandedMacro()) {
// does condition reassign variable?
if (tok != top->astOperand2() && Token::Match(top->astOperand2(), "%oror%|&&") &&

View File

@ -138,6 +138,8 @@ private:
TEST_CASE(valueFlowCrash);
TEST_CASE(valueFlowHang);
TEST_CASE(valueFlowCrashConstructorInitialization);
TEST_CASE(valueFlowUnknownMixedOperators);
}
static bool isNotTokValue(const ValueFlow::Value &val) {
@ -4804,6 +4806,20 @@ private:
"}";
valueOfTok(code, "path");
}
void valueFlowUnknownMixedOperators() {
const char *code= "int f(int a, int b, bool x) {\n"
" if (a == 1 && (!(b == 2 && x))) {\n"
" } else {\n"
" if (x) {\n"
" }\n"
" }\n"
"\n"
" return 0;\n"
"}" ;
ASSERT_EQUALS(false, testValueOfXKnown(code, 4U, 1));
}
};
REGISTER_TEST(TestValueFlow)