Fixed #1344 (false negative: missing const not found)

This commit is contained in:
Robert Reif 2010-02-08 07:25:19 +01:00 committed by Daniel Marjamäki
parent 2d5d060514
commit 9591e09dd0
2 changed files with 135 additions and 0 deletions

View File

@ -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()
{
@ -1490,6 +1504,9 @@ void CheckClass::checkConst()
if (!tok2)
break;
const Token *paramEnd = tok2;
const Token *paramStart = tok2->link();
// is this a non-const function that is implemented inline?
if (Token::simpleMatch(tok2, ") {"))
{
@ -1513,6 +1530,24 @@ void CheckClass::checkConst()
(tok3->str().find("=") == 1 &&
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;
break;
}

View File

@ -82,6 +82,8 @@ private:
// can member function be made const
TEST_CASE(const1);
TEST_CASE(const2);
TEST_CASE(const3);
TEST_CASE(constoperator); // operator< can often be const
TEST_CASE(constincdec); // increment/decrement => non-const
TEST_CASE(constReturnReference);
@ -1624,6 +1626,104 @@ private:
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
void constoperator()
{