Skip to content

Commit 12e58c8

Browse files
lordylikedanmar
authored andcommitted
fix ticket 8570: passedByValue with member initializer list and std::move (danmar#1316)
* fix ticket 8570 allow member initializer list variables that are moved to be non-const * review feedback * replace tabs with spaces in test code
1 parent 77b653b commit 12e58c8

2 files changed

Lines changed: 87 additions & 0 deletions

File tree

lib/checkother.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,6 +1354,21 @@ static std::size_t estimateSize(const Type* type, const Settings* settings, cons
13541354

13551355
static bool canBeConst(const Variable *var)
13561356
{
1357+
{ // check initializer list. If variable is moved from it can't be const.
1358+
const Function* func_scope = var->scope()->function;
1359+
if (func_scope->type == Function::Type::eConstructor) {
1360+
//could be initialized in initializer list
1361+
if (func_scope->arg->link()->next()->str() == ":") {
1362+
for (const Token* tok2 = func_scope->arg->link()->next()->next(); tok2 != var->scope()->bodyStart; tok2 = tok2->next()) {
1363+
if (tok2->varId() != var->declarationId())
1364+
continue;
1365+
const Token* parent = tok2->astParent();
1366+
if (parent && Token::simpleMatch(parent->previous(), "move ("))
1367+
return false;
1368+
}
1369+
}
1370+
}
1371+
}
13571372
for (const Token* tok2 = var->scope()->bodyStart; tok2 != var->scope()->bodyEnd; tok2 = tok2->next()) {
13581373
if (tok2->varId() != var->declarationId())
13591374
continue;

test/testother.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,7 @@ class TestOther : public TestFixture {
165165
TEST_CASE(checkCastIntToCharAndBack); // ticket #160
166166

167167
TEST_CASE(checkCommaSeparatedReturn);
168+
TEST_CASE(checkPassByReference);
168169

169170
TEST_CASE(checkComparisonFunctionIsAlwaysTrueOrFalse);
170171

@@ -6024,6 +6025,77 @@ class TestOther : public TestFixture {
60246025
ASSERT_EQUALS("", errout.str());
60256026
}
60266027

6028+
void checkPassByReference() {
6029+
// #8570 passByValue when std::move is used
6030+
check("struct A\n"
6031+
"{\n"
6032+
" std::vector<int> x;\n"
6033+
"};\n"
6034+
"\n"
6035+
"struct B\n"
6036+
"{\n"
6037+
" explicit B(A a) : a(std::move(a)) {}\n"
6038+
" void Init(A _a) { a = std::move(_a); }\n"
6039+
" A a;"
6040+
"};", nullptr, false, false, true);
6041+
ASSERT_EQUALS("", errout.str());
6042+
6043+
check("struct A\n"
6044+
"{\n"
6045+
" std::vector<int> x;\n"
6046+
"};\n"
6047+
"\n"
6048+
"struct B\n"
6049+
"{\n"
6050+
" explicit B(A a) : a{std::move(a)} {}\n"
6051+
" void Init(A _a) { a = std::move(_a); }\n"
6052+
" A a;"
6053+
"};", nullptr, false, false, true);
6054+
ASSERT_EQUALS("", errout.str());
6055+
6056+
check("struct A\n"
6057+
"{\n"
6058+
" std::vector<int> x;\n"
6059+
"};\n"
6060+
"\n"
6061+
"struct B\n"
6062+
"{\n"
6063+
" B(A a, A a2) : a{std::move(a)}, a2{std::move(a2)} {}\n"
6064+
" void Init(A _a) { a = std::move(_a); }\n"
6065+
" A a;"
6066+
" A a2;"
6067+
"};", nullptr, false, false, true);
6068+
ASSERT_EQUALS("", errout.str());
6069+
6070+
check("struct A\n"
6071+
"{\n"
6072+
" std::vector<int> x;\n"
6073+
"};\n"
6074+
"\n"
6075+
"struct B\n"
6076+
"{\n"
6077+
" B(A a, A a2) : a{std::move(a)}, a2{a2} {}\n"
6078+
" void Init(A _a) { a = std::move(_a); }\n"
6079+
" A a;"
6080+
" A a2;"
6081+
"};", nullptr, false, false, true);
6082+
ASSERT_EQUALS("[test.cpp:8]: (performance) Function parameter 'a2' should be passed by const reference.\n", errout.str());
6083+
6084+
check("struct A\n"
6085+
"{\n"
6086+
" std::vector<int> x;\n"
6087+
"};\n"
6088+
"\n"
6089+
"struct B\n"
6090+
"{\n"
6091+
" B(A a, A a2) : a{std::move(a)}, a2(a2) {}\n"
6092+
" void Init(A _a) { a = std::move(_a); }\n"
6093+
" A a;"
6094+
" A a2;"
6095+
"};", nullptr, false, false, true);
6096+
ASSERT_EQUALS("[test.cpp:8]: (performance) Function parameter 'a2' should be passed by const reference.\n", errout.str());
6097+
}
6098+
60276099
void checkComparisonFunctionIsAlwaysTrueOrFalse() {
60286100
// positive test
60296101
check("bool f(int x){\n"

0 commit comments

Comments
 (0)