| 466 | } |
| 467 | |
| 468 | static std::vector<const Token*> evaluateType(const Token* start, const Token* end) |
| 469 | { |
| 470 | if (!start) |
| 471 | return {}; |
| 472 | if (!end) |
| 473 | return {}; |
| 474 | std::vector<const Token*> result; |
| 475 | for (const Token* tok = start; tok != end; tok = tok->next()) { |
| 476 | if (!Token::Match(tok, "%name%|::|<|(|*|&|&&")) |
| 477 | return {}; |
| 478 | if (Token::simpleMatch(tok, "decltype (")) { |
| 479 | if (Token::Match(tok->next(), "( %name% )")) { |
| 480 | const Token* vartok = tok->tokAt(2); |
| 481 | if (vartok->function() && !vartok->variable()) { |
| 482 | result.push_back(vartok); |
| 483 | } else { |
| 484 | auto t = Token::typeDecl(vartok); |
| 485 | if (!t.first || !t.second) |
| 486 | return {}; |
| 487 | auto inner = evaluateType(t.first, t.second); |
| 488 | if (inner.empty()) |
| 489 | return {}; |
| 490 | result.insert(result.end(), inner.begin(), inner.end()); |
| 491 | } |
| 492 | } else if (Token::Match(tok->next(), "( %name% (|{") && Token::Match(tok->linkAt(3), "}|) )")) { |
| 493 | const Token* ftok = tok->tokAt(3); |
| 494 | auto t = Token::typeDecl(ftok); |
| 495 | if (!t.first || !t.second) |
| 496 | return {}; |
| 497 | auto inner = evaluateType(t.first, t.second); |
| 498 | if (inner.empty()) |
| 499 | return {}; |
| 500 | result.insert(result.end(), inner.begin(), inner.end()); |
| 501 | } else { |
| 502 | // We can't evaluate the decltype so bail |
| 503 | return {}; |
| 504 | } |
| 505 | tok = tok->linkAt(1); |
| 506 | |
| 507 | } else { |
| 508 | if (tok->link()) { |
| 509 | auto inner = evaluateType(tok->next(), tok->link()); |
| 510 | if (inner.empty()) |
| 511 | return {}; |
| 512 | result.push_back(tok); |
| 513 | result.insert(result.end(), inner.begin(), inner.end()); |
| 514 | tok = tok->link(); |
| 515 | } |
| 516 | result.push_back(tok); |
| 517 | } |
| 518 | } |
| 519 | return result; |
| 520 | } |
| 521 | |
| 522 | static bool hasUnknownType(const std::vector<const Token*>& toks) |
| 523 | { |