refactoring namespace handling. ticket: #2001

This commit is contained in:
Robert Reif 2010-09-01 16:47:53 +02:00 committed by Daniel Marjamäki
parent 15b4cab4bb
commit 4153b7d24b
2 changed files with 115 additions and 79 deletions

View File

@ -70,7 +70,7 @@ static bool isFunction(const Token *tok, const Token **argStart)
else if (tok->str() == "operator") else if (tok->str() == "operator")
{ {
// operator[] or 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| ;|{|=|:")) Token::Match(tok->tokAt(3)->link(), ") const| ;|{|=|:"))
{ {
*argStart = tok->tokAt(3); *argStart = tok->tokAt(3);
@ -260,80 +260,7 @@ void CheckClass::createSymbolDatabase()
if (Token::Match(next, ") const| ;") || if (Token::Match(next, ") const| ;") ||
Token::Match(next, ") const| = 0 ;")) Token::Match(next, ") const| = 0 ;"))
{ {
// find implementation using names on stack // find the function implementation later
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);
tok = next->next(); tok = next->next();
} }
@ -344,8 +271,6 @@ void CheckClass::createSymbolDatabase()
function.hasBody = true; function.hasBody = true;
function.arg = function.argDef; function.arg = function.argDef;
info->functionList.push_back(function);
// skip over function body // skip over function body
tok = next->next(); tok = next->next();
while (tok && tok->str() != "{") while (tok && tok->str() != "{")
@ -354,6 +279,8 @@ void CheckClass::createSymbolDatabase()
return; return;
tok = tok->link(); tok = tok->link();
} }
info->functionList.push_back(function);
} }
// friend class declaration? // friend class declaration?
@ -373,7 +300,6 @@ void CheckClass::createSymbolDatabase()
std::multimap<std::string, SpaceInfo *>::iterator it; std::multimap<std::string, SpaceInfo *>::iterator it;
// finish filling in base class info
for (it = spaceInfoMMap.begin(); it != spaceInfoMMap.end(); ++it) for (it = spaceInfoMMap.begin(); it != spaceInfoMMap.end(); ++it)
{ {
info = it->second; info = it->second;
@ -382,6 +308,7 @@ void CheckClass::createSymbolDatabase()
if (info->isNamespace) if (info->isNamespace)
continue; continue;
// finish filling in base class info
for (unsigned int i = 0; i < info->derivedFrom.size(); ++i) for (unsigned int i = 0; i < info->derivedFrom.size(); ++i)
{ {
std::multimap<std::string, SpaceInfo *>::iterator it1; std::multimap<std::string, SpaceInfo *>::iterator it1;
@ -398,7 +325,8 @@ void CheckClass::createSymbolDatabase()
{ {
// are they in the same namespace or different namespaces with same name? // are they in the same namespace or different namespaces with same name?
if ((spaceInfo->nestedIn == info->nestedIn) || 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))) (spaceInfo->nestedIn->className == info->nestedIn->className)))
{ {
info->derivedFrom[i].spaceInfo = spaceInfo; info->derivedFrom[i].spaceInfo = spaceInfo;
@ -408,6 +336,84 @@ void CheckClass::createSymbolDatabase()
} }
} }
} }
std::list<Func>::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_) : CheckClass::SpaceInfo::SpaceInfo(CheckClass *check_, const Token *classDef_, CheckClass::SpaceInfo *nestedIn_) :
check(check_), check(check_),
classDef(classDef_), classDef(classDef_),
classStart(NULL),
classEnd(NULL),
nestedIn(nestedIn_), nestedIn(nestedIn_),
numConstructors(0) numConstructors(0)
{ {

View File

@ -3951,6 +3951,34 @@ private:
" };\n" " };\n"
"}\n"); "}\n");
ASSERT_EQUALS("[test.cpp:12]: (style) The function 'N::Derived::getResourceName' can be const\n", errout.str()); 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 void const36() // ticket #2003