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

Function getLifetimeTokens

lib/valueflow.cpp:1519–1670  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1517
1518template<class Predicate>
1519static std::vector<ValueFlow::LifetimeToken> getLifetimeTokens(const Token* tok,
1520 bool escape,
1521 ErrorPath errorPath,
1522 Predicate pred,
1523 const Settings& settings,
1524 int depth = 20)
1525{
1526 if (!tok)
1527 return std::vector<ValueFlow::LifetimeToken> {};
1528 if (Token::simpleMatch(tok, "..."))
1529 return std::vector<ValueFlow::LifetimeToken>{};
1530 const Variable *var = tok->variable();
1531 if (pred(tok))
1532 return {{tok, std::move(errorPath)}};
1533 if (depth < 0)
1534 return {{tok, std::move(errorPath)}};
1535 if (var && var->declarationId() == tok->varId()) {
1536 if (var->isReference() || var->isRValueReference()) {
1537 const Token * const varDeclEndToken = var->declEndToken();
1538 if (!varDeclEndToken)
1539 return {{tok, true, std::move(errorPath)}};
1540 if (var->isArgument()) {
1541 errorPath.emplace_back(varDeclEndToken, "Passed to reference.");
1542 return {{tok, true, std::move(errorPath)}};
1543 }
1544 if (Token::Match(varDeclEndToken, "=|{")) {
1545 errorPath.emplace_back(varDeclEndToken, "Assigned to reference.");
1546 const Token *vartok = varDeclEndToken->astOperand2();
1547 const bool temporary = isTemporary(vartok, nullptr, true);
1548 const bool nonlocal = var->isStatic() || var->isGlobal();
1549 if (vartok == tok || (nonlocal && temporary) ||
1550 (!escape && (var->isConst() || var->isRValueReference()) && temporary))
1551 return {{tok, true, std::move(errorPath)}};
1552 if (vartok)
1553 return getLifetimeTokens(vartok, escape, std::move(errorPath), pred, settings, depth - 1);
1554 } else if (Token::simpleMatch(var->nameToken()->astParent(), ":") &&
1555 var->nameToken()->astParent()->astParent() &&
1556 Token::simpleMatch(var->nameToken()->astParent()->astParent()->previous(), "for (")) {
1557 errorPath.emplace_back(var->nameToken(), "Assigned to reference.");
1558 const Token* vartok = var->nameToken();
1559 if (vartok == tok)
1560 return {{tok, true, std::move(errorPath)}};
1561 const Token* contok = var->nameToken()->astParent()->astOperand2();
1562 if (astIsContainer(contok))
1563 return ValueFlow::LifetimeToken::setAddressOf(
1564 getLifetimeTokens(contok, escape, std::move(errorPath), pred, settings, depth - 1),
1565 false);
1566 return std::vector<ValueFlow::LifetimeToken>{};
1567 } else {
1568 return std::vector<ValueFlow::LifetimeToken> {};
1569 }
1570 }
1571 } else if (Token::Match(tok->previous(), "%name% (")) {
1572 const Function *f = tok->previous()->function();
1573 if (f) {
1574 if (!Function::returnsReference(f))
1575 return {{tok, std::move(errorPath)}};
1576 std::vector<ValueFlow::LifetimeToken> result;

Callers 7

getLifetimeTokensMethod · 0.85
hasLifetimeTokenMethod · 0.85
getLifetimeTokenFunction · 0.85
byRefMethod · 0.85
byValMethod · 0.85
valueFlowLifetimeFunction · 0.85
checkVarLifetimeScopeMethod · 0.85

Calls 15

isTemporaryFunction · 0.85
astIsContainerFunction · 0.85
getArgumentPosFunction · 0.85
derefSharedFunction · 0.85
exprDependsOnThisFunction · 0.85
setInconclusiveFunction · 0.85
getLibraryContainerFunction · 0.85
getArgumentStartFunction · 0.85
getParentValueTypesFunction · 0.85
variableMethod · 0.80
declEndTokenMethod · 0.80
astOperand2Method · 0.80

Tested by

no test coverage detected