Fix 10592: False positive: returnDanglingLifetime (#3557)
This commit is contained in:
parent
0d1d3b4ed0
commit
c057dcce0f
|
@ -259,6 +259,15 @@ bool astIsSmartPointer(const Token* tok)
|
|||
return tok && tok->valueType() && tok->valueType()->smartPointerTypeToken;
|
||||
}
|
||||
|
||||
bool astIsUniqueSmartPointer(const Token* tok)
|
||||
{
|
||||
if (!astIsSmartPointer(tok))
|
||||
return false;
|
||||
if (!tok->valueType()->smartPointer)
|
||||
return false;
|
||||
return tok->valueType()->smartPointer->unique;
|
||||
}
|
||||
|
||||
bool astIsIterator(const Token *tok)
|
||||
{
|
||||
return tok && tok->valueType() && tok->valueType()->type == ValueType::Type::ITERATOR;
|
||||
|
|
|
@ -82,6 +82,7 @@ bool astIsBool(const Token *tok);
|
|||
bool astIsPointer(const Token *tok);
|
||||
|
||||
bool astIsSmartPointer(const Token* tok);
|
||||
bool astIsUniqueSmartPointer(const Token* tok);
|
||||
|
||||
bool astIsIterator(const Token *tok);
|
||||
|
||||
|
|
|
@ -557,6 +557,21 @@ static const Token* getParentLifetime(bool cpp, const Token* tok, const Library*
|
|||
if (std::any_of(it.base() - 1, members.end() - 1, [&](const Token* tok2) {
|
||||
if (astIsPointer(tok2) || astIsContainerView(tok2) || astIsIterator(tok2))
|
||||
return true;
|
||||
if (!astIsUniqueSmartPointer(tok2)) {
|
||||
if (astIsSmartPointer(tok2))
|
||||
return true;
|
||||
const Token* dotTok = tok2->next();
|
||||
if (!Token::simpleMatch(dotTok, ".")) {
|
||||
const Token* endTok = nextAfterAstRightmostLeaf(tok2);
|
||||
if (Token::simpleMatch(endTok, "."))
|
||||
dotTok = endTok;
|
||||
else if (Token::simpleMatch(endTok->next(), "."))
|
||||
dotTok = endTok->next();
|
||||
}
|
||||
// If we are dereferencing the member variable then treat it as borrowed
|
||||
if (Token::simpleMatch(dotTok, ".") && dotTok->originalName() == "->")
|
||||
return true;
|
||||
}
|
||||
const Variable* var = tok2->variable();
|
||||
return var && var->isReference();
|
||||
}))
|
||||
|
|
|
@ -2885,15 +2885,6 @@ static void valueFlowReverse(TokenList* tokenlist,
|
|||
valueFlowReverse(tok, nullptr, varToken, values, tokenlist, settings);
|
||||
}
|
||||
|
||||
static bool isUniqueSmartPointer(const Token* tok)
|
||||
{
|
||||
if (!astIsSmartPointer(tok))
|
||||
return false;
|
||||
if (!tok->valueType()->smartPointer)
|
||||
return false;
|
||||
return tok->valueType()->smartPointer->unique;
|
||||
}
|
||||
|
||||
std::string lifetimeType(const Token *tok, const ValueFlow::Value *val)
|
||||
{
|
||||
std::string result;
|
||||
|
@ -3090,8 +3081,7 @@ static std::vector<LifetimeToken> getLifetimeTokens(const Token* tok,
|
|||
return {{tok, std::move(errorPath)}};
|
||||
const Variable *tokvar = vartok->variable();
|
||||
const bool isContainer = astIsContainer(vartok) && !astIsPointer(vartok);
|
||||
if (!isUniqueSmartPointer(vartok) && !isContainer &&
|
||||
!(tokvar && tokvar->isArray() && !tokvar->isArgument()) &&
|
||||
if (!astIsUniqueSmartPointer(vartok) && !isContainer && !(tokvar && tokvar->isArray() && !tokvar->isArgument()) &&
|
||||
(Token::Match(vartok->astParent(), "[|*") || vartok->astParent()->originalName() == "->")) {
|
||||
for (const ValueFlow::Value &v : vartok->values()) {
|
||||
if (!v.isLocalLifetimeValue())
|
||||
|
@ -4158,7 +4148,7 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase*, ErrorLogger
|
|||
valueFlowLifetimeFunction(tok, tokenlist, errorLogger, settings);
|
||||
}
|
||||
// Unique pointer lifetimes
|
||||
else if (isUniqueSmartPointer(tok) && astIsLHS(tok) && Token::simpleMatch(tok->astParent(), ". get ( )")) {
|
||||
else if (astIsUniqueSmartPointer(tok) && astIsLHS(tok) && Token::simpleMatch(tok->astParent(), ". get ( )")) {
|
||||
Token* ptok = tok->astParent()->tokAt(2);
|
||||
ErrorPath errorPath = {{ptok, "Raw pointer to smart pointer created here."}};
|
||||
ValueFlow::Value value;
|
||||
|
|
|
@ -2482,6 +2482,15 @@ private:
|
|||
" }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
check("struct A {\n"
|
||||
" std::map<std::string, int> m;\n"
|
||||
" int* f(std::string s) {\n"
|
||||
" auto r = m.emplace(name, name);\n"
|
||||
" return &(r.first->second);\n"
|
||||
" }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void danglingLifetimeContainerView()
|
||||
|
|
Loading…
Reference in New Issue