Skip to content

Commit ff9ac4b

Browse files
Fix #12773 FP accessMoved using try_emplace() together with std::move() (#8421)
1 parent 8396413 commit ff9ac4b

2 files changed

Lines changed: 29 additions & 1 deletion

File tree

lib/valueflow.cpp

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3223,6 +3223,14 @@ static Token* findEndOfFunctionCallForParameter(Token* parameterToken)
32233223
return nextAfterAstRightmostLeaf(parent);
32243224
}
32253225

3226+
static bool isTryEmplace(const Token* tok)
3227+
{
3228+
if (tok->str() != "(" || !Token::simpleMatch(tok->astOperand1(), ".") || !tok->astOperand1()->astOperand1() || !Token::simpleMatch(tok->astOperand1()->astOperand2(), "try_emplace"))
3229+
return false;
3230+
const ValueType* vt = tok->astOperand1()->astOperand1()->valueType();
3231+
return vt && vt->container && vt->container->stdAssociativeLike;
3232+
}
3233+
32263234
static void valueFlowAfterMove(const TokenList& tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger& errorLogger, const Settings& settings)
32273235
{
32283236
if (!tokenlist.isCPP() || settings.standards.cpp < Standards::CPP11)
@@ -3265,9 +3273,17 @@ static void valueFlowAfterMove(const TokenList& tokenlist, const SymbolDatabase&
32653273
const nonneg int varId = varTok->varId();
32663274
// x is not MOVED after assignment if code is: x = ... std::move(x) .. ;
32673275
const Token *parent = tok->astParent();
3276+
bool bail = false;
32683277
while (parent && parent->str() != "=" && parent->str() != "return" &&
3269-
!(parent->str() == "(" && isOpenParenthesisMemberFunctionCallOfVarId(parent, varId)))
3278+
!(parent->str() == "(" && isOpenParenthesisMemberFunctionCallOfVarId(parent, varId))) {
3279+
if (isTryEmplace(parent)) {
3280+
bail = true;
3281+
break;
3282+
}
32703283
parent = parent->astParent();
3284+
}
3285+
if (bail)
3286+
continue;
32713287
if (parent &&
32723288
(parent->str() == "return" || // MOVED in return statement
32733289
parent->str() == "(")) // MOVED in self assignment, isOpenParenthesisMemberFunctionCallOfVarId == true

test/testother.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ class TestOther : public TestFixture {
305305
TEST_CASE(moveTernary);
306306
TEST_CASE(movePointerAlias);
307307
TEST_CASE(moveOutparam);
308+
TEST_CASE(moveTryEmplace);
308309

309310
TEST_CASE(funcArgNamesDifferent);
310311
TEST_CASE(funcArgOrderDifferent);
@@ -12752,6 +12753,17 @@ class TestOther : public TestFixture {
1275212753
ASSERT_EQUALS("", errout_str());
1275312754
}
1275412755

12756+
void moveTryEmplace()
12757+
{
12758+
check("void f(std::map<std::string, std::string>& m, std::string& s) {\n" // #12773
12759+
" bool b = m.try_emplace(\"a\", std::move(s)).second;\n"
12760+
" if (!b) {\n"
12761+
" std::cout << s;\n"
12762+
" }\n"
12763+
"}\n");
12764+
ASSERT_EQUALS("", errout_str());
12765+
}
12766+
1275512767
void funcArgNamesDifferent() {
1275612768
check("void func1(int a, int b, int c);\n"
1275712769
"void func1(int a, int b, int c) { }\n"

0 commit comments

Comments
 (0)