Fix issue 9880: False positive: danglingLifetime (#2810)

This commit is contained in:
Paul Fultz II 2020-09-17 00:23:38 -05:00 committed by GitHub
parent b827f8d92e
commit 11c99d7387
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 37 additions and 2 deletions

View File

@ -3507,6 +3507,7 @@ struct LifetimeStore {
ValueFlow::Value value;
value.valueType = ValueFlow::Value::LIFETIME;
value.lifetimeScope = v.lifetimeScope;
value.path = v.path;
value.tokvalue = lt.token;
value.errorPath = std::move(er);
value.lifetimeKind = type;
@ -3612,7 +3613,7 @@ static void valueFlowLifetimeFunction(Token *tok, TokenList *tokenlist, ErrorLog
for (const Token* returnTok : returns) {
if (returnTok == tok)
continue;
const Variable *returnVar = returnTok->variable();
const Variable *returnVar = getLifetimeVariable(returnTok);
if (returnVar && returnVar->isArgument() && (returnVar->isConst() || !isVariableChanged(returnVar, settings, tokenlist->isCPP()))) {
LifetimeStore ls = LifetimeStore::fromFunctionArg(f, tok, returnVar, tokenlist, errorLogger);
ls.inconclusive = inconclusive;
@ -3630,7 +3631,7 @@ static void valueFlowLifetimeFunction(Token *tok, TokenList *tokenlist, ErrorLog
ls.inconclusive = inconclusive;
ls.errorPath = v.errorPath;
ls.errorPath.emplace_front(returnTok, "Return " + lifetimeType(returnTok, &v) + ".");
if (var->isReference() || var->isRValueReference()) {
if (!v.isArgumentLifetimeValue() && (var->isReference() || var->isRValueReference())) {
ls.byRef(tok->next(), tokenlist, errorLogger, settings);
} else if (v.isArgumentLifetimeValue()) {
ls.byVal(tok->next(), tokenlist, errorLogger, settings);

View File

@ -2515,6 +2515,18 @@ private:
"[test.cpp:7] -> [test.cpp:7] -> [test.cpp:3] -> [test.cpp:3] -> [test.cpp:6] -> [test.cpp:7]: (error) Returning object that points to local variable 'v' that will be invalid when returning.\n",
errout.str());
check("template<class T>\n"
"auto by_value(const T& x) {\n"
" return [=] { return x; };\n"
"}\n"
"auto g() {\n"
" std::vector<int> v;\n"
" return by_value(v.begin());\n"
"}\n");
ASSERT_EQUALS(
"[test.cpp:7] -> [test.cpp:7] -> [test.cpp:3] -> [test.cpp:3] -> [test.cpp:2] -> [test.cpp:6] -> [test.cpp:7]: (error) Returning object that points to local variable 'v' that will be invalid when returning.\n",
errout.str());
check("auto by_ref(int& x) {\n"
" return [&] { return x; };\n"
"}\n"
@ -2526,12 +2538,34 @@ private:
"[test.cpp:2] -> [test.cpp:1] -> [test.cpp:2] -> [test.cpp:6] -> [test.cpp:5] -> [test.cpp:6]: (error) Returning object that points to local variable 'i' that will be invalid when returning.\n",
errout.str());
check("auto by_ref(const int& x) {\n"
" return [=] { return x; };\n"
"}\n"
"auto f() {\n"
" int i = 0;\n"
" return by_ref(i);\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("auto f(int x) {\n"
" int a;\n"
" std::tie(a) = x;\n"
" return a;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("std::pair<std::string, std::string>\n"
"str_pair(std::string const & a, std::string const & b) {\n"
" return std::make_pair(a, b);\n"
"}\n"
"std::vector<std::pair<std::string, std::string> > create_parameters() {\n"
" std::vector<std::pair<std::string, std::string> > par;\n"
" par.push_back(str_pair(\"param1\", \"prop_a\"));\n"
" par.push_back(str_pair(\"param2\", \"prop_b\"));\n"
" par.push_back(str_pair(\"param3\", \"prop_c\"));\n"
" return par;\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void danglingLifetimeAggegrateConstructor() {