| 424 | } |
| 425 | |
| 426 | static void fillProgramMemoryFromAssignments(ProgramMemory& pm, const Token* tok, const Settings& settings, const ProgramMemory& state, const ProgramMemory::Map& vars) |
| 427 | { |
| 428 | int indentlevel = 0; |
| 429 | for (const Token *tok2 = tok; tok2; tok2 = tok2->previous()) { |
| 430 | if ((Token::simpleMatch(tok2, "=") || Token::Match(tok2->previous(), "%var% (|{")) && tok2->astOperand1() && |
| 431 | tok2->astOperand2()) { |
| 432 | bool setvar = false; |
| 433 | const Token* vartok = tok2->astOperand1(); |
| 434 | for (const auto& p:vars) { |
| 435 | if (p.first.getExpressionId() != vartok->exprId()) |
| 436 | continue; |
| 437 | if (vartok == tok) |
| 438 | continue; |
| 439 | pm.setValue(vartok, p.second); |
| 440 | setvar = true; |
| 441 | } |
| 442 | if (!setvar) { |
| 443 | if (!pm.hasValue(vartok->exprId())) { |
| 444 | const Token* valuetok = tok2->astOperand2(); |
| 445 | ProgramMemory local = state; |
| 446 | pm.setValue(vartok, execute(valuetok, local, settings)); |
| 447 | } |
| 448 | } |
| 449 | } else if (Token::simpleMatch(tok2, ")") && tok2->link() && |
| 450 | Token::Match(tok2->link()->previous(), "assert|ASSERT ( !!)")) { |
| 451 | const Token* cond = tok2->link()->astOperand2(); |
| 452 | if (!conditionIsTrue(cond, state, settings)) { |
| 453 | // TODO: change to assert when we can propagate the assert, for now just bail |
| 454 | if (conditionIsFalse(cond, state, settings)) |
| 455 | return; |
| 456 | programMemoryParseCondition(pm, cond, nullptr, settings, true); |
| 457 | } |
| 458 | tok2 = tok2->link()->previous(); |
| 459 | } else if (tok2->exprId() > 0 && Token::Match(tok2, ".|(|[|*|%var%") && !pm.hasValue(tok2->exprId()) && |
| 460 | isVariableChanged(tok2, 0, settings)) { |
| 461 | pm.setUnknown(tok2); |
| 462 | } |
| 463 | |
| 464 | if (tok2->str() == "{") { |
| 465 | if (indentlevel <= 0) { |
| 466 | const Token* cond = getCondTokFromEnd(tok2->link()); |
| 467 | // Keep progressing with anonymous/do scopes and always true branches |
| 468 | if (!Token::Match(tok2->previous(), "do|; {") && !conditionIsTrue(cond, state, settings) && |
| 469 | (cond || !isBasicForLoop(tok2))) |
| 470 | break; |
| 471 | } else |
| 472 | --indentlevel; |
| 473 | if (Token::simpleMatch(tok2->previous(), "else {")) |
| 474 | tok2 = tok2->linkAt(-2)->previous(); |
| 475 | } |
| 476 | if (tok2->str() == "}" && !Token::Match(tok2->link()->previous(), "%var% {")) { |
| 477 | const Token *cond = getCondTokFromEnd(tok2); |
| 478 | const bool inElse = Token::simpleMatch(tok2->link()->previous(), "else {"); |
| 479 | if (cond) { |
| 480 | if (conditionIsFalse(cond, state, settings)) { |
| 481 | if (inElse) { |
| 482 | ++indentlevel; |
| 483 | continue; |
no test coverage detected