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()
|
||||
{
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue