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:
parent
ff0eee4d77
commit
9b62caf0ef
|
@ -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;
|
||||
|
|
|
@ -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() {
|
||||
|
|
Loading…
Reference in New Issue