| 2396 | } |
| 2397 | |
| 2398 | std::pair<const Token*, const Token*> Token::typeDecl(const Token* tok, bool pointedToType) |
| 2399 | { |
| 2400 | if (!tok) |
| 2401 | return {}; |
| 2402 | if (tok->type()) |
| 2403 | return {tok, tok->next()}; |
| 2404 | if (tok->variable()) { |
| 2405 | const Variable *var = tok->variable(); |
| 2406 | if (!var->typeStartToken() || !var->typeEndToken()) |
| 2407 | return {}; |
| 2408 | if (pointedToType && astIsSmartPointer(var->nameToken())) { |
| 2409 | const ValueType* vt = var->valueType(); |
| 2410 | if (vt && vt->smartPointerTypeToken) |
| 2411 | return { vt->smartPointerTypeToken, vt->smartPointerTypeToken->linkAt(-1) }; |
| 2412 | } |
| 2413 | if (pointedToType && astIsIterator(var->nameToken())) { |
| 2414 | const ValueType* vt = var->valueType(); |
| 2415 | if (vt && vt->containerTypeToken) |
| 2416 | return { vt->containerTypeToken, vt->containerTypeToken->linkAt(-1) }; |
| 2417 | } |
| 2418 | std::pair<const Token*, const Token*> result; |
| 2419 | if (Token::simpleMatch(var->typeStartToken(), "auto")) { |
| 2420 | const Token * tok2 = var->declEndToken(); |
| 2421 | if (Token::Match(tok2, "; %varid% =", var->declarationId())) |
| 2422 | tok2 = tok2->tokAt(2); |
| 2423 | if (Token::simpleMatch(tok2, "=") && Token::Match(tok2->astOperand2(), "!!=") && tok != tok2->astOperand2()) { |
| 2424 | tok2 = tok2->astOperand2(); |
| 2425 | |
| 2426 | if (Token::simpleMatch(tok2, "[") && tok2->astOperand1()) { |
| 2427 | const ValueType* vt = tok2->astOperand1()->valueType(); |
| 2428 | if (vt && vt->containerTypeToken) |
| 2429 | return { vt->containerTypeToken, vt->containerTypeToken->linkAt(-1) }; |
| 2430 | } |
| 2431 | |
| 2432 | const Token* varTok = tok2; // try to find a variable |
| 2433 | if (Token::Match(varTok, ":: %name%")) |
| 2434 | varTok = varTok->next(); |
| 2435 | while (Token::Match(varTok, "%name% ::")) |
| 2436 | varTok = varTok->tokAt(2); |
| 2437 | std::pair<const Token*, const Token*> r = typeDecl(varTok); |
| 2438 | if (r.first) |
| 2439 | return r; |
| 2440 | |
| 2441 | if (pointedToType && tok2->astOperand1() && Token::simpleMatch(tok2, "new")) { |
| 2442 | if (Token::simpleMatch(tok2->astOperand1(), "(")) |
| 2443 | return { tok2->next(), tok2->astOperand1() }; |
| 2444 | const Token* declEnd = nextAfterAstRightmostLeaf(tok2->astOperand1()); |
| 2445 | if (Token::simpleMatch(declEnd, "<") && declEnd->link()) |
| 2446 | declEnd = declEnd->link()->next(); |
| 2447 | return { tok2->next(), declEnd }; |
| 2448 | } |
| 2449 | const Token *typeBeg{}, *typeEnd{}; |
| 2450 | if (tok2->str() == "::" && Token::simpleMatch(tok2->astOperand2(), "{")) { // empty initlist |
| 2451 | typeBeg = previousBeforeAstLeftmostLeaf(tok2); |
| 2452 | typeEnd = tok2->astOperand2(); |
| 2453 | } |
| 2454 | else if (tok2->str() == "{") { |
| 2455 | typeBeg = previousBeforeAstLeftmostLeaf(tok2); |
nothing calls this directly
no test coverage detected