| 201 | |
| 202 | template<class T, class F, REQUIRES("T must be a Token class", std::is_convertible<T*, const Token*> )> |
| 203 | Progress traverseConditional(T* tok, F f, bool traverseUnknown) { |
| 204 | Analyzer::Action action = analyzer->analyze(tok, Analyzer::Direction::Forward); |
| 205 | if (action.isNone() && Token::Match(tok, "?|&&|%oror%") && tok->astOperand1() && tok->astOperand2()) { |
| 206 | const T* condTok = tok->astOperand1(); |
| 207 | T* childTok = tok->astOperand2(); |
| 208 | bool checkThen, checkElse; |
| 209 | std::tie(checkThen, checkElse) = evalCond(condTok); |
| 210 | if (!checkThen && !checkElse) { |
| 211 | if (!traverseUnknown && stopOnCondition(condTok) && tok->str() != "?" && stopUpdates()) { |
| 212 | return Progress::Continue; |
| 213 | } |
| 214 | checkThen = true; |
| 215 | checkElse = true; |
| 216 | } |
| 217 | if (childTok->str() == ":") { |
| 218 | if (checkThen && traverseRecursive(childTok->astOperand1(), f, traverseUnknown) == Progress::Break) |
| 219 | return Break(); |
| 220 | if (checkElse && traverseRecursive(childTok->astOperand2(), f, traverseUnknown) == Progress::Break) |
| 221 | return Break(); |
| 222 | } else { |
| 223 | if (!checkThen && tok->str() == "&&") |
| 224 | return Progress::Continue; |
| 225 | if (!checkElse && tok->str() == "||") |
| 226 | return Progress::Continue; |
| 227 | if (traverseRecursive(childTok, f, traverseUnknown) == Progress::Break) |
| 228 | return Break(); |
| 229 | } |
| 230 | } else { |
| 231 | return f(tok, action); |
| 232 | } |
| 233 | return Progress::Continue; |
| 234 | } |
| 235 | |
| 236 | Progress update(Token* tok) { |
| 237 | Analyzer::Action action = analyzer->analyze(tok, Analyzer::Direction::Forward); |
no test coverage detected