diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index a74685c39..c830e76c4 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -3623,11 +3623,18 @@ static void valueFlowLifetime(TokenList *tokenlist, SymbolDatabase*, ErrorLogger if (!Token::Match(parent, ". %name% (")) continue; + bool isContainerOfPointers = true; + const Token* containerTypeToken = tok->valueType()->containerTypeToken; + if (containerTypeToken) { + ValueType vt = ValueType::parseDecl(containerTypeToken, settings); + isContainerOfPointers = vt.pointer > 0; + } + LifetimeStore ls; if (astIsIterator(parent->tokAt(2))) 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}; else continue; diff --git a/test/teststl.cpp b/test/teststl.cpp index 931fdc73f..e00595055 100644 --- a/test/teststl.cpp +++ b/test/teststl.cpp @@ -4164,6 +4164,40 @@ private: " v.push_back(\"y\");\n" "}\n",true); ASSERT_EQUALS("", errout.str()); + + // #9796 + check("struct A {};\n" + "void f() {\n" + " std::vector 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> 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> v;\n" + " std::shared_ptr a = std::make_shared();\n" + " v.push_back(a);\n" + " std::shared_ptr b = v.back();\n" + " v.pop_back();\n" + " delete b;\n" + "}\n" ,true); + ASSERT_EQUALS("", errout.str()); } void invalidContainerLoop() {