Skip to content

Commit c057dcc

Browse files
authored
Fix 10592: False positive: returnDanglingLifetime (#3557)
1 parent 0d1d3b4 commit c057dcc

5 files changed

Lines changed: 36 additions & 12 deletions

File tree

lib/astutils.cpp

100644100755
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,15 @@ bool astIsSmartPointer(const Token* tok)
259259
return tok && tok->valueType() && tok->valueType()->smartPointerTypeToken;
260260
}
261261

262+
bool astIsUniqueSmartPointer(const Token* tok)
263+
{
264+
if (!astIsSmartPointer(tok))
265+
return false;
266+
if (!tok->valueType()->smartPointer)
267+
return false;
268+
return tok->valueType()->smartPointer->unique;
269+
}
270+
262271
bool astIsIterator(const Token *tok)
263272
{
264273
return tok && tok->valueType() && tok->valueType()->type == ValueType::Type::ITERATOR;

lib/astutils.h

100644100755
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ bool astIsBool(const Token *tok);
8282
bool astIsPointer(const Token *tok);
8383

8484
bool astIsSmartPointer(const Token* tok);
85+
bool astIsUniqueSmartPointer(const Token* tok);
8586

8687
bool astIsIterator(const Token *tok);
8788

lib/checkautovariables.cpp

100644100755
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,21 @@ static const Token* getParentLifetime(bool cpp, const Token* tok, const Library*
557557
if (std::any_of(it.base() - 1, members.end() - 1, [&](const Token* tok2) {
558558
if (astIsPointer(tok2) || astIsContainerView(tok2) || astIsIterator(tok2))
559559
return true;
560+
if (!astIsUniqueSmartPointer(tok2)) {
561+
if (astIsSmartPointer(tok2))
562+
return true;
563+
const Token* dotTok = tok2->next();
564+
if (!Token::simpleMatch(dotTok, ".")) {
565+
const Token* endTok = nextAfterAstRightmostLeaf(tok2);
566+
if (Token::simpleMatch(endTok, "."))
567+
dotTok = endTok;
568+
else if (Token::simpleMatch(endTok->next(), "."))
569+
dotTok = endTok->next();
570+
}
571+
// If we are dereferencing the member variable then treat it as borrowed
572+
if (Token::simpleMatch(dotTok, ".") && dotTok->originalName() == "->")
573+
return true;
574+
}
560575
const Variable* var = tok2->variable();
561576
return var && var->isReference();
562577
}))

lib/valueflow.cpp

100644100755
Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2885,15 +2885,6 @@ static void valueFlowReverse(TokenList* tokenlist,
28852885
valueFlowReverse(tok, nullptr, varToken, values, tokenlist, settings);
28862886
}
28872887

2888-
static bool isUniqueSmartPointer(const Token* tok)
2889-
{
2890-
if (!astIsSmartPointer(tok))
2891-
return false;
2892-
if (!tok->valueType()->smartPointer)
2893-
return false;
2894-
return tok->valueType()->smartPointer->unique;
2895-
}
2896-
28972888
std::string lifetimeType(const Token *tok, const ValueFlow::Value *val)
28982889
{
28992890
std::string result;
@@ -3090,8 +3081,7 @@ static std::vector<LifetimeToken> getLifetimeTokens(const Token* tok,
30903081
return {{tok, std::move(errorPath)}};
30913082
const Variable *tokvar = vartok->variable();
30923083
const bool isContainer = astIsContainer(vartok) && !astIsPointer(vartok);
3093-
if (!isUniqueSmartPointer(vartok) && !isContainer &&
3094-
!(tokvar && tokvar->isArray() && !tokvar->isArgument()) &&
3084+
if (!astIsUniqueSmartPointer(vartok) && !isContainer && !(tokvar && tokvar->isArray() && !tokvar->isArgument()) &&
30953085
(Token::Match(vartok->astParent(), "[|*") || vartok->astParent()->originalName() == "->")) {
30963086
for (const ValueFlow::Value &v : vartok->values()) {
30973087
if (!v.isLocalLifetimeValue())
@@ -4158,7 +4148,7 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase*, ErrorLogger
41584148
valueFlowLifetimeFunction(tok, tokenlist, errorLogger, settings);
41594149
}
41604150
// Unique pointer lifetimes
4161-
else if (isUniqueSmartPointer(tok) && astIsLHS(tok) && Token::simpleMatch(tok->astParent(), ". get ( )")) {
4151+
else if (astIsUniqueSmartPointer(tok) && astIsLHS(tok) && Token::simpleMatch(tok->astParent(), ". get ( )")) {
41624152
Token* ptok = tok->astParent()->tokAt(2);
41634153
ErrorPath errorPath = {{ptok, "Raw pointer to smart pointer created here."}};
41644154
ValueFlow::Value value;

test/testautovariables.cpp

100644100755
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2482,6 +2482,15 @@ class TestAutoVariables : public TestFixture {
24822482
" }\n"
24832483
"};\n");
24842484
ASSERT_EQUALS("", errout.str());
2485+
2486+
check("struct A {\n"
2487+
" std::map<std::string, int> m;\n"
2488+
" int* f(std::string s) {\n"
2489+
" auto r = m.emplace(name, name);\n"
2490+
" return &(r.first->second);\n"
2491+
" }\n"
2492+
"};\n");
2493+
ASSERT_EQUALS("", errout.str());
24852494
}
24862495

24872496
void danglingLifetimeContainerView()

0 commit comments

Comments
 (0)