Fix FP#11508 (#4774)

* Add tests to cover the issue

* Set lifetime of pointer to data passed as view to SubFunction

* Move isContainerOfPointers to separate function

* Revert "Set lifetime of pointer to data passed as view to SubFunction"

This reverts commit 30dafe23e40354606776d2573653608025cae754.

* Skip propagating lifetime of iterators/pointers for views

* Add indents to test cases

* Skip all non-local values in container view lifetime
This commit is contained in:
Mateusz Michalak 2023-02-18 17:38:51 +01:00 committed by GitHub
parent ff0eee4d77
commit 9b62caf0ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 9 deletions

View File

@ -4629,6 +4629,17 @@ static bool isConvertedToView(const Token* tok, const Settings* settings)
});
}
static bool isContainerOfPointers(const Token* tok, const Settings* settings)
{
if (!tok)
{
return true;
}
ValueType vt = ValueType::parseDecl(tok, settings, true); // TODO: set isCpp
return vt.pointer > 0;
}
static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase* /*db*/, ErrorLogger *errorLogger, const Settings *settings)
{
for (Token *tok = tokenlist->front(); tok; tok = tok->next()) {
@ -4781,13 +4792,6 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase* /*db*/, Erro
if (!Token::Match(parent, ". %name% ("))
continue;
bool isContainerOfPointers = true;
const Token* containerTypeToken = tok->valueType()->containerTypeToken;
if (containerTypeToken) {
ValueType vt = ValueType::parseDecl(containerTypeToken, settings, true); // TODO: set isCpp
isContainerOfPointers = vt.pointer > 0;
}
ValueFlow::Value master;
master.valueType = ValueFlow::Value::ValueType::LIFETIME;
master.lifetimeScope = ValueFlow::Value::LifetimeScope::Local;
@ -4795,7 +4799,7 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase* /*db*/, Erro
if (astIsIterator(parent->tokAt(2))) {
master.errorPath.emplace_back(parent->tokAt(2), "Iterator to container is created here.");
master.lifetimeKind = ValueFlow::Value::LifetimeKind::Iterator;
} else if ((astIsPointer(parent->tokAt(2)) && !isContainerOfPointers) ||
} else if ((astIsPointer(parent->tokAt(2)) && !isContainerOfPointers(tok->valueType()->containerTypeToken, settings)) ||
Token::Match(parent->next(), "data|c_str")) {
master.errorPath.emplace_back(parent->tokAt(2), "Pointer to container is created here.");
master.lifetimeKind = ValueFlow::Value::LifetimeKind::Object;
@ -4816,7 +4820,7 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase* /*db*/, Erro
}
} else if (astIsContainerView(tok)) {
for (const ValueFlow::Value& v : tok->values()) {
if (!v.isLifetimeValue())
if (!v.isLocalLifetimeValue())
continue;
if (!v.tokvalue)
continue;

View File

@ -4194,6 +4194,27 @@ private:
" f(bar);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:10]: (error) Address of local auto-variable assigned to a function parameter.\n", errout.str());
check("void f(std::string_view text);\n" // #11508
"void g() {\n"
" std::string teststr;\n"
" f(teststr);"
"}\n"
"void f(std::string_view text) {"
" g(text.data());\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("void f(std::span<int> data);\n" // #11508
"void g() {\n"
" std::vector<int> v;\n"
" f(v);"
"}\n"
"void f(std::span<int> data) {"
" g(data.begin());\n"
"}\n");
ASSERT_EQUALS("", errout.str());
}
void deadPointer() {