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

Function valueFlowForwardLifetime

lib/valueflow.cpp:1955–2043  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

1953}
1954
1955static void valueFlowForwardLifetime(Token * tok, const TokenList &tokenlist, ErrorLogger &errorLogger, const Settings &settings)
1956{
1957 // Forward lifetimes to constructed variable
1958 if (Token::Match(tok->previous(), "%var% {|(") && isVariableDecl(tok->previous())) {
1959 std::list<ValueFlow::Value> values = tok->values();
1960 values.remove_if(&isNotLifetimeValue);
1961 valueFlowForward(nextAfterAstRightmostLeaf(tok), ValueFlow::getEndOfExprScope(tok), tok->previous(), std::move(values), tokenlist, errorLogger, settings);
1962 return;
1963 }
1964 Token *parent = tok->astParent();
1965 while (parent && parent->str() == ",")
1966 parent = parent->astParent();
1967 if (!parent)
1968 return;
1969 // Assignment
1970 if (parent->str() == "=" && (!parent->astParent() || Token::simpleMatch(parent->astParent(), ";"))) {
1971 // Rhs values..
1972 if (!parent->astOperand2() || parent->astOperand2()->values().empty())
1973 return;
1974
1975 if (!ValueFlow::isLifetimeBorrowed(parent->astOperand2(), settings))
1976 return;
1977
1978 const Token* expr = getLHSVariableToken(parent);
1979 if (!expr)
1980 return;
1981
1982 if (expr->exprId() == 0)
1983 return;
1984
1985 const Token* endOfVarScope = ValueFlow::getEndOfExprScope(expr);
1986
1987 // Only forward lifetime values
1988 std::list<ValueFlow::Value> values = parent->astOperand2()->values();
1989 values.remove_if(&isNotLifetimeValue);
1990 // Dont forward lifetimes that overlap
1991 values.remove_if([&](const ValueFlow::Value& value) {
1992 return findAstNode(value.tokvalue, [&](const Token* child) {
1993 return child->exprId() == expr->exprId();
1994 });
1995 });
1996
1997 // Skip RHS
1998 Token* nextExpression = nextAfterAstRightmostLeaf(parent);
1999
2000 if (expr->exprId() > 0) {
2001 valueFlowForward(nextExpression, endOfVarScope->next(), expr, values, tokenlist, errorLogger, settings);
2002
2003 for (ValueFlow::Value& val : values) {
2004 if (val.lifetimeKind == ValueFlow::Value::LifetimeKind::Address)
2005 val.lifetimeKind = ValueFlow::Value::LifetimeKind::SubObject;
2006 }
2007 // TODO: handle `[`
2008 if (Token::simpleMatch(parent->astOperand1(), ".")) {
2009 const Token* parentLifetime =
2010 getParentLifetime(parent->astOperand1()->astOperand2(), settings.library);
2011 if (parentLifetime && parentLifetime->exprId() > 0) {
2012 valueFlowForward(nextExpression, endOfVarScope, parentLifetime, std::move(values), tokenlist, errorLogger, settings);

Callers 5

forEachMethod · 0.85
forwardLifetimeMethod · 0.85
valueFlowLifetimeFunction · 0.85
valueFlowForwardAssignFunction · 0.85

Calls 15

isVariableDeclFunction · 0.85
valueFlowForwardFunction · 0.85
isLifetimeBorrowedFunction · 0.85
getLHSVariableTokenFunction · 0.85
findAstNodeFunction · 0.85
getParentLifetimeFunction · 0.85
isScopeBracketFunction · 0.85
setTokenValueFunction · 0.85
astParentMethod · 0.80

Tested by

no test coverage detected