diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 29f8b8b35..611fcbde8 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -2649,7 +2649,7 @@ struct LifetimeStore { const Variable *var = getLifetimeVariable(tok2, errorPath); if (!var) continue; - for (const Token *tok3 = tok; tok != var->declEndToken(); tok3 = tok3->previous()) { + for (const Token *tok3 = tok; tok3 && tok3 != var->declEndToken(); tok3 = tok3->previous()) { if (tok3->varId() == var->declarationId()) { LifetimeStore{tok3, message, type} .byVal(tok, tokenlist, errorLogger, settings, pred); break; @@ -2699,8 +2699,10 @@ static void valueFlowLifetimeFunction(Token *tok, TokenList *tokenlist, ErrorLog const bool isPointer = endTypeTok && Token::simpleMatch(endTypeTok->previous(), "*"); Token *vartok = tok->tokAt(-2); std::vector args = getArguments(tok); - if (args.size() == 2 && astCanonicalType(args[0]) == astCanonicalType(args[1]) && - (((astIsIterator(args[0]) && astIsIterator(args[1])) || (astIsPointer(args[0]) && astIsPointer(args[1]))))) { + std::size_t n = args.size(); + if (n > 1 && astCanonicalType(args[n - 2]) == astCanonicalType(args[n - 1]) && + (((astIsIterator(args[n - 2]) && astIsIterator(args[n - 1])) || + (astIsPointer(args[n - 2]) && astIsPointer(args[n - 1]))))) { LifetimeStore{args.back(), "Added to container '" + vartok->str() + "'.", ValueFlow::Value::Object} .byDerefCopy( vartok, tokenlist, errorLogger, settings); } else if (!args.empty() && astIsPointer(args.back()) == isPointer) { diff --git a/test/testautovariables.cpp b/test/testautovariables.cpp index 5d9486953..296ffbe4d 100644 --- a/test/testautovariables.cpp +++ b/test/testautovariables.cpp @@ -1420,6 +1420,19 @@ private: "[test.cpp:5] -> [test.cpp:6] -> [test.cpp:4] -> [test.cpp:6]: (error) Non-local variable 'v' will use object that points to local variable 'i'.\n", errout.str()); + check("struct A {\n" + " std::vector m;\n" + " void f() {\n" + " int x;\n" + " std::vector v;\n" + " v.push_back(&x);\n" + " m.insert(m.end(), v.begin(), v.end());\n" + " }\n" + "};\n"); + ASSERT_EQUALS( + "[test.cpp:6] -> [test.cpp:6] -> [test.cpp:6] -> [test.cpp:4] -> [test.cpp:7]: (error) Non-local variable 'm' will use object that points to local variable 'x'.\n", + errout.str()); + check("struct A {\n" " std::vector v;\n" " void f() {\n" @@ -1483,6 +1496,27 @@ private: " return g([&]() { return v.data(); });\n" "}\n"); ASSERT_EQUALS("", errout.str()); + + check("std::vector g();\n" + "struct A {\n" + " std::vector m;\n" + " void f() {\n" + " std::vector v = g();\n" + " m.insert(m.end(), v.begin(), v.end());\n" + " }\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); + + check("class A {\n" + " int f( P p ) {\n" + " std::vector< S > maps;\n" + " m2.insert( m1.begin(), m1.end() );\n" + " }\n" + " struct B {};\n" + " std::map< S, B > m1;\n" + " std::map< S, B > m2;\n" + "};\n"); + ASSERT_EQUALS("", errout.str()); } void danglingLifetime() {