Fixed #1344 (false negative: missing const not found)
This commit is contained in:
parent
2d5d060514
commit
9591e09dd0
|
@ -1429,6 +1429,20 @@ void CheckClass::thisSubtraction()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Token * findParameter(const Token *var, const Token *start, const Token * end)
|
||||||
|
{
|
||||||
|
const Token * param = start->next();
|
||||||
|
for (; param && param != end; param = param->next())
|
||||||
|
{
|
||||||
|
if (param->varId()) // a function parameter
|
||||||
|
{
|
||||||
|
// check if the variable and the parameter name are the same
|
||||||
|
if (var->str() == param->str())
|
||||||
|
return param;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void CheckClass::checkConst()
|
void CheckClass::checkConst()
|
||||||
{
|
{
|
||||||
|
@ -1490,6 +1504,9 @@ void CheckClass::checkConst()
|
||||||
if (!tok2)
|
if (!tok2)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
const Token *paramEnd = tok2;
|
||||||
|
const Token *paramStart = tok2->link();
|
||||||
|
|
||||||
// is this a non-const function that is implemented inline?
|
// is this a non-const function that is implemented inline?
|
||||||
if (Token::simpleMatch(tok2, ") {"))
|
if (Token::simpleMatch(tok2, ") {"))
|
||||||
{
|
{
|
||||||
|
@ -1513,6 +1530,24 @@ void CheckClass::checkConst()
|
||||||
(tok3->str().find("=") == 1 &&
|
(tok3->str().find("=") == 1 &&
|
||||||
tok3->str().find_first_of("<>") == std::string::npos))
|
tok3->str().find_first_of("<>") == std::string::npos))
|
||||||
{
|
{
|
||||||
|
if (tok3->str() == "=") // assignment.. =
|
||||||
|
{
|
||||||
|
const Token * param = findParameter(tok3->previous(), paramStart, paramEnd);
|
||||||
|
if (param)
|
||||||
|
{
|
||||||
|
// assignment to function argument reference can be const
|
||||||
|
// f(type & x) { x = something; }
|
||||||
|
if (param->tokAt(-1)->str() == "&")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// assignment to function argument pointer can be const
|
||||||
|
// f(type * x) { *x = something; }
|
||||||
|
else if ((param->tokAt(-1)->str() == "*") &&
|
||||||
|
(tok3->tokAt(-2)->str() == "*"))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
isconst = false;
|
isconst = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,6 +82,8 @@ private:
|
||||||
|
|
||||||
// can member function be made const
|
// can member function be made const
|
||||||
TEST_CASE(const1);
|
TEST_CASE(const1);
|
||||||
|
TEST_CASE(const2);
|
||||||
|
TEST_CASE(const3);
|
||||||
TEST_CASE(constoperator); // operator< can often be const
|
TEST_CASE(constoperator); // operator< can often be const
|
||||||
TEST_CASE(constincdec); // increment/decrement => non-const
|
TEST_CASE(constincdec); // increment/decrement => non-const
|
||||||
TEST_CASE(constReturnReference);
|
TEST_CASE(constReturnReference);
|
||||||
|
@ -1624,6 +1626,104 @@ private:
|
||||||
ASSERT_EQUALS("", errout.str());
|
ASSERT_EQUALS("", errout.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void const2()
|
||||||
|
{
|
||||||
|
// ticket 1344
|
||||||
|
// assignment to variable can't be const
|
||||||
|
checkConst("class Fred {\n"
|
||||||
|
" std::string s;\n"
|
||||||
|
" void foo() { s = ""; }\n"
|
||||||
|
"};\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// assignment to function argument reference can be const
|
||||||
|
checkConst("class Fred {\n"
|
||||||
|
" std::string s;\n"
|
||||||
|
" void foo(std::string & a) { a = s; }\n"
|
||||||
|
"};\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) The function 'Fred::foo' can be const\n", errout.str());
|
||||||
|
|
||||||
|
// assignment to variable can't be const
|
||||||
|
checkConst("class Fred {\n"
|
||||||
|
" std::string s;\n"
|
||||||
|
" void foo(std::string & a) { s = a; }\n"
|
||||||
|
"};\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// assignment to function argument references can be const
|
||||||
|
checkConst("class Fred {\n"
|
||||||
|
" std::string s;\n"
|
||||||
|
" void foo(std::string & a, std::string & b) { a = s; b = s; }\n"
|
||||||
|
"};\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) The function 'Fred::foo' can be const\n", errout.str());
|
||||||
|
|
||||||
|
// assignment to variable, can't be const
|
||||||
|
checkConst("class Fred {\n"
|
||||||
|
" std::string s;\n"
|
||||||
|
" void foo(std::string & a, std::string & b) { s = a; s = b; }\n"
|
||||||
|
"};\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// assignment to variable, can't be const
|
||||||
|
checkConst("class Fred {\n"
|
||||||
|
" std::string s;\n"
|
||||||
|
" void foo(std::string & a, std::string & b) { s = a; b = s; }\n"
|
||||||
|
"};\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// assignment to variable, can't be const
|
||||||
|
checkConst("class Fred {\n"
|
||||||
|
" std::string s;\n"
|
||||||
|
" void foo(std::string & a, std::string & b) { a = s; s = b; }\n"
|
||||||
|
"};\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void const3()
|
||||||
|
{
|
||||||
|
// assignment to function argument pointer can be const
|
||||||
|
checkConst("class Fred {\n"
|
||||||
|
" int s;\n"
|
||||||
|
" void foo(int * a) { *a = s; }\n"
|
||||||
|
"};\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) The function 'Fred::foo' can be const\n", errout.str());
|
||||||
|
|
||||||
|
// assignment to variable, can't be const
|
||||||
|
checkConst("class Fred {\n"
|
||||||
|
" int s;\n"
|
||||||
|
" void foo(int * a) { s = *a; }\n"
|
||||||
|
"};\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// assignment to function argument pointers can be const
|
||||||
|
checkConst("class Fred {\n"
|
||||||
|
" std::string s;\n"
|
||||||
|
" void foo(std::string * a, std::string * b) { *a = s; *b = s; }\n"
|
||||||
|
"};\n");
|
||||||
|
ASSERT_EQUALS("[test.cpp:3]: (style) The function 'Fred::foo' can be const\n", errout.str());
|
||||||
|
|
||||||
|
// assignment to variable, can't be const
|
||||||
|
checkConst("class Fred {\n"
|
||||||
|
" std::string s;\n"
|
||||||
|
" void foo(std::string * a, std::string * b) { s = *a; s = *b; }\n"
|
||||||
|
"};\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// assignment to variable, can't be const
|
||||||
|
checkConst("class Fred {\n"
|
||||||
|
" std::string s;\n"
|
||||||
|
" void foo(std::string * a, std::string * b) { s = *a; *b = s; }\n"
|
||||||
|
"};\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
|
||||||
|
// assignment to variable, can't be const
|
||||||
|
checkConst("class Fred {\n"
|
||||||
|
" std::string s;\n"
|
||||||
|
" void foo(std::string * a, std::string * b) { *a = s; s = b; }\n"
|
||||||
|
"};\n");
|
||||||
|
ASSERT_EQUALS("", errout.str());
|
||||||
|
}
|
||||||
|
|
||||||
// operator< can often be const
|
// operator< can often be const
|
||||||
void constoperator()
|
void constoperator()
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue