MCPcopy Create free account
hub / github.com/cppcheck-opensource/cppcheck / valueFlowLifetimeFunction

Function valueFlowLifetimeFunction

lib/valueflow.cpp:2452–2600  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

2450}
2451
2452static void valueFlowLifetimeFunction(Token *tok, const TokenList &tokenlist, ErrorLogger &errorLogger, const Settings &settings)
2453{
2454 if (!Token::Match(tok, "%name% ("))
2455 return;
2456 Token* memtok = nullptr;
2457 if (Token::Match(tok->astParent(), ". %name% (") && astIsRHS(tok))
2458 memtok = tok->astParent()->astOperand1();
2459 const int returnContainer = settings.library.returnValueContainer(tok);
2460 if (returnContainer >= 0) {
2461 std::vector<const Token *> args = getArguments(tok);
2462 for (int argnr = 1; argnr <= args.size(); ++argnr) {
2463 const Library::ArgumentChecks::IteratorInfo *i = settings.library.getArgIteratorInfo(tok, argnr);
2464 if (!i)
2465 continue;
2466 if (i->container != returnContainer)
2467 continue;
2468 const Token * const argTok = args[argnr - 1];
2469 bool forward = false;
2470 for (ValueFlow::Value val : argTok->values()) {
2471 if (!val.isLifetimeValue())
2472 continue;
2473 val.errorPath.emplace_back(argTok, "Passed to '" + tok->str() + "'.");
2474 setTokenValue(tok->next(), std::move(val), settings);
2475 forward = true;
2476 }
2477 // Check if lifetime is available to avoid adding the lifetime twice
2478 if (forward) {
2479 valueFlowForwardLifetime(tok, tokenlist, errorLogger, settings);
2480 break;
2481 }
2482 }
2483 } else if (Token::Match(tok->tokAt(-2), "std :: ref|cref|tie|front_inserter|back_inserter")) {
2484 for (const Token *argtok : getArguments(tok)) {
2485 LifetimeStore{argtok, "Passed to '" + tok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}.byRef(
2486 tok->next(), tokenlist, errorLogger, settings);
2487 }
2488 } else if (Token::Match(tok->tokAt(-2), "std :: make_tuple|tuple_cat|make_pair|make_reverse_iterator|next|prev|move|bind")) {
2489 for (const Token *argtok : getArguments(tok)) {
2490 LifetimeStore{argtok, "Passed to '" + tok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}.byVal(
2491 tok->next(), tokenlist, errorLogger, settings);
2492 }
2493 } else if (memtok && Token::Match(tok->astParent(), ". push_back|push_front|insert|push|assign") &&
2494 astIsNonStringContainer(memtok)) {
2495 std::vector<const Token *> args = getArguments(tok);
2496 const std::size_t n = args.size();
2497 if (n > 1 && Token::typeStr(args[n - 2]) == Token::typeStr(args[n - 1]) &&
2498 ((astIsIterator(args[n - 2]) && astIsIterator(args[n - 1])) ||
2499 (astIsPointer(args[n - 2]) && astIsPointer(args[n - 1])))) {
2500 LifetimeStore{
2501 args.back(), "Added to container '" + memtok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}
2502 .byDerefCopy(memtok, tokenlist, errorLogger, settings);
2503 } else if (!args.empty() && ValueFlow::isLifetimeBorrowed(args.back(), settings)) {
2504 LifetimeStore{
2505 args.back(), "Added to container '" + memtok->str() + "'.", ValueFlow::Value::LifetimeKind::Object}
2506 .byVal(memtok, tokenlist, errorLogger, settings);
2507 }
2508 } else if (tok->function()) {
2509 const Function *f = tok->function();

Callers 2

valueFlowForwardLifetimeFunction · 0.85
valueFlowLifetimeFunction · 0.85

Calls 15

astIsRHSFunction · 0.85
setTokenValueFunction · 0.85
valueFlowForwardLifetimeFunction · 0.85
astIsNonStringContainerFunction · 0.85
astIsIteratorFunction · 0.85
astIsPointerFunction · 0.85
isLifetimeBorrowedFunction · 0.85
isVariableChangedFunction · 0.85
containsFunction · 0.85
exprDependsOnThisFunction · 0.85
lifetimeTypeFunction · 0.85

Tested by

no test coverage detected