From 4153b7d24ba3a73c6f8521f4a741cbd5fe87d066 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Wed, 1 Sep 2010 16:47:53 +0200 Subject: [PATCH] refactoring namespace handling. ticket: #2001 --- lib/checkclass.cpp | 166 ++++++++++++++++++++++++--------------------- test/testclass.cpp | 28 ++++++++ 2 files changed, 115 insertions(+), 79 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index b33fe2867..aa19425d9 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -70,7 +70,7 @@ static bool isFunction(const Token *tok, const Token **argStart) else if (tok->str() == "operator") { // operator[] or operator()? - if ((Token::Match(tok->next(), "( ) (") || Token::Match(tok->next(), "[ ] (")) && + if ((Token::simpleMatch(tok->next(), "( ) (") || Token::simpleMatch(tok->next(), "[ ] (")) && Token::Match(tok->tokAt(3)->link(), ") const| ;|{|=|:")) { *argStart = tok->tokAt(3); @@ -260,80 +260,7 @@ void CheckClass::createSymbolDatabase() if (Token::Match(next, ") const| ;") || Token::Match(next, ") const| = 0 ;")) { - // find implementation using names on stack - SpaceInfo *nest = info; - unsigned int depth = 0; - - std::string classPattern; - std::string classPath; - std::string searchPattern; - const Token *funcArgs = function.tokenDef->tokAt(2); - int offset = 1; - - if (function.isOperator) - { - if (Token::Match(function.tokenDef, "(|[")) - { - classPattern = "operator " + function.tokenDef->str() + " " + function.tokenDef->next()->str() + " ("; - offset = 2; - } - else if (Token::Match(function.tokenDef, "new|delete [")) - { - classPattern = "operator " + function.tokenDef->str() + " " + function.tokenDef->next()->str() + " " + function.tokenDef->next()->strAt(2) + " ("; - offset = 3; - } - else - classPattern = "operator " + function.tokenDef->str() + " ("; - } - else - classPattern = function.tokenDef->str() + " ("; - - // look for an implementation outside of class - while (!function.hasBody && nest) - { - classPath = nest->className + std::string(" :: ") + classPath; - searchPattern = classPath + classPattern; - depth++; - nest = nest->nestedIn; - - // start looking at end of class - SpaceInfo *top = info; - const Token *found = top->classEnd; - while ((found = Token::findmatch(found, searchPattern.c_str(), nest ? nest->classEnd : 0)) != NULL) - { - // skip other classes - if (found->previous()->str() == "::") - break; - - // goto function name - while (found->next()->str() != "(") - found = found->next(); - - if (Token::Match(found->tokAt(offset)->link(), function.isConst ? ") const {" : ") {") || - (function.type == Func::Constructor && Token::Match(found->next()->link(), ") :|{"))) - { - if (argsMatch(funcArgs, found->tokAt(offset + 1), classPath, depth)) - { - function.token = found; - function.hasBody = true; - function.arg = found->tokAt(offset); - - info->functionList.push_back(function); - break; - } - - // skip function body - while (found->str() != "{") - found = found->next(); - - found = found->link(); - } - } - } - - if (!function.hasBody) - info->functionList.push_back(function); - + // find the function implementation later tok = next->next(); } @@ -344,8 +271,6 @@ void CheckClass::createSymbolDatabase() function.hasBody = true; function.arg = function.argDef; - info->functionList.push_back(function); - // skip over function body tok = next->next(); while (tok && tok->str() != "{") @@ -354,6 +279,8 @@ void CheckClass::createSymbolDatabase() return; tok = tok->link(); } + + info->functionList.push_back(function); } // friend class declaration? @@ -373,7 +300,6 @@ void CheckClass::createSymbolDatabase() std::multimap::iterator it; - // finish filling in base class info for (it = spaceInfoMMap.begin(); it != spaceInfoMMap.end(); ++it) { info = it->second; @@ -382,6 +308,7 @@ void CheckClass::createSymbolDatabase() if (info->isNamespace) continue; + // finish filling in base class info for (unsigned int i = 0; i < info->derivedFrom.size(); ++i) { std::multimap::iterator it1; @@ -398,7 +325,8 @@ void CheckClass::createSymbolDatabase() { // are they in the same namespace or different namespaces with same name? if ((spaceInfo->nestedIn == info->nestedIn) || - ((spaceInfo->nestedIn->isNamespace && info->nestedIn->isNamespace) && + ((spaceInfo->nestedIn && spaceInfo->nestedIn->isNamespace) && + (info->nestedIn && info->nestedIn->isNamespace) && (spaceInfo->nestedIn->className == info->nestedIn->className))) { info->derivedFrom[i].spaceInfo = spaceInfo; @@ -408,6 +336,84 @@ void CheckClass::createSymbolDatabase() } } } + + std::list::iterator func; + + // find the function body if not implemented inline + for (func = info->functionList.begin(); func != info->functionList.end(); ++func) + { + if (!func->hasBody) + { + // find implementation using names on stack + SpaceInfo *nest = info; + unsigned int depth = 0; + + std::string classPattern; + std::string classPath; + std::string searchPattern; + const Token *funcArgs = func->tokenDef->tokAt(2); + int offset = 1; + + if (func->isOperator) + { + if (Token::Match(func->tokenDef, "(|[")) + { + classPattern = "operator " + func->tokenDef->str() + " " + func->tokenDef->next()->str() + " ("; + offset = 2; + } + else if (Token::Match(func->tokenDef, "new|delete [")) + { + classPattern = "operator " + func->tokenDef->str() + " " + func->tokenDef->next()->str() + " " + func->tokenDef->next()->strAt(2) + " ("; + offset = 3; + } + else + classPattern = "operator " + func->tokenDef->str() + " ("; + } + else + classPattern = func->tokenDef->str() + " ("; + + // look for an implementation outside of class + while (!func->hasBody && nest) + { + classPath = nest->className + std::string(" :: ") + classPath; + searchPattern = classPath + classPattern; + depth++; + nest = nest->nestedIn; + + // start looking at end of class + SpaceInfo *top = info; + const Token *found = top->classEnd; + while ((found = Token::findmatch(found, searchPattern.c_str(), nest ? nest->classEnd : 0)) != NULL) + { + // skip other classes + if (found->previous()->str() == "::") + break; + + // goto function name + while (found->next()->str() != "(") + found = found->next(); + + if (Token::Match(found->tokAt(offset)->link(), func->isConst ? ") const {" : ") {") || + (func->type == Func::Constructor && Token::Match(found->next()->link(), ") :|{"))) + { + if (argsMatch(funcArgs, found->tokAt(offset + 1), classPath, depth)) + { + func->token = found; + func->hasBody = true; + func->arg = found->tokAt(offset); + break; + } + + // skip function body + while (found->str() != "{") + found = found->next(); + + found = found->link(); + } + } + } + } + } } } @@ -487,6 +493,8 @@ const Token *CheckClass::initBaseInfo(SpaceInfo *info, const Token *tok) CheckClass::SpaceInfo::SpaceInfo(CheckClass *check_, const Token *classDef_, CheckClass::SpaceInfo *nestedIn_) : check(check_), classDef(classDef_), + classStart(NULL), + classEnd(NULL), nestedIn(nestedIn_), numConstructors(0) { diff --git a/test/testclass.cpp b/test/testclass.cpp index 483d61690..f6bb0c1b7 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -3951,6 +3951,34 @@ private: " };\n" "}\n"); ASSERT_EQUALS("[test.cpp:12]: (style) The function 'N::Derived::getResourceName' can be const\n", errout.str()); + + checkConst("namespace N\n" + "{\n" + " class Base\n" + " {\n" + " public:\n" + " int getResourceName();\n" + " int var;\n" + " };\n" + "}\n" + "int N::Base::getResourceName() { return var; }\n"); + ASSERT_EQUALS("[test.cpp:10] -> [test.cpp:6]: (style) The function 'N::Base::getResourceName' can be const\n", errout.str()); + + checkConst("namespace N\n" + "{\n" + " class Base\n" + " {\n" + " public:\n" + " int getResourceName();\n" + " int var;\n" + " };\n" + "}\n" + "namespace N\n" + "{\n" + " int Base::getResourceName() { return var; }\n" + "}\n"); + ASSERT_EQUALS("", errout.str()); + TODO_ASSERT_EQUALS("[test.cpp:12] -> [test.cpp:6]: (style) The function 'N::Base::getResourceName' can be const\n", errout.str()); } void const36() // ticket #2003