Fix issue 10214: FP: danglingTempReference doesn't account for reference lifetime extension (#3220)
* Fix issue 10214: FP: danglingTempReference doesn't account for reference lifetime extension
This commit is contained in:
parent
59f7b937f1
commit
db5f00a16a
|
@ -488,6 +488,18 @@ static bool isDanglingSubFunction(const Token* tokvalue, const Token* tok)
|
|||
return exprDependsOnThis(parent);
|
||||
}
|
||||
|
||||
static bool isAssignedToNonLocal(const Token* tok)
|
||||
{
|
||||
if (!Token::simpleMatch(tok->astParent(), "="))
|
||||
return false;
|
||||
if (!Token::Match(tok->astParent()->astOperand1(), "%var%"))
|
||||
return false;
|
||||
const Variable* var = tok->astParent()->astOperand1()->variable();
|
||||
if (!var)
|
||||
return false;
|
||||
return !var->isLocal() || var->isStatic();
|
||||
}
|
||||
|
||||
void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token * end)
|
||||
{
|
||||
const bool printInconclusive = mSettings->certainty.isEnabled(Certainty::inconclusive);
|
||||
|
@ -546,7 +558,8 @@ void CheckAutoVariables::checkVarLifetimeScope(const Token * start, const Token
|
|||
if (!printInconclusive && val.isInconclusive())
|
||||
continue;
|
||||
const bool escape = Token::Match(tok->astParent(), "return|throw");
|
||||
for (const LifetimeToken& lt : getLifetimeTokens(getParentLifetime(val.tokvalue), escape)) {
|
||||
for (const LifetimeToken& lt :
|
||||
getLifetimeTokens(getParentLifetime(val.tokvalue), escape || isAssignedToNonLocal(tok))) {
|
||||
const Token * tokvalue = lt.token;
|
||||
if (val.isLocalLifetimeValue()) {
|
||||
if (escape) {
|
||||
|
|
|
@ -2693,10 +2693,10 @@ std::vector<LifetimeToken> getLifetimeTokens(const Token* tok, bool escape, Valu
|
|||
} else if (Token::simpleMatch(var->declEndToken(), "=")) {
|
||||
errorPath.emplace_back(var->declEndToken(), "Assigned to reference.");
|
||||
const Token *vartok = var->declEndToken()->astOperand2();
|
||||
const bool temporaryDefault = false; //If we can't tell then assume the value is not temporary as this will result in fewer false positives.
|
||||
const bool temporary = isTemporary(true, vartok, nullptr, temporaryDefault);
|
||||
const bool temporary = isTemporary(true, vartok, nullptr, true);
|
||||
const bool nonlocal = var->isStatic() || var->isGlobal();
|
||||
if (vartok == tok || (nonlocal && temporary) || (!escape && (var->isConst() || var->isRValueReference()) && temporary))
|
||||
if (vartok == tok || (nonlocal && temporary) ||
|
||||
(!escape && (var->isConst() || var->isRValueReference()) && temporary))
|
||||
return {{tok, true, std::move(errorPath)}};
|
||||
if (vartok)
|
||||
return getLifetimeTokens(vartok, escape, std::move(errorPath), depth - 1);
|
||||
|
|
|
@ -2597,6 +2597,19 @@ private:
|
|||
" return e;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// #10214
|
||||
check("struct A {\n"
|
||||
" std::string key;\n"
|
||||
" const char *value;\n"
|
||||
"};\n"
|
||||
"const char *f(const std::string &key, const std::vector<A> &lookup) {\n"
|
||||
" const auto &entry =\n"
|
||||
" std::find_if(lookup.begin(), lookup.end(),\n"
|
||||
" [key](const auto &v) { return v.key == key; });\n"
|
||||
" return (entry == lookup.end()) ? \"\" : entry->value;\n"
|
||||
"}\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void danglingLifetimeFunction() {
|
||||
|
|
Loading…
Reference in New Issue