From 45865f54a899e6194ab2b7435f6ff951071b6c27 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Fri, 26 Mar 2010 19:06:00 +0100 Subject: [PATCH] Fixed #1525 (false negative: the function can be declared as const (member declared as mutable)) --- lib/checkclass.cpp | 14 ++++++++++++-- lib/checkclass.h | 14 +++++++++----- lib/tokenize.cpp | 6 +++--- test/testclass.cpp | 13 +++++++++++++ 4 files changed, 37 insertions(+), 10 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index c4654b107..993056d4b 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -112,6 +112,14 @@ CheckClass::Var *CheckClass::getVarList(const Token *tok1, bool withClasses, boo if (next->str() == "typedef") continue; + // Is it a mutable variable? + bool isMutable = false; + if (next->str() == "mutable") + { + isMutable = true; + next = next->next(); + } + // Is it a variable declaration? 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 (!varname.empty() && varname != "operator") { - Var *var = new Var(varname, false, priv, varlist); + Var *var = new Var(varname, false, priv, isMutable, varlist); varlist = var; } } @@ -1774,7 +1782,9 @@ bool CheckClass::isMemberVar(const Var *varlist, const Token *tok) for (const Var *var = varlist; var; var = var->next) { if (var->name == tok->str()) - return true; + { + return !var->isMutable; + } } return false; diff --git a/lib/checkclass.h b/lib/checkclass.h index d3908bcd1..2cb578685 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -113,12 +113,13 @@ private: class Var { public: - Var(const std::string &name_, bool init = false, bool priv = false, Var *next = 0) - : name(name_) + Var(const std::string &name_, bool init_ = false, bool priv_ = false, bool mutable_ = false, Var *next_ = 0) + : name(name_), + init(init_), + priv(priv_), + isMutable(mutable_), + next(next_) { - this->init = init; - this->priv = priv; - this->next = next; } /** @brief name of variable */ @@ -130,6 +131,9 @@ private: /** @brief is this variable declared in the private section? */ bool priv; + /** @brief is this variable mutable? */ + bool isMutable; + /** @brief next Var item */ Var *next; }; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 21a7496bb..282ff984a 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1215,14 +1215,14 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s Token::createMutualLinks(tok->tokAt(2), tok->tokAt(3)); } - // Remove "volatile", "mutable" and "inline" - while (Token::Match(_tokens, "volatile|mutable|inline")) + // Remove "volatile" and "inline" + while (Token::Match(_tokens, "volatile|inline")) { _tokens->deleteThis(); } 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(); } diff --git a/test/testclass.cpp b/test/testclass.cpp index a0deef392..36738f8eb 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -98,6 +98,7 @@ private: TEST_CASE(const9); // ticket #1515 TEST_CASE(const10); // ticket #1522 TEST_CASE(const11); // ticket #1529 + TEST_CASE(const12); // ticket #1552 TEST_CASE(constoperator); // operator< can often be const TEST_CASE(constincdec); // increment/decrement => non-const TEST_CASE(constReturnReference); @@ -2229,6 +2230,18 @@ private: 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 void constincdec() {