Fixed #1525 (false negative: the function can be declared as const (member declared as mutable))

This commit is contained in:
Robert Reif 2010-03-26 19:06:00 +01:00 committed by Daniel Marjamäki
parent 307000b448
commit 45865f54a8
4 changed files with 37 additions and 10 deletions

View File

@ -112,6 +112,14 @@ CheckClass::Var *CheckClass::getVarList(const Token *tok1, bool withClasses, boo
if (next->str() == "typedef") if (next->str() == "typedef")
continue; continue;
// Is it a mutable variable?
bool isMutable = false;
if (next->str() == "mutable")
{
isMutable = true;
next = next->next();
}
// Is it a variable declaration? // Is it a variable declaration?
if (Token::Match(next, "%type% %var% ;")) if (Token::Match(next, "%type% %var% ;"))
{ {
@ -174,7 +182,7 @@ CheckClass::Var *CheckClass::getVarList(const Token *tok1, bool withClasses, boo
// If the varname was set in one of the two if-block above, create a entry for this variable.. // If the varname was set in one of the two if-block above, create a entry for this variable..
if (!varname.empty() && varname != "operator") if (!varname.empty() && varname != "operator")
{ {
Var *var = new Var(varname, false, priv, varlist); Var *var = new Var(varname, false, priv, isMutable, varlist);
varlist = var; varlist = var;
} }
} }
@ -1774,7 +1782,9 @@ bool CheckClass::isMemberVar(const Var *varlist, const Token *tok)
for (const Var *var = varlist; var; var = var->next) for (const Var *var = varlist; var; var = var->next)
{ {
if (var->name == tok->str()) if (var->name == tok->str())
return true; {
return !var->isMutable;
}
} }
return false; return false;

View File

@ -113,12 +113,13 @@ private:
class Var class Var
{ {
public: public:
Var(const std::string &name_, bool init = false, bool priv = false, Var *next = 0) Var(const std::string &name_, bool init_ = false, bool priv_ = false, bool mutable_ = false, Var *next_ = 0)
: name(name_) : name(name_),
init(init_),
priv(priv_),
isMutable(mutable_),
next(next_)
{ {
this->init = init;
this->priv = priv;
this->next = next;
} }
/** @brief name of variable */ /** @brief name of variable */
@ -130,6 +131,9 @@ private:
/** @brief is this variable declared in the private section? */ /** @brief is this variable declared in the private section? */
bool priv; bool priv;
/** @brief is this variable mutable? */
bool isMutable;
/** @brief next Var item */ /** @brief next Var item */
Var *next; Var *next;
}; };

View File

@ -1215,14 +1215,14 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s
Token::createMutualLinks(tok->tokAt(2), tok->tokAt(3)); Token::createMutualLinks(tok->tokAt(2), tok->tokAt(3));
} }
// Remove "volatile", "mutable" and "inline" // Remove "volatile" and "inline"
while (Token::Match(_tokens, "volatile|mutable|inline")) while (Token::Match(_tokens, "volatile|inline"))
{ {
_tokens->deleteThis(); _tokens->deleteThis();
} }
for (Token *tok = _tokens; tok; tok = tok->next()) for (Token *tok = _tokens; tok; tok = tok->next())
{ {
while (Token::Match(tok->next(), "volatile|mutable|inline")) while (Token::Match(tok->next(), "volatile|inline"))
{ {
tok->deleteNext(); tok->deleteNext();
} }

View File

@ -98,6 +98,7 @@ private:
TEST_CASE(const9); // ticket #1515 TEST_CASE(const9); // ticket #1515
TEST_CASE(const10); // ticket #1522 TEST_CASE(const10); // ticket #1522
TEST_CASE(const11); // ticket #1529 TEST_CASE(const11); // ticket #1529
TEST_CASE(const12); // ticket #1552
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);
@ -2229,6 +2230,18 @@ private:
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
} }
void const12()
{
// ticket #1525
checkConst("class A {\n"
"public:\n"
" int foo() { x = 0; }\n"
"private:\n"
" mutable int x;\n"
"}");
ASSERT_EQUALS("[test.cpp:3]: (style) The function 'A::foo' can be const\n", errout.str());
}
// increment/decrement => not const // increment/decrement => not const
void constincdec() void constincdec()
{ {