| 383 | } |
| 384 | |
| 385 | unsigned int TemplateSimplifier::templateParameters(const Token *tok) |
| 386 | { |
| 387 | unsigned int numberOfParameters = 1; |
| 388 | |
| 389 | if (!tok) |
| 390 | return 0; |
| 391 | if (tok->str() != "<") |
| 392 | return 0; |
| 393 | if (Token::Match(tok->previous(), "%var% <")) |
| 394 | return 0; |
| 395 | tok = tok->next(); |
| 396 | if (!tok || tok->str() == ">") |
| 397 | return 0; |
| 398 | |
| 399 | unsigned int level = 0; |
| 400 | |
| 401 | while (tok) { |
| 402 | // skip template template |
| 403 | if (level == 0 && Token::simpleMatch(tok, "template <")) { |
| 404 | const Token *closing = tok->next()->findClosingBracket(); |
| 405 | if (closing) { |
| 406 | if (closing->str() == ">>") |
| 407 | return numberOfParameters; |
| 408 | tok = closing->next(); |
| 409 | if (!tok) |
| 410 | syntaxError(tok); |
| 411 | if (Token::Match(tok, ">|>>|>>=")) |
| 412 | return numberOfParameters; |
| 413 | if (tok->str() == ",") { |
| 414 | ++numberOfParameters; |
| 415 | tok = tok->next(); |
| 416 | continue; |
| 417 | } |
| 418 | } else |
| 419 | return 0; |
| 420 | } |
| 421 | |
| 422 | // skip const/volatile |
| 423 | if (Token::Match(tok, "const|volatile")) |
| 424 | tok = tok->next(); |
| 425 | |
| 426 | // skip struct/union |
| 427 | if (Token::Match(tok, "struct|union")) |
| 428 | tok = tok->next(); |
| 429 | |
| 430 | // Skip '&' |
| 431 | if (Token::Match(tok, "& ::| %name%")) |
| 432 | tok = tok->next(); |
| 433 | |
| 434 | // Skip variadic types (Ticket #5774, #6059, #6172) |
| 435 | if (Token::simpleMatch(tok, "...")) { |
| 436 | if ((tok->previous()->isName() && !Token::Match(tok->tokAt(-2), "<|,|::")) || |
| 437 | (!tok->previous()->isName() && !Token::Match(tok->previous(), ">|&|&&|*"))) |
| 438 | return 0; // syntax error |
| 439 | tok = tok->next(); |
| 440 | if (!tok) |
| 441 | return 0; |
| 442 | if (tok->str() == ">") { |
nothing calls this directly
no test coverage detected