make member variable change detection simpler and more accurate for CheckClass::checkConst
This commit is contained in:
parent
20853fe273
commit
1e1434e191
|
@ -1357,25 +1357,34 @@ void CheckClass::checkConst()
|
|||
|
||||
bool CheckClass::isMemberVar(const Scope *scope, const Token *tok)
|
||||
{
|
||||
const Token *tok1 = tok;
|
||||
bool again = false;
|
||||
|
||||
while (tok->previous() && !Token::Match(tok->previous(), "}|{|;(||public:|protected:|private:|return|:|?"))
|
||||
// try to find the member variable
|
||||
do
|
||||
{
|
||||
if (Token::simpleMatch(tok->previous(), "* this"))
|
||||
again = false;
|
||||
|
||||
if (tok->str() == "this")
|
||||
{
|
||||
return true;
|
||||
|
||||
tok = tok->previous();
|
||||
}
|
||||
else if (Token::Match(tok->tokAt(-2), "%var% . %var%"))
|
||||
{
|
||||
tok = tok->tokAt(-2);
|
||||
again = true;
|
||||
}
|
||||
else if (Token::Match(tok->tokAt(-2), "] . %var%"))
|
||||
{
|
||||
tok = tok->tokAt(-2)->link()->previous();
|
||||
again = true;
|
||||
}
|
||||
else if (tok->str() == "]")
|
||||
{
|
||||
tok = tok->link()->previous();
|
||||
again = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (tok->str() == "this")
|
||||
return true;
|
||||
|
||||
if (Token::Match(tok, "( * %var% ) [") || (Token::Match(tok, "( * %var% ) <<") && tok1->next()->str() == "<<"))
|
||||
tok = tok->tokAt(2);
|
||||
|
||||
// ignore class namespace
|
||||
if (tok->str() == scope->className && tok->next()->str() == "::")
|
||||
tok = tok->tokAt(2);
|
||||
while (again);
|
||||
|
||||
std::list<Variable>::const_iterator var;
|
||||
for (var = scope->varlist.begin(); var != scope->varlist.end(); ++var)
|
||||
|
@ -1492,7 +1501,7 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Token *tok)
|
|||
(tok1->str().find("=") == 1 &&
|
||||
tok1->str().find_first_of("<!>") == std::string::npos))
|
||||
{
|
||||
if (tok1->previous()->varId() == 0 && !scope->derivedFrom.empty())
|
||||
if (tok1->next()->str() == "this")
|
||||
{
|
||||
isconst = false;
|
||||
break;
|
||||
|
@ -1502,26 +1511,6 @@ bool CheckClass::checkConstFunc(const Scope *scope, const Token *tok)
|
|||
isconst = false;
|
||||
break;
|
||||
}
|
||||
else if (tok1->previous()->str() == "]")
|
||||
{
|
||||
if (isMemberVar(scope, tok1->previous()->link()->previous()))
|
||||
{
|
||||
isconst = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (tok1->next()->str() == "this")
|
||||
{
|
||||
isconst = false;
|
||||
break;
|
||||
}
|
||||
|
||||
// FIXME: I assume that a member union/struct variable is assigned.
|
||||
else if (Token::Match(tok1->tokAt(-2), ". %var%"))
|
||||
{
|
||||
isconst = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// streaming: <<
|
||||
|
|
|
@ -176,7 +176,8 @@ private:
|
|||
TEST_CASE(constoperator3);
|
||||
TEST_CASE(constoperator4);
|
||||
TEST_CASE(constincdec); // increment/decrement => non-const
|
||||
TEST_CASE(constassign);
|
||||
TEST_CASE(constassign1);
|
||||
TEST_CASE(constassign2);
|
||||
TEST_CASE(constincdecarray); // increment/decrement array element => non-const
|
||||
TEST_CASE(constassignarray);
|
||||
TEST_CASE(constReturnReference);
|
||||
|
@ -5403,7 +5404,7 @@ private:
|
|||
ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
|
||||
}
|
||||
|
||||
void constassign()
|
||||
void constassign1()
|
||||
{
|
||||
checkConst("class Fred {\n"
|
||||
" int a;\n"
|
||||
|
@ -5466,6 +5467,98 @@ private:
|
|||
ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
|
||||
}
|
||||
|
||||
void constassign2()
|
||||
{
|
||||
checkConst("class Fred {\n"
|
||||
" struct A { int a; } s;\n"
|
||||
" void nextA() { return s.a=1; }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
checkConst("class Fred {\n"
|
||||
" struct A { int a; } s;\n"
|
||||
" void nextA() { return s.a-=1; }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
checkConst("class Fred {\n"
|
||||
" struct A { int a; } s;\n"
|
||||
" void nextA() { return s.a+=1; }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
checkConst("class Fred {\n"
|
||||
" struct A { int a; } s;\n"
|
||||
" void nextA() { return s.a*=-1; }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
checkConst("struct A { int a; } s;\n"
|
||||
"class Fred {\n"
|
||||
" void nextA() { return s.a=1; }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
|
||||
|
||||
checkConst("struct A { int a; } s;\n"
|
||||
"class Fred {\n"
|
||||
" void nextA() { return s.a-=1; }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
|
||||
|
||||
checkConst("struct A { int a; } s;\n"
|
||||
"class Fred {\n"
|
||||
" void nextA() { return s.a+=1; }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
|
||||
|
||||
checkConst("struct A { int a; } s;\n"
|
||||
"class Fred {\n"
|
||||
" void nextA() { return s.a*=-1; }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
|
||||
|
||||
checkConst("struct A { int a; } s;\n"
|
||||
"class Fred {\n"
|
||||
" void nextA() { return s.a/=-2; }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (information) Technically the member function 'Fred::nextA' can be const.\n", errout.str());
|
||||
|
||||
checkConst("struct A { int a; };\n"
|
||||
"class Fred {\n"
|
||||
" A s;\n"
|
||||
" void nextA() { return s.a=1; }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
checkConst("struct A { int a; };\n"
|
||||
"class Fred {\n"
|
||||
" A s;\n"
|
||||
" void nextA() { return s.a-=1; }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
checkConst("struct A { int a; };\n"
|
||||
"class Fred {\n"
|
||||
" A s;\n"
|
||||
" void nextA() { return s.a+=1; }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
checkConst("struct A { int a; };\n"
|
||||
"class Fred {\n"
|
||||
" A s;\n"
|
||||
" void nextA() { return s.a*=-1; }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
checkConst("struct A { int a; };\n"
|
||||
"class Fred {\n"
|
||||
" A s;\n"
|
||||
" void nextA() { return s.a/=-2; }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
// increment/decrement array element => not const
|
||||
void constincdecarray()
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue