| 560 | } |
| 561 | |
| 562 | static void valueFlowTypeTraits(TokenList& tokenlist, const Settings& settings) |
| 563 | { |
| 564 | std::unordered_map<std::string, std::function<ValueFlow::Value(std::vector<std::vector<const Token*>> args)>> eval; |
| 565 | eval["is_void"] = [&](std::vector<std::vector<const Token*>> args) { |
| 566 | if (args.size() != 1) |
| 567 | return ValueFlow::Value::unknown(); |
| 568 | stripCV(args[0]); |
| 569 | if (args[0].size() == 1 && args[0][0]->str() == "void") |
| 570 | return ValueFlow::Value(1); |
| 571 | if (!hasUnknownType(args[0])) |
| 572 | return ValueFlow::Value(0); |
| 573 | return ValueFlow::Value::unknown(); |
| 574 | }; |
| 575 | eval["is_lvalue_reference"] = [&](const std::vector<std::vector<const Token*>>& args) { |
| 576 | if (args.size() != 1) |
| 577 | return ValueFlow::Value::unknown(); |
| 578 | if (args[0].back()->str() == "&") |
| 579 | return ValueFlow::Value(1); |
| 580 | if (!hasUnknownType(args[0])) |
| 581 | return ValueFlow::Value(0); |
| 582 | return ValueFlow::Value::unknown(); |
| 583 | }; |
| 584 | eval["is_rvalue_reference"] = [&](const std::vector<std::vector<const Token*>>& args) { |
| 585 | if (args.size() != 1) |
| 586 | return ValueFlow::Value::unknown(); |
| 587 | if (args[0].back()->str() == "&&") |
| 588 | return ValueFlow::Value(1); |
| 589 | if (!hasUnknownType(args[0])) |
| 590 | return ValueFlow::Value(0); |
| 591 | return ValueFlow::Value::unknown(); |
| 592 | }; |
| 593 | eval["is_reference"] = [&](const std::vector<std::vector<const Token*>>& args) { |
| 594 | if (args.size() != 1) |
| 595 | return ValueFlow::Value::unknown(); |
| 596 | ValueFlow::Value isRValue = eval["is_rvalue_reference"](args); |
| 597 | if (isRValue.isUninitValue() || isRValue.intvalue == 1) |
| 598 | return isRValue; |
| 599 | return eval["is_lvalue_reference"](args); |
| 600 | }; |
| 601 | for (Token* tok = tokenlist.front(); tok; tok = tok->next()) { |
| 602 | |
| 603 | if (!Token::Match(tok, "std :: %name% <")) |
| 604 | continue; |
| 605 | Token* templateTok = tok->tokAt(3); |
| 606 | Token* updateTok = nullptr; |
| 607 | std::string traitName = tok->strAt(2); |
| 608 | if (endsWith(traitName, "_v")) { |
| 609 | traitName.pop_back(); |
| 610 | traitName.pop_back(); |
| 611 | updateTok = tok->next(); |
| 612 | } else if (Token::simpleMatch(templateTok->link(), "> { }") || |
| 613 | Token::simpleMatch(templateTok->link(), "> :: value")) { |
| 614 | updateTok = templateTok->link()->next(); |
| 615 | } |
| 616 | if (!updateTok) |
| 617 | continue; |
| 618 | if (updateTok->hasKnownIntValue()) |
| 619 | continue; |
no test coverage detected