Improve Fix #6180 (Do not warn about move if it is part of a reassignment of the variable)
This commit is contained in:
parent
f8cfa72159
commit
f4ab45f13b
|
@ -1736,6 +1736,12 @@ static bool isStdMoveOrStdForwarded(Token * tok, ValueFlow::Value::MoveKind * mo
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool isOpenParenthesisMemberFunctionCallOfVarId(const Token * openParenthesisToken, unsigned int varId)
|
||||||
|
{
|
||||||
|
return Token::Match(openParenthesisToken->tokAt(-3),"%varid% . %name% (", varId) &&
|
||||||
|
openParenthesisToken->tokAt(-2)->originalName() == emptyString;
|
||||||
|
}
|
||||||
|
|
||||||
static void valueFlowAfterMove(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
|
static void valueFlowAfterMove(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
|
||||||
{
|
{
|
||||||
if (!tokenlist->isCPP() || settings->standards.cpp < Standards::CPP11)
|
if (!tokenlist->isCPP() || settings->standards.cpp < Standards::CPP11)
|
||||||
|
@ -1757,15 +1763,18 @@ static void valueFlowAfterMove(TokenList *tokenlist, SymbolDatabase* symboldatab
|
||||||
ValueFlow::Value::MoveKind moveKind;
|
ValueFlow::Value::MoveKind moveKind;
|
||||||
if (!isStdMoveOrStdForwarded(tok, &moveKind, &varTok))
|
if (!isStdMoveOrStdForwarded(tok, &moveKind, &varTok))
|
||||||
continue;
|
continue;
|
||||||
|
const unsigned int varId = varTok->varId();
|
||||||
// x is not MOVED after assignment if code is: x = ... std::move(x) .. ;
|
// x is not MOVED after assignment if code is: x = ... std::move(x) .. ;
|
||||||
const Token *parent = tok->astParent();
|
const Token *parent = tok->astParent();
|
||||||
while (parent && parent->str() != "=" && parent->str() != "return")
|
while (parent && parent->str() != "=" && parent->str() != "return" &&
|
||||||
|
!(parent->str() == "(" && isOpenParenthesisMemberFunctionCallOfVarId(parent, varId)))
|
||||||
parent = parent->astParent();
|
parent = parent->astParent();
|
||||||
if (parent && parent->str() == "return") // MOVED in return statement
|
if (parent &&
|
||||||
|
(parent->str() == "return" || // MOVED in return statement
|
||||||
|
parent->str() == "(")) // MOVED in self assignment, isOpenParenthesisMemberFunctionCallOfVarId == true
|
||||||
continue;
|
continue;
|
||||||
if (parent && parent->astOperand1()->str() == varTok->str())
|
if (parent && parent->astOperand1()->varId() == varId)
|
||||||
continue;
|
continue;
|
||||||
const unsigned int varid = varTok->varId();
|
|
||||||
const Variable *var = varTok->variable();
|
const Variable *var = varTok->variable();
|
||||||
if (!var)
|
if (!var)
|
||||||
continue;
|
continue;
|
||||||
|
@ -1778,7 +1787,7 @@ static void valueFlowAfterMove(TokenList *tokenlist, SymbolDatabase* symboldatab
|
||||||
std::list<ValueFlow::Value> values;
|
std::list<ValueFlow::Value> values;
|
||||||
values.push_back(value);
|
values.push_back(value);
|
||||||
|
|
||||||
valueFlowForward(varTok->next(), endOfVarScope, var, varid, values, false, tokenlist, errorLogger, settings);
|
valueFlowForward(varTok->next(), endOfVarScope, var, varId, values, false, tokenlist, errorLogger, settings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -179,6 +179,9 @@ private:
|
||||||
TEST_CASE(moveAndAssign1);
|
TEST_CASE(moveAndAssign1);
|
||||||
TEST_CASE(moveAndAssign2);
|
TEST_CASE(moveAndAssign2);
|
||||||
TEST_CASE(moveAssignMoveAssign);
|
TEST_CASE(moveAssignMoveAssign);
|
||||||
|
TEST_CASE(moveAndReset1);
|
||||||
|
TEST_CASE(moveAndReset2);
|
||||||
|
TEST_CASE(moveResetMoveReset);
|
||||||
TEST_CASE(moveAndFunctionParameter);
|
TEST_CASE(moveAndFunctionParameter);
|
||||||
TEST_CASE(moveAndFunctionParameterReference);
|
TEST_CASE(moveAndFunctionParameterReference);
|
||||||
TEST_CASE(moveAndFunctionParameterConstReference);
|
TEST_CASE(moveAndFunctionParameterConstReference);
|
||||||
|
@ -6189,6 +6192,50 @@ private:
|
||||||
"[test.cpp:8]: (warning) Access of moved variable a.\n", errout.str());
|
"[test.cpp:8]: (warning) Access of moved variable a.\n", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void moveAndReset1() {
|
||||||
|
check("A g(A a);\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" A a;\n"
|
||||||
|
" a.reset(g(std::move(a)));\n"
|
||||||
|
" a.reset(g(std::move(a)));\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void moveAndReset2() {
|
||||||
|
check("A g(A a);\n"
|
||||||
|
"void f() {\n"
|
||||||
|
" A a;\n"
|
||||||
|
" A b;\n"
|
||||||
|
" A c;\n"
|
||||||
|
" b.reset(g(std::move(a)));\n"
|
||||||
|
" c.reset(g(std::move(a)));\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:7]: (warning) Access of moved variable a.\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void moveResetMoveReset() {
|
||||||
|
check("void h(A a);\n"
|
||||||
|
"void f() {"
|
||||||
|
" A a;\n"
|
||||||
|
" g(std::move(a));\n"
|
||||||
|
" h(a);\n"
|
||||||
|
" a.reset(b);\n"
|
||||||
|
" h(a);\n"
|
||||||
|
" g(std::move(a));\n"
|
||||||
|
" h(a);\n"
|
||||||
|
" a.reset(b);\n"
|
||||||
|
" h(a);\n"
|
||||||
|
"}");
|
||||||
|
ASSERT_EQUALS("[test.cpp:4]: (warning) Access of moved variable a.\n"
|
||||||
|
"[test.cpp:5]: (warning, inconclusive) Access of moved variable a.\n"
|
||||||
|
"[test.cpp:6]: (warning, inconclusive) Access of moved variable a.\n"
|
||||||
|
"[test.cpp:7]: (warning, inconclusive) Access of moved variable a.\n"
|
||||||
|
"[test.cpp:8]: (warning) Access of moved variable a.\n"
|
||||||
|
"[test.cpp:9]: (warning, inconclusive) Access of moved variable a.\n"
|
||||||
|
"[test.cpp:10]: (warning, inconclusive) Access of moved variable a.\n", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
void moveAndFunctionParameter() {
|
void moveAndFunctionParameter() {
|
||||||
check("void g(A a);\n"
|
check("void g(A a);\n"
|
||||||
"void f() {\n"
|
"void f() {\n"
|
||||||
|
|
Loading…
Reference in New Issue