9356: Prevent false positive when passing non-const reference to member constructor (#2370)

* Add cases for 9356

* 9356: Prevent false positive when passing non-const reference to member constructor

This workarounds false positives 'Parameter  can be declared with const [constParameter]'
when said parameter is used in constructor call. It assume the
constructor call might change the parameter (without any checks.
The drawback is that we have false negative, in cases where we could
check the constructor actually takes a const reference, or a copied by
value parameter.

* Add todo comment in isVariableMutableInInitializer
This commit is contained in:
Ken-Patrick Lehrmann 2020-01-04 11:36:45 +01:00 committed by Daniel Marjamäki
parent e07801a891
commit eca7ee9260
2 changed files with 88 additions and 0 deletions

View File

@ -1299,6 +1299,10 @@ static bool isVariableMutableInInitializer(const Token* start, const Token * end
const Token * memberTok = tok->astParent()->previous();
if (Token::Match(memberTok, "%var% (") && memberTok->variable()) {
const Variable * memberVar = memberTok->variable();
if(memberVar->isClass())
//TODO: check if the called constructor could live with a const variable
// pending that, assume the worst (that it can't)
return true;
if (!memberVar->isReference())
continue;
if (memberVar->isConst())

View File

@ -2107,6 +2107,90 @@ private:
"void an();\n"
"void h();\n");
ASSERT_EQUALS("", errout.str());
check("class C\n"
"{\n"
"public:\n"
" explicit C(int&);\n"
"};\n"
"\n"
"class D\n"
"{\n"
"public:\n"
" explicit D(int&);\n"
"\n"
"private:\n"
" C c;\n"
"};\n"
"\n"
"D::D(int& i)\n"
" : c(i)\n"
"{\n"
"}\n");
ASSERT_EQUALS("", errout.str());
check("class C\n"
"{\n"
"public:\n"
" explicit C(const int&);\n"
"};\n"
"\n"
"class D\n"
"{\n"
"public:\n"
" explicit D(int&);\n"
"\n"
"private:\n"
" C c;\n"
"};\n"
"\n"
"D::D(int& i)\n"
" : c(i)\n"
"{\n"
"}\n");
TODO_ASSERT_EQUALS("[test.cpp:16]: (style) Parameter 'i' can be declared with const\n", "", errout.str());
check("class C\n"
"{\n"
"public:\n"
" explicit C(int);\n"
"};\n"
"\n"
"class D\n"
"{\n"
"public:\n"
" explicit D(int&);\n"
"\n"
"private:\n"
" C c;\n"
"};\n"
"\n"
"D::D(int& i)\n"
" : c(i)\n"
"{\n"
"}\n");
TODO_ASSERT_EQUALS("[test.cpp:16]: (style) Parameter 'i' can be declared with const\n", "", errout.str());
check("class C\n"
"{\n"
"public:\n"
" explicit C(int, int);\n"
"};\n"
"\n"
"class D\n"
"{\n"
"public:\n"
" explicit D(int&);\n"
"\n"
"private:\n"
" C c;\n"
"};\n"
"\n"
"D::D(int& i)\n"
" : c(0, i)\n"
"{\n"
"}\n");
TODO_ASSERT_EQUALS("[test.cpp:16]: (style) Parameter 'i' can be declared with const\n", "", errout.str());
}
void switchRedundantAssignmentTest() {