Skip to content

Commit cb5a5e6

Browse files
zingsheimdanmar
authored andcommitted
Improve Fix #6180 (Access of moved variable still allowed until function is called)
1 parent 9a871d3 commit cb5a5e6

4 files changed

Lines changed: 48 additions & 20 deletions

File tree

lib/token.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -779,7 +779,7 @@ class CPPCHECKLIB Token {
779779
const ValueFlow::Value * getMovedValue() const {
780780
std::list<ValueFlow::Value>::const_iterator it;
781781
for (it = values.begin(); it != values.end(); ++it) {
782-
if (it->isMovedValue())
782+
if (it->isMovedValue() && it->moveKind != ValueFlow::Value::NonMovedVariable)
783783
return &(*it);
784784
}
785785
return nullptr;

lib/valueflow.cpp

Lines changed: 38 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1742,6 +1742,40 @@ static bool isOpenParenthesisMemberFunctionCallOfVarId(const Token * openParenth
17421742
openParenthesisToken->tokAt(-2)->originalName() == emptyString;
17431743
}
17441744

1745+
static const Token * nextAfterAstRightmostLeaf(Token const * tok)
1746+
{
1747+
const Token * rightmostLeaf = tok;
1748+
if (!rightmostLeaf || !rightmostLeaf->astOperand1())
1749+
return nullptr;
1750+
do {
1751+
if (rightmostLeaf->astOperand2())
1752+
rightmostLeaf = rightmostLeaf->astOperand2();
1753+
else
1754+
rightmostLeaf = rightmostLeaf->astOperand1();
1755+
} while (rightmostLeaf->astOperand1());
1756+
return rightmostLeaf->next();
1757+
}
1758+
1759+
static const Token * findOpenParentesisOfMove(const Token * moveVarTok)
1760+
{
1761+
const Token * tok = moveVarTok;
1762+
while (tok && tok->str() != "(")
1763+
tok = tok->previous();
1764+
return tok;
1765+
}
1766+
1767+
static const Token * findEndOfFunctionCallForParameter(const Token * parameterToken)
1768+
{
1769+
if (!parameterToken)
1770+
return nullptr;
1771+
const Token * parent = parameterToken->astParent();
1772+
while(parent && !parent->isOp() && parent->str() != "(")
1773+
parent = parent->astParent();
1774+
if (!parent)
1775+
return nullptr;
1776+
return nextAfterAstRightmostLeaf(parent);
1777+
}
1778+
17451779
static void valueFlowAfterMove(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
17461780
{
17471781
if (!tokenlist->isCPP() || settings->standards.cpp < Standards::CPP11)
@@ -1804,26 +1838,14 @@ static void valueFlowAfterMove(TokenList *tokenlist, SymbolDatabase* symboldatab
18041838
value.setKnown();
18051839
std::list<ValueFlow::Value> values;
18061840
values.push_back(value);
1807-
1808-
valueFlowForward(varTok->next(), endOfVarScope, var, varId, values, false, tokenlist, errorLogger, settings);
1841+
const Token * openParentesisOfMove = findOpenParentesisOfMove(varTok);
1842+
const Token * endOfFunctionCall = findEndOfFunctionCallForParameter(openParentesisOfMove);
1843+
if (endOfFunctionCall)
1844+
valueFlowForward(const_cast<Token *>(endOfFunctionCall), endOfVarScope, var, varId, values, false, tokenlist, errorLogger, settings);
18091845
}
18101846
}
18111847
}
18121848

1813-
static const Token * nextAfterAstRightmostLeaf(Token const * tok)
1814-
{
1815-
const Token * rightmostLeaf = tok;
1816-
if (!rightmostLeaf || !rightmostLeaf->astOperand1())
1817-
return nullptr;
1818-
do {
1819-
if (rightmostLeaf->astOperand2())
1820-
rightmostLeaf = rightmostLeaf->astOperand2();
1821-
else
1822-
rightmostLeaf = rightmostLeaf->astOperand1();
1823-
} while (rightmostLeaf->astOperand1());
1824-
return rightmostLeaf->next();
1825-
}
1826-
18271849
static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldatabase, ErrorLogger *errorLogger, const Settings *settings)
18281850
{
18291851
const std::size_t functions = symboldatabase->functionScopes.size();

lib/valueflow.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ class Settings;
3333
namespace ValueFlow {
3434
class CPPCHECKLIB Value {
3535
public:
36-
explicit Value(long long val = 0) : valueType(INT), intvalue(val), tokvalue(nullptr), floatValue(0.0), moveKind(MovedVariable), varvalue(val), condition(0), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {}
37-
Value(const Token *c, long long val) : valueType(INT), intvalue(val), tokvalue(nullptr), floatValue(0.0), moveKind(MovedVariable), varvalue(val), condition(c), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {}
36+
explicit Value(long long val = 0) : valueType(INT), intvalue(val), tokvalue(nullptr), floatValue(0.0), moveKind(NonMovedVariable), varvalue(val), condition(0), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {}
37+
Value(const Token *c, long long val) : valueType(INT), intvalue(val), tokvalue(nullptr), floatValue(0.0), moveKind(NonMovedVariable), varvalue(val), condition(c), varId(0U), conditional(false), inconclusive(false), defaultArg(false), valueKind(ValueKind::Possible) {}
3838

3939
bool operator==(const Value &rhs) const {
4040
if (valueType != rhs.valueType)

test/testvalueflow.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,13 @@ class TestValueFlow : public TestFixture {
338338
"}";
339339
ASSERT_EQUALS(true, testValueOfX(code, 4U, ValueFlow::Value::MovedVariable));
340340

341+
code = "void f(int i) {\n"
342+
" X x;\n"
343+
" y = g(std::move(x), \n"
344+
" x.size());\n"
345+
"}";
346+
ASSERT_EQUALS(false, testValueOfX(code, 4U, ValueFlow::Value::MovedVariable));
347+
341348
code = "void f(int i) {\n"
342349
" X x;\n"
343350
" x = g(std::move(x));\n"
@@ -352,7 +359,6 @@ class TestValueFlow : public TestFixture {
352359
" return h(std::move(x));\n"
353360
"}";
354361
ASSERT_EQUALS(false, testValueOfX(code, 5U, ValueFlow::Value::MovedVariable));
355-
356362
}
357363

358364
void valueFlowCalculations() {

0 commit comments

Comments
 (0)