| 4471 | } |
| 4472 | |
| 4473 | void beforeCondition(TokenList& tokenlist, |
| 4474 | const SymbolDatabase& symboldatabase, |
| 4475 | ErrorLogger& errorLogger, |
| 4476 | const Settings& settings, |
| 4477 | const std::set<const Scope*>& skippedFunctions) const { |
| 4478 | traverseCondition(symboldatabase, settings, skippedFunctions, [&](const Condition& cond, Token* tok, const Scope*) { |
| 4479 | if (cond.vartok->exprId() == 0) |
| 4480 | return; |
| 4481 | |
| 4482 | // If condition is known then don't propagate value |
| 4483 | if (tok->hasKnownIntValue()) |
| 4484 | return; |
| 4485 | |
| 4486 | Token* top = tok->astTop(); |
| 4487 | |
| 4488 | if (Token::Match(top, "%assign%")) |
| 4489 | return; |
| 4490 | if (Token::Match(cond.vartok->astParent(), "%assign%|++|--")) |
| 4491 | return; |
| 4492 | |
| 4493 | if (Token::simpleMatch(tok->astParent(), "?") && tok->astParent()->isExpandedMacro()) { |
| 4494 | if (settings.debugwarnings) |
| 4495 | bailout(tokenlist, |
| 4496 | errorLogger, |
| 4497 | tok, |
| 4498 | "variable '" + cond.vartok->expressionString() + "', condition is defined in macro"); |
| 4499 | return; |
| 4500 | } |
| 4501 | |
| 4502 | // if,macro => bailout |
| 4503 | if (Token::simpleMatch(top->previous(), "if (") && top->previous()->isExpandedMacro()) { |
| 4504 | if (settings.debugwarnings) |
| 4505 | bailout(tokenlist, |
| 4506 | errorLogger, |
| 4507 | tok, |
| 4508 | "variable '" + cond.vartok->expressionString() + "', condition is defined in macro"); |
| 4509 | return; |
| 4510 | } |
| 4511 | |
| 4512 | if (cond.true_values.empty() && cond.false_values.empty()) |
| 4513 | return; |
| 4514 | |
| 4515 | std::list<ValueFlow::Value> values = cond.true_values; |
| 4516 | if (cond.true_values != cond.false_values) |
| 4517 | values.insert(values.end(), cond.false_values.cbegin(), cond.false_values.cend()); |
| 4518 | |
| 4519 | // extra logic for unsigned variables 'i>=1' => possible value can also be 0 |
| 4520 | if (Token::Match(tok, "<|>|<=|>=")) { |
| 4521 | if (cond.vartok->valueType() && cond.vartok->valueType()->sign != ValueType::Sign::UNSIGNED) |
| 4522 | return; |
| 4523 | |
| 4524 | values.remove_if([](const ValueFlow::Value& v) { |
| 4525 | if (v.isIntValue()) |
| 4526 | return v.intvalue != 0; |
| 4527 | return false; |
| 4528 | }); |
| 4529 | } |
| 4530 | if (values.empty()) |
no test coverage detected