diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 4be7a13dbc7..107d3de8462 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -5739,11 +5739,11 @@ static void valueFlowSubFunction(const TokenList& tokenlist, // passing value(s) to function std::list argvalues(getFunctionArgumentValues(argtok)); - // Remove non-local lifetimes - argvalues.remove_if([](const ValueFlow::Value& v) { + // Remove non-local lifetimes and moved values + argvalues.remove_if([argvar](const ValueFlow::Value& v) { if (v.isLifetimeValue()) return !v.isLocalLifetimeValue() && !v.isSubFunctionLifetimeValue(); - return false; + return v.isMovedValue() && !argvar->isReference(); }); // 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 32a09055d65..c82b09bd299 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); @@ -13353,6 +13354,30 @@ 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()); + + check("void g(const std::string& s) {}\n" + "void h(std::string& r) { x = std::move(r); }\n" + "void f(std::string s1, std::string s2) {\n" + " t1 = std::move(s1);\n" + " t2 = std::move(s2);\n" + " g(s1);\n" + " h(s2);\n" + "}\n"); + ASSERT_EQUALS("[test.cpp:2:40]: (warning) Access of moved variable 'r'. [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"