Fix 11468: false positive danglingTempReference warning (#4679)

This commit is contained in:
Paul Fultz II 2023-01-07 16:44:22 -06:00 committed by GitHub
parent aab3d30e4c
commit cefc105c5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 35 additions and 9 deletions

View File

@ -4079,19 +4079,20 @@ struct LifetimeStore {
} }
template<class Predicate> template<class Predicate>
void byDerefCopy(Token* tok, bool byDerefCopy(Token* tok,
TokenList* tokenlist, TokenList* tokenlist,
ErrorLogger* errorLogger, ErrorLogger* errorLogger,
const Settings* settings, const Settings* settings,
Predicate pred, Predicate pred,
SourceLocation loc = SourceLocation::current()) const SourceLocation loc = SourceLocation::current()) const
{ {
bool update = false;
if (!settings->certainty.isEnabled(Certainty::inconclusive) && inconclusive) if (!settings->certainty.isEnabled(Certainty::inconclusive) && inconclusive)
return; return update;
if (!argtok) if (!argtok)
return; return update;
if (!tok) if (!tok)
return; return update;
for (const ValueFlow::Value &v : argtok->values()) { for (const ValueFlow::Value &v : argtok->values()) {
if (!v.isLifetimeValue()) if (!v.isLifetimeValue())
continue; continue;
@ -4105,20 +4106,22 @@ struct LifetimeStore {
const Token * const varDeclEndToken = var->declEndToken(); const Token * const varDeclEndToken = var->declEndToken();
for (const Token *tok3 = tok; tok3 && tok3 != varDeclEndToken; tok3 = tok3->previous()) { for (const Token *tok3 = tok; tok3 && tok3 != varDeclEndToken; tok3 = tok3->previous()) {
if (tok3->varId() == var->declarationId()) { if (tok3->varId() == var->declarationId()) {
LifetimeStore{tok3, message, type, inconclusive}.byVal(tok, tokenlist, errorLogger, settings, pred, loc); update |= LifetimeStore{tok3, message, type, inconclusive}
.byVal(tok, tokenlist, errorLogger, settings, pred, loc);
break; break;
} }
} }
} }
return update;
} }
void byDerefCopy(Token* tok, bool byDerefCopy(Token* tok,
TokenList* tokenlist, TokenList* tokenlist,
ErrorLogger* errorLogger, ErrorLogger* errorLogger,
const Settings* settings, const Settings* settings,
SourceLocation loc = SourceLocation::current()) const SourceLocation loc = SourceLocation::current()) const
{ {
byDerefCopy( return byDerefCopy(
tok, tok,
tokenlist, tokenlist,
errorLogger, errorLogger,
@ -4348,9 +4351,14 @@ static void valueFlowLifetimeFunction(Token *tok, TokenList *tokenlist, ErrorLog
ls.forward = false; ls.forward = false;
ls.errorPath = v.errorPath; ls.errorPath = v.errorPath;
ls.errorPath.emplace_front(returnTok, "Return " + lifetimeType(returnTok, &v) + "."); ls.errorPath.emplace_front(returnTok, "Return " + lifetimeType(returnTok, &v) + ".");
if (v.lifetimeScope == ValueFlow::Value::LifetimeScope::ThisValue) int thisIndirect = v.lifetimeScope == ValueFlow::Value::LifetimeScope::ThisValue ? 0 : 1;
if (derefShared(memtok->astParent()))
thisIndirect--;
if (thisIndirect == -1)
update |= ls.byDerefCopy(tok->next(), tokenlist, errorLogger, settings);
else if (thisIndirect == 0)
update |= ls.byVal(tok->next(), tokenlist, errorLogger, settings); update |= ls.byVal(tok->next(), tokenlist, errorLogger, settings);
else else if (thisIndirect == 1)
update |= ls.byRef(tok->next(), tokenlist, errorLogger, settings); update |= ls.byRef(tok->next(), tokenlist, errorLogger, settings);
continue; continue;
} }

View File

@ -2004,6 +2004,24 @@ private:
ASSERT_EQUALS( ASSERT_EQUALS(
"[test.cpp:11] -> [test.cpp:2] -> [test.cpp:11] -> [test.cpp:12]: (error) Using reference to dangling temporary.\n", "[test.cpp:11] -> [test.cpp:2] -> [test.cpp:11] -> [test.cpp:12]: (error) Using reference to dangling temporary.\n",
errout.str()); errout.str());
check("struct C {\n"
" std::vector<std::vector<int>> v;\n"
"};\n"
"struct P {\n"
" std::vector<C*>::const_iterator find() const { return pv.begin(); }\n"
" std::vector<C*> pv;\n"
"};\n"
"struct M {\n"
" const P* get() const { return p; }\n"
" P* p;\n"
"};\n"
"void f(const M* m) {\n"
" auto it = m->get()->find();\n"
" auto e = (*it)->v.begin();\n"
" const int& x = (*e)[1];\n"
"}\n");
ASSERT_EQUALS("", errout.str());
} }
void testglobalnamespace() { void testglobalnamespace() {