diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 7848ef4e97c..ffe78b298cb 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -5738,11 +5738,11 @@ static void valueFlowSubFunction(const TokenList& tokenlist, // passing value(s) to function std::list argvalues(getFunctionArgumentValues(argtok)); - // Remove non-local lifetimes + // Remove non-local lifetimes and moved values argvalues.remove_if([](const ValueFlow::Value& v) { if (v.isLifetimeValue()) return !v.isLocalLifetimeValue() && !v.isSubFunctionLifetimeValue(); - return false; + return v.isMovedValue(); }); // Remove uninit values if argument is passed by value if (argtok->variable() && !argtok->variable()->isPointer() && argvalues.size() == 1 && diff --git a/test/testother.cpp b/test/testother.cpp index e285d8d8bd0..7c8c6f891c0 100644 --- a/test/testother.cpp +++ b/test/testother.cpp @@ -312,6 +312,7 @@ class TestOther : public TestFixture { TEST_CASE(movePointerAlias); TEST_CASE(moveOutparam); TEST_CASE(moveTryEmplace); + TEST_CASE(moveSubFunction); TEST_CASE(funcArgNamesDifferent); TEST_CASE(funcArgOrderDifferent); @@ -13342,6 +13343,20 @@ class TestOther : public TestFixture { ASSERT_EQUALS("", errout_str()); } + void moveSubFunction() + { + check("struct T {\n" // #15150 + " void set(std::string a) { m = std::move(a); }\n" + " std::string m;\n" + "};\n" + "void f(std::string s) {\n" + " T t;\n" + " t.set(std::move(s));\n" + " t.set(s);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:8:11]: (warning) Access of moved variable 's'. [accessMoved]\n", errout_str()); + } + void funcArgNamesDifferent() { check("void func1(int a, int b, int c);\n" "void func1(int a, int b, int c) { }\n"