| 5549 | } |
| 5550 | |
| 5551 | static void valueFlowSwitchVariable(const TokenList& tokenlist, |
| 5552 | const SymbolDatabase& symboldatabase, |
| 5553 | ErrorLogger& errorLogger, |
| 5554 | const Settings& settings) |
| 5555 | { |
| 5556 | for (const Scope& scope : symboldatabase.scopeList) { |
| 5557 | if (scope.type != ScopeType::eSwitch) |
| 5558 | continue; |
| 5559 | if (!Token::Match(scope.classDef, "switch ( %var% ) {")) |
| 5560 | continue; |
| 5561 | const Token* vartok = scope.classDef->tokAt(2); |
| 5562 | const Variable* var = vartok->variable(); |
| 5563 | if (!var) |
| 5564 | continue; |
| 5565 | |
| 5566 | // bailout: global non-const variables |
| 5567 | if (!(var->isLocal() || var->isArgument()) && !var->isConst()) { |
| 5568 | if (settings.debugwarnings) |
| 5569 | bailout(tokenlist, errorLogger, vartok, "switch variable " + var->name() + " is global"); |
| 5570 | continue; |
| 5571 | } |
| 5572 | |
| 5573 | for (const Token* tok = scope.bodyStart->next(); tok != scope.bodyEnd; tok = tok->next()) { |
| 5574 | if (tok->str() == "{") { |
| 5575 | tok = tok->link(); |
| 5576 | continue; |
| 5577 | } |
| 5578 | if (Token::Match(tok, "case %num% :")) { |
| 5579 | std::list<ValueFlow::Value> values; |
| 5580 | values.emplace_back(MathLib::toBigNumber(tok->tokAt(1))); |
| 5581 | values.back().condition = tok; |
| 5582 | values.back().errorPath.emplace_back(tok, |
| 5583 | "case " + tok->strAt(1) + ": " + vartok->str() + " is " + |
| 5584 | tok->strAt(1) + " here."); |
| 5585 | bool known = false; |
| 5586 | if ((Token::simpleMatch(tok->previous(), "{") || Token::simpleMatch(tok->tokAt(-2), "break ;")) && |
| 5587 | !Token::Match(tok->tokAt(3), ";| case")) |
| 5588 | known = true; |
| 5589 | while (Token::Match(tok->tokAt(3), ";| case %num% :")) { |
| 5590 | known = false; |
| 5591 | tok = tok->tokAt(3); |
| 5592 | if (!tok->isName()) |
| 5593 | tok = tok->next(); |
| 5594 | values.emplace_back(MathLib::toBigNumber(tok->tokAt(1))); |
| 5595 | values.back().condition = tok; |
| 5596 | values.back().errorPath.emplace_back(tok, |
| 5597 | "case " + tok->strAt(1) + ": " + vartok->str() + " is " + |
| 5598 | tok->strAt(1) + " here."); |
| 5599 | } |
| 5600 | for (auto val = values.cbegin(); val != values.cend(); ++val) { |
| 5601 | valueFlowReverse(tokenlist, const_cast<Token*>(scope.classDef), vartok, *val, errorLogger, settings); |
| 5602 | } |
| 5603 | if (vartok->variable()->scope()) { |
| 5604 | if (known) |
| 5605 | values.back().setKnown(); |
| 5606 | |
| 5607 | // FIXME We must check if there is a return. See #9276 |
| 5608 | /* |
no test coverage detected