Fix 11468: false positive danglingTempReference warning (#4679)
This commit is contained in:
parent
aab3d30e4c
commit
cefc105c5f
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in New Issue