From 2dc4222c9ad313dab1e960cf40bb22c79e1b42cf Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Sun, 28 Mar 2010 11:46:42 +0200 Subject: [PATCH] Refactoring: Added CheckClass::isMemberFunc --- lib/checkclass.cpp | 119 ++++++++++++++++++++++++++++++++------------- lib/checkclass.h | 1 + test/testclass.cpp | 23 +++++++++ 3 files changed, 109 insertions(+), 34 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index 1462e9300..7fc78bccb 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -1578,40 +1578,7 @@ void CheckClass::checkConst() continue; // member function? - if (Token::Match(tok2, "%type% %var% (") || - Token::Match(tok2, "%type% %type% %var% (") || - Token::Match(tok2, "%type% < %type% > %var% (") || - Token::Match(tok2, "%type% < %type% , %type% > %var% (") || - Token::Match(tok2, "%type% :: %type% %var% (") || - Token::Match(tok2, "%type% :: %type% < %type% > %var% (") || - Token::Match(tok2, "%type% :: %type% < %type% , %type% > %var% (") || - Token::Match(tok2, "%type% :: %type% < %type% :: %type% < %type% > , %type% > %var% (") || - Token::Match(tok2, "%type% < %type% < %type% > , %type% > %var% (") || - Token::Match(tok2, "%type% :: %type% < %type% , %type% :: %type% < %type% > > %var% (") || - Token::Match(tok2, "%type% < %type% , %type% < %type% > > %var% (") || - Token::Match(tok2, "%type% :: %type% < %type% :: %type% < %type% > , %type% :: %type% < %type% > > %var% (") || - Token::Match(tok2, "%type% < %type% < %type% > , %type% < %type% > > %var% (") || - Token::Match(tok2, "%type% :: %type% < %type% :: %type% < %type% , %type% > , %type% > %var% (") || - Token::Match(tok2, "%type% < %type% < %type% , %type% > , %type% > %var% (") || - Token::Match(tok2, "%type% :: %type% < %type% , %type% :: %type% < %type% , %type% > > %var% (") || - Token::Match(tok2, "%type% < %type% , %type% < %type% , %type% > > %var% (") || - Token::Match(tok2, "const %type% < %type% > &|* %var% (") || - Token::Match(tok2, "const %type% < %type% , %type% > &|* %var% (") || - Token::Match(tok2, "const %type% &|* %var% (") || - Token::Match(tok2, "const %type% :: %type% &|*| %var% (") || - Token::Match(tok2, "const %type% :: %type% < %type% > *|& %var% (") || - Token::Match(tok2, "const %type% :: %type% < %type% , %type% > *|& %var% (") || - Token::Match(tok2, "const %type% :: %type% < %type% :: %type% < %type% > , %type% > *|& %var% (") || - Token::Match(tok2, "const %type% < %type% < %type% > , %type% > *|& %var% (") || - Token::Match(tok2, "const %type% :: %type% < %type% , %type% :: %type% < %type% > > *|& %var% (") || - Token::Match(tok2, "const %type% < %type% , %type% < %type% > > *|& %var% (") || - Token::Match(tok2, "const %type% :: %type% < %type% :: %type% < %type% > , %type% :: %type% < %type% > > *|& %var% (") || - Token::Match(tok2, "const %type% < %type% < %type% > , %type% < %type% > > *|& %var% (") || - Token::Match(tok2, "const %type% :: %type% < %type% :: %type% < %type% , %type% > , %type% > *|& %var% (") || - Token::Match(tok2, "const %type% < %type% < %type% , %type% > , %type% > *|& %var% (") || - Token::Match(tok2, "const %type% :: %type% < %type% , %type% :: %type% < %type% , %type% > > *|& %var% (") || - Token::Match(tok2, "const %type% < %type% , %type% < %type% , %type% > > *|& %var% (") || - Token::Match(tok2, "%type% operator %any% (")) + if (isMemberFunc(tok2)) { // goto function name.. while (tok2->next()->str() != "(") @@ -1794,6 +1761,90 @@ bool CheckClass::sameFunc(int nest, const Token *firstEnd, const Token *secondEn return true; } +// A const member function can return either a copy of or +// a const reference or pointer to something. +// Is this a member function with these signatures: +// type var ( returns a copy of something +// const type var ( returns a const copy of something +// const type & var ( returns a const reference to something +// const type * var ( returns a const pointer to something +// type operator any ( returns a copy of something +// const type operator any ( returns a const copy of something +// const type & operator any ( returns a const reference to something +// const type * operator any ( returns a const pointer to something +// Type can be anything from a standard type to a complex template. +bool CheckClass::isMemberFunc(const Token *tok) +{ + bool isConst = false; + + if (tok->str() == "const") + { + isConst = true; + tok = tok->next(); + } + + if (Token::Match(tok, "%type%")) + { + tok = tok->next(); + + if (Token::Match(tok, "%var% (")) + return true; + else if (Token::Match(tok, "operator %any% (")) + return true; + else if (Token::Match(tok, "%type%")) + tok = tok->next(); + + while (Token::Match(tok, ":: %type%")) + tok = tok->tokAt(2); + + // template with parameter(s)? + if (Token::Match(tok, "< %type%")) + { + unsigned int level = 1; + tok = tok->tokAt(2); + while (tok) + { + if (tok->str() == "<") + level++; + else if (tok->str() == ">") + { + level--; + if (level == 0) + { + tok = tok->next(); + break; + } + } + tok = tok->next(); + } + } + + // template with default type + else if (Token::Match(tok, "< >")) + tok = tok->tokAt(2); + + // operator something + else if (Token::Match(tok, "operator %any% (")) + return true; + + if (isConst) + { + while (Token::Match(tok, "*|&")) + { + tok = tok->next(); + + if (tok->str() == "const") + tok = tok->next(); + } + } + + if (Token::Match(tok, "%var% (")) + return true; + } + + return false; +} + bool CheckClass::isMemberVar(const Var *varlist, const Token *tok) { while (tok->previous() && !Token::Match(tok->previous(), "}|{|;|public:|protected:|private:|return|:|?")) diff --git a/lib/checkclass.h b/lib/checkclass.h index 2cb578685..4ef033878 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -164,6 +164,7 @@ private: void checkConstructors(const Token *tok1, const std::string &funcname, bool hasPrivateConstructor, bool isStruct); bool sameFunc(int nest, const Token *firstEnd, const Token *secondEnd); + bool isMemberFunc(const Token *tok); bool isMemberVar(const Var *varlist, const Token *tok); bool checkConstFunc(const Var *varlist, const Token *tok); diff --git a/test/testclass.cpp b/test/testclass.cpp index e8c211d25..fc6b0b4d8 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -2646,6 +2646,29 @@ private: ASSERT_EQUALS("", errout.str()); + checkConst("class A {\n" + "public:\n" + " int * const * foo() { return &x; }\n" + "private:\n" + " const int * x;\n" + "}"); + ASSERT_EQUALS("", errout.str()); + + checkConst("class A {\n" + "public:\n" + " const int ** foo() { return &x; }\n" + "private:\n" + " const int * x;\n" + "}"); + ASSERT_EQUALS("[test.cpp:3]: (style) The function 'A::foo' can be const\n", errout.str()); + + checkConst("class A {\n" + "public:\n" + " const int * const * foo() { return &x; }\n" + "private:\n" + " const int * x;\n" + "}"); + ASSERT_EQUALS("[test.cpp:3]: (style) The function 'A::foo' can be const\n", errout.str()); } // increment/decrement => not const