| 514 | //--------------------------------------------------------------------------- |
| 515 | |
| 516 | static bool findFormat(nonneg int arg, const Token *firstArg, |
| 517 | const Token *&formatStringTok, const Token *&formatArgTok) |
| 518 | { |
| 519 | const Token* argTok = firstArg; |
| 520 | |
| 521 | for (int i = 0; i < arg && argTok; ++i) |
| 522 | argTok = argTok->nextArgument(); |
| 523 | |
| 524 | if (Token::Match(argTok, "%str% [,)]")) { |
| 525 | formatArgTok = argTok->nextArgument(); |
| 526 | formatStringTok = argTok; |
| 527 | return true; |
| 528 | } |
| 529 | if (Token::Match(argTok, "%var% [,)]") && |
| 530 | argTok->variable() && |
| 531 | Token::Match(argTok->variable()->typeStartToken(), "char|wchar_t") && |
| 532 | (argTok->variable()->isPointer() || |
| 533 | (argTok->variable()->dimensions().size() == 1 && |
| 534 | argTok->variable()->dimensionKnown(0) && |
| 535 | argTok->variable()->dimension(0) != 0))) { |
| 536 | formatArgTok = argTok->nextArgument(); |
| 537 | if (!argTok->values().empty()) { |
| 538 | const auto value = std::find_if( |
| 539 | argTok->values().cbegin(), argTok->values().cend(), std::mem_fn(&ValueFlow::Value::isTokValue)); |
| 540 | if (value != argTok->values().cend() && value->isTokValue() && value->tokvalue && |
| 541 | value->tokvalue->tokType() == Token::eString) { |
| 542 | formatStringTok = value->tokvalue; |
| 543 | } |
| 544 | } |
| 545 | return true; |
| 546 | } |
| 547 | return false; |
| 548 | } |
| 549 | |
| 550 | // Utility function returning whether iToTest equals iTypename or iOptionalPrefix+iTypename |
| 551 | static inline bool typesMatch(const std::string& iToTest, const std::string& iTypename, const std::string& iOptionalPrefix = "std::") |
no test coverage detected