Merge pull request #2710 from pfultz2/fp-invalid-container-pointer
Fix issue 9796: False positive: lifetime, pointer item is not deallocated by pop_back
This commit is contained in:
commit
2fd44fa464
|
@ -3623,11 +3623,18 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase*, ErrorLogger
|
||||||
if (!Token::Match(parent, ". %name% ("))
|
if (!Token::Match(parent, ". %name% ("))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
bool isContainerOfPointers = true;
|
||||||
|
const Token* containerTypeToken = tok->valueType()->containerTypeToken;
|
||||||
|
if (containerTypeToken) {
|
||||||
|
ValueType vt = ValueType::parseDecl(containerTypeToken, settings);
|
||||||
|
isContainerOfPointers = vt.pointer > 0;
|
||||||
|
}
|
||||||
|
|
||||||
LifetimeStore ls;
|
LifetimeStore ls;
|
||||||
|
|
||||||
if (astIsIterator(parent->tokAt(2)))
|
if (astIsIterator(parent->tokAt(2)))
|
||||||
ls = LifetimeStore{tok, "Iterator to container is created here.", ValueFlow::Value::LifetimeKind::Iterator};
|
ls = LifetimeStore{tok, "Iterator to container is created here.", ValueFlow::Value::LifetimeKind::Iterator};
|
||||||
else if (astIsPointer(parent->tokAt(2)) || Token::Match(parent->next(), "data|c_str"))
|
else if ((astIsPointer(parent->tokAt(2)) && !isContainerOfPointers) || Token::Match(parent->next(), "data|c_str"))
|
||||||
ls = LifetimeStore{tok, "Pointer to container is created here.", ValueFlow::Value::LifetimeKind::Object};
|
ls = LifetimeStore{tok, "Pointer to container is created here.", ValueFlow::Value::LifetimeKind::Object};
|
||||||
else
|
else
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -4164,6 +4164,40 @@ private:
|
||||||
" v.push_back(\"y\");\n"
|
" v.push_back(\"y\");\n"
|
||||||
"}\n",true);
|
"}\n",true);
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// #9796
|
||||||
|
check("struct A {};\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" std::vector<A *> v;\n"
|
||||||
|
" A *a = new A();\n"
|
||||||
|
" v.push_back(a);\n"
|
||||||
|
" A *b = v.back();\n"
|
||||||
|
" v.pop_back();\n"
|
||||||
|
" delete b;\n"
|
||||||
|
"}\n" ,true);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("struct A {};\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" std::vector<A *, std::allocator<A*>> v;\n"
|
||||||
|
" A *a = new A();\n"
|
||||||
|
" v.push_back(a);\n"
|
||||||
|
" A *b = v.back();\n"
|
||||||
|
" v.pop_back();\n"
|
||||||
|
" delete b;\n"
|
||||||
|
"}\n" ,true);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
check("struct A {};\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" std::vector<std::shared_ptr<A>> v;\n"
|
||||||
|
" std::shared_ptr<A> a = std::make_shared<A>();\n"
|
||||||
|
" v.push_back(a);\n"
|
||||||
|
" std::shared_ptr<A> b = v.back();\n"
|
||||||
|
" v.pop_back();\n"
|
||||||
|
" delete b;\n"
|
||||||
|
"}\n" ,true);
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void invalidContainerLoop() {
|
void invalidContainerLoop() {
|
||||||
|
|
Loading…
Reference in New Issue