| 82 | } |
| 83 | |
| 84 | PathAnalysis::Progress PathAnalysis::forwardRange(const Token* startToken, const Token* endToken, Info info, const std::function<PathAnalysis::Progress(const Info&)>& f) const |
| 85 | { |
| 86 | for (const Token *tok = startToken; precedes(tok, endToken); tok = tok->next()) { |
| 87 | if (Token::Match(tok, "asm|goto|break|continue")) |
| 88 | return Progress::Break; |
| 89 | if (Token::Match(tok, "return|throw")) { |
| 90 | forwardRecursive(tok, std::move(info), f); |
| 91 | return Progress::Break; |
| 92 | // Evaluate RHS of assignment before LHS |
| 93 | } |
| 94 | if (const Token* assignTok = assignExpr(tok)) { |
| 95 | if (forwardRecursive(assignTok->astOperand2(), info, f) == Progress::Break) |
| 96 | return Progress::Break; |
| 97 | if (forwardRecursive(assignTok->astOperand1(), info, f) == Progress::Break) |
| 98 | return Progress::Break; |
| 99 | tok = nextAfterAstRightmostLeaf(assignTok); |
| 100 | if (!tok) |
| 101 | return Progress::Break; |
| 102 | } else if (Token::simpleMatch(tok, "}") && Token::simpleMatch(tok->link()->previous(), ") {") && Token::Match(tok->link()->linkAt(-1)->previous(), "if|while|for (")) { |
| 103 | const Token * blockStart = tok->link()->linkAt(-1)->previous(); |
| 104 | const Token * condTok = getCondTok(blockStart); |
| 105 | if (!condTok) |
| 106 | continue; |
| 107 | info.errorPath.emplace_back(condTok, "Assuming condition is true."); |
| 108 | // Traverse a loop a second time |
| 109 | if (Token::Match(blockStart, "for|while (")) { |
| 110 | const Token* endCond = blockStart->linkAt(1); |
| 111 | bool traverseLoop = true; |
| 112 | // Only traverse simple for loops |
| 113 | if (Token::simpleMatch(blockStart, "for") && !Token::Match(endCond->tokAt(-3), "; ++|--|%var% %var%|++|-- ) {")) |
| 114 | traverseLoop = false; |
| 115 | // Traverse loop a second time |
| 116 | if (traverseLoop) { |
| 117 | // Traverse condition |
| 118 | if (forwardRecursive(condTok, info, f) == Progress::Break) |
| 119 | return Progress::Break; |
| 120 | // TODO: Should we traverse the body: forwardRange(tok->link(), tok, info, f)? |
| 121 | } |
| 122 | } |
| 123 | if (Token::simpleMatch(tok, "} else {")) { |
| 124 | tok = tok->linkAt(2); |
| 125 | } |
| 126 | } else if (Token::Match(tok, "if|while|for (") && Token::simpleMatch(tok->linkAt(1), ") {")) { |
| 127 | const Token * endCond = tok->linkAt(1); |
| 128 | const Token * endBlock = endCond->linkAt(1); |
| 129 | const Token * condTok = getCondTok(tok); |
| 130 | if (!condTok) |
| 131 | continue; |
| 132 | // Traverse condition |
| 133 | if (forwardRange(tok->next(), tok->linkAt(1), info, f) == Progress::Break) |
| 134 | return Progress::Break; |
| 135 | Info i = info; |
| 136 | i.known = false; |
| 137 | i.errorPath.emplace_back(condTok, "Assuming condition is true."); |
| 138 | |
| 139 | // Check if condition is true or false |
| 140 | bool checkThen = false; |
| 141 | bool checkElse = false; |
nothing calls this directly
no test coverage detected