Improved updateClassList(), but not yet took it into use.

findClassFunction is now non-static.
updateClassList usage is currently commented out as it doesn't handle class inside a function
This commit is contained in:
Reijo Tomperi 2010-01-29 23:22:18 +02:00
parent f561441d90
commit 1d5ba4e320
6 changed files with 139 additions and 21 deletions

View File

@ -11,7 +11,7 @@
<Option output="cppcheck" prefix_auto="1" extension_auto="1" /> <Option output="cppcheck" prefix_auto="1" extension_auto="1" />
<Option type="1" /> <Option type="1" />
<Option compiler="gcc" /> <Option compiler="gcc" />
<Option parameters="p.cpp --debug" /> <Option parameters="p.cpp --debug --enable=all" />
<Compiler> <Compiler>
<Add option="-g" /> <Add option="-g" />
</Compiler> </Compiler>

View File

@ -285,7 +285,7 @@ void CheckClass::initializeVarList(const Token *tok1, const Token *ftok, Var *va
{ {
callstack.push_back(ftok->str()); callstack.push_back(ftok->str());
int i = 0; int i = 0;
const Token *ftok2 = Tokenizer::findClassFunction(tok1, classname, ftok->strAt(0), i, isStruct); const Token *ftok2 = _tokenizer->findClassFunction(tok1, classname, ftok->strAt(0), i, isStruct);
if (ftok2) if (ftok2)
{ {
initializeVarList(tok1, ftok2, varlist, classname, callstack, isStruct); initializeVarList(tok1, ftok2, varlist, classname, callstack, isStruct);
@ -500,7 +500,11 @@ void CheckClass::checkConstructors(const Token *tok1, const char funcname[], boo
Var *varlist = getVarList(tok1, withClasses, isStruct); Var *varlist = getVarList(tok1, withClasses, isStruct);
int indentlevel = 0; int indentlevel = 0;
const Token *constructor_token = Tokenizer::findClassFunction(tok1, className, funcname, indentlevel, isStruct); const Token *constructor_token = _tokenizer->findClassFunction(tok1, className, funcname, indentlevel, isStruct);
if (constructor_token)
std::cout << constructor_token->str() << "\n";
else
std::cout << "null\n";
std::list<std::string> callstack; std::list<std::string> callstack;
initializeVarList(tok1, constructor_token, varlist, className, callstack, isStruct); initializeVarList(tok1, constructor_token, varlist, className, callstack, isStruct);
while (constructor_token) while (constructor_token)
@ -547,7 +551,7 @@ void CheckClass::checkConstructors(const Token *tok1, const char funcname[], boo
for (Var *var = varlist; var; var = var->next) for (Var *var = varlist; var; var = var->next)
var->init = false; var->init = false;
constructor_token = Tokenizer::findClassFunction(constructor_token->next(), className, funcname, indentlevel, isStruct); constructor_token = _tokenizer->findClassFunction(constructor_token->next(), className, funcname, indentlevel, isStruct);
callstack.clear(); callstack.clear();
initializeVarList(tok1, constructor_token, varlist, className, callstack, isStruct); initializeVarList(tok1, constructor_token, varlist, className, callstack, isStruct);
} }

View File

@ -2319,7 +2319,7 @@ void CheckMemoryLeakInClass::variable(const std::string &classname, const Token
// Loop through all tokens. Inspect member functions // Loop through all tokens. Inspect member functions
int indent_ = 0; int indent_ = 0;
const Token *functionToken = Tokenizer::findClassFunction(_tokenizer->tokens(), classname.c_str(), "~| %var%", indent_); const Token *functionToken = _tokenizer->findClassFunction(_tokenizer->tokens(), classname.c_str(), "~| %var%", indent_);
while (functionToken) while (functionToken)
{ {
const bool constructor(Token::Match(functionToken, (classname + " :: " + classname + " (").c_str())); const bool constructor(Token::Match(functionToken, (classname + " :: " + classname + " (").c_str()));
@ -2417,7 +2417,7 @@ void CheckMemoryLeakInClass::variable(const std::string &classname, const Token
} }
} }
functionToken = Tokenizer::findClassFunction(functionToken->next(), classname.c_str(), "~| %var%", indent_); functionToken = _tokenizer->Tokenizer::findClassFunction(functionToken->next(), classname.c_str(), "~| %var%", indent_);
} }
if (allocInConstructor && !deallocInDestructor) if (allocInConstructor && !deallocInDestructor)

View File

@ -1003,7 +1003,7 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s
// simplify function pointers // simplify function pointers
simplifyFunctionPointers(); simplifyFunctionPointers();
//updateClassList();
setVarId(); setVarId();
if (!validate()) if (!validate())
return false; return false;
@ -1576,20 +1576,67 @@ void Tokenizer::simplifyTemplates()
} }
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
std::string Tokenizer::getNameForFunctionParams(const Token *start)
{
if (start->next() == start->link())
return "";
std::string result;
bool findNextComma = false;
for (const Token *tok = start->next(); tok && tok != start->link(); tok = tok->next())
{
if (findNextComma)
{
if (tok->str() == ",")
findNextComma = false;
continue;
}
result.append(tok->str() + ",");
findNextComma = true;
}
return result;
}
void Tokenizer::updateClassList() void Tokenizer::updateClassList()
{ {
const char pattern_class[] = "class %var% [{:]";
_classInfoList.clear(); _classInfoList.clear();
// Locate class // Locate class
const Token *tok1 = tokens(); const Token *tok1 = tokens();
while ((tok1 = Token::findmatch(tok1, pattern_class)) != 0)
{
const char *className;
className = tok1->strAt(1);
tok1 = tok1->next();
// Locate implementation
tok1 = tokens();
std::map<std::string, std::map<std::string, std::map<std::string, const Token*> > > implementations;
while ((tok1 = Token::findmatch(tok1, "%var% :: ~| %var% (")) != 0)
{
if (tok1->tokAt(2)->str() == "~")
implementations[tok1->str()]["~ "+tok1->tokAt(3)->str()][getNameForFunctionParams(tok1->tokAt(4))] = tok1;
else
implementations[tok1->str()][tok1->tokAt(2)->str()][getNameForFunctionParams(tok1->tokAt(3))] = tok1;
//std::cout <<"1."<< tok1->str() << "," << tok1->tokAt(2)->str() << ","<<getNameForFunctionParams(tok1->tokAt(3));
tok1 = tok1->next();
}
tok1 = tokens();
while ((tok1 = Token::findmatch(tok1, "%var% :: operator %any% (")) != 0)
{
implementations[tok1->str()][tok1->tokAt(2)->str()+" "+tok1->tokAt(3)->str()][getNameForFunctionParams(tok1->tokAt(4))] = tok1;
//std::cout <<"3."<< tok1->str() << "," << tok1->tokAt(2)->str()+" "+tok1->tokAt(3)->str() << ","<<getNameForFunctionParams(tok1->tokAt(4));
tok1 = tok1->next();
}
tok1 = tokens();
while ((tok1 = Token::findmatch(tok1, "class|struct %var% [{:]")) != 0)
{
ClassInfo::MemberType memberType = ClassInfo::PRIVATE; ClassInfo::MemberType memberType = ClassInfo::PRIVATE;
if (tok1->str() == "struct")
memberType = ClassInfo::PUBLIC;
const char *className = tok1->strAt(1);
tok1 = tok1->next();
int indentlevel = 0; int indentlevel = 0;
for (const Token *tok = tok1; tok; tok = tok->next()) for (const Token *tok = tok1; tok; tok = tok->next())
{ {
@ -1627,12 +1674,40 @@ void Tokenizer::updateClassList()
else if (Token::Match(tok, "%var% (")) else if (Token::Match(tok, "%var% ("))
{ {
// member function
ClassInfo::MemberFunctionInfo func; ClassInfo::MemberFunctionInfo func;
if (tok->previous()->str() == "~")
{
// destructor
func._declaration = tok->previous();
func._name = "~ " + tok->str();
}
else
{
// member function
func._declaration = tok; func._declaration = tok;
func._name = tok->str(); func._name = tok->str();
func._type = memberType; }
func._type = memberType;
if (tok->next()->link()->next()->str() == "{")
func._implementation = tok;
else
func._implementation = implementations[className][func._name][getNameForFunctionParams(tok->next())];
//std::cout <<"\n2."<< className << "," << func._name << ","<<getNameForFunctionParams(tok->next())<<"\n";
_classInfoList[className]._memberFunctions.push_back(func);
}
else if (Token::Match(tok, "operator %any% ("))
{
ClassInfo::MemberFunctionInfo func;
func._declaration = tok;
func._name = tok->str() + " " + tok->next()->str();
func._type = memberType;
if (tok->tokAt(2)->link()->next()->str() == "{")
func._implementation = tok;
else
func._implementation = implementations[className][func._name][getNameForFunctionParams(tok->tokAt(2))];
//std::cout <<"\n4."<< className << "," << func._name << ","<<getNameForFunctionParams(tok->tokAt(2))<<"\n";
_classInfoList[className]._memberFunctions.push_back(func); _classInfoList[className]._memberFunctions.push_back(func);
} }
} }
@ -5058,11 +5133,40 @@ std::string Tokenizer::file(const Token *tok) const
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
const Token * Tokenizer::findClassFunction(const Token *tok, const char classname[], const char funcname[], int &indentlevel, bool isStruct) const Token * Tokenizer::findClassFunction(const Token *tok, const char classname[], const char funcname[], int &indentlevel, bool isStruct) const
{ {
if (indentlevel < 0 || tok == NULL) if (indentlevel < 0 || tok == NULL)
return NULL; return NULL;
/*
// TODO: This is currently commented out as updateClassList doesn't
// fully work yet and call to updateClassList is currently also
// commented out.
//std::cout << tok->str()<<"--\n";
if( tok == _tokens || tok->str() == "class" || tok->str() == "struct")
tok = 0;
std::map<std::string, ClassInfo>::const_iterator iter;
iter = _classInfoList.find(classname);
if( iter == _classInfoList.end() )
return NULL;
for( size_t i = 0; i < iter->second._memberFunctions.size(); i++ )
if( Token::Match( iter->second._memberFunctions[i]._declaration, funcname ) )
{
if( tok != 0 )
{
if( tok == iter->second._memberFunctions[i]._implementation ||
tok->previous() == iter->second._memberFunctions[i]._implementation)
tok = 0;
continue;
}
return iter->second._memberFunctions[i]._implementation;
}
return NULL;
*/
const std::string classPattern(std::string(isStruct ? "struct " : "class ") + classname + " :|{"); const std::string classPattern(std::string(isStruct ? "struct " : "class ") + classname + " :|{");
const std::string internalPattern(std::string("!!~ ") + funcname + " ("); const std::string internalPattern(std::string("!!~ ") + funcname + " (");
const std::string externalPattern(std::string(classname) + " :: " + funcname + " ("); const std::string externalPattern(std::string(classname) + " :: " + funcname + " (");

View File

@ -115,7 +115,7 @@ public:
* @param isStruct is it a struct * @param isStruct is it a struct
* @return First matching token or NULL. * @return First matching token or NULL.
*/ */
static const Token *findClassFunction(const Token *tok, const char classname[], const char funcname[], int &indentlevel, bool isStruct = false); const Token *findClassFunction(const Token *tok, const char classname[], const char funcname[], int &indentlevel, bool isStruct = false) const;
/** /**
* get error messages * get error messages
@ -390,6 +390,16 @@ private:
*/ */
bool simplifyDoWhileAddBracesHelper(Token *tok); bool simplifyDoWhileAddBracesHelper(Token *tok);
/**
* This will return a short name describing function parameters
* e.g. parameters: (int a, char b) should get name "int,char,".
* This should help to identify functions with the same name,
* but with different parameters.
* @param start The "(" token
* @return, e.g. "int,char,"
*/
static std::string getNameForFunctionParams(const Token *start);
/** Disable assignment operator */ /** Disable assignment operator */
void operator=(const Tokenizer &); void operator=(const Tokenizer &);

View File

@ -2316,9 +2316,9 @@ private:
int i; int i;
i = 0; i = 0;
const Token *tok = Tokenizer::findClassFunction(tokenizer.tokens(), "Fred", "%var%", i); const Token *tok = tokenizer.findClassFunction(tokenizer.tokens(), "Fred", "%var%", i);
ASSERT_EQUALS(true, Token::simpleMatch(tok, "Fred ( ) {")); ASSERT_EQUALS(true, Token::simpleMatch(tok, "Fred ( ) {"));
tok = Tokenizer::findClassFunction(tok->next(), "Fred", "%var%", i); tok = tokenizer.findClassFunction(tok->next(), "Fred", "%var%", i);
ASSERT_EQUALS(0, tok ? 1 : 0); ASSERT_EQUALS(0, tok ? 1 : 0);
} }
@ -2339,9 +2339,9 @@ private:
int i; int i;
i = 0; i = 0;
const Token *tok = Tokenizer::findClassFunction(tokenizer.tokens(), "Fred", "%var%", i, true); const Token *tok = tokenizer.findClassFunction(tokenizer.tokens(), "Fred", "%var%", i, true);
ASSERT_EQUALS(true, Token::simpleMatch(tok, "Fred ( ) {")); ASSERT_EQUALS(true, Token::simpleMatch(tok, "Fred ( ) {"));
tok = Tokenizer::findClassFunction(tok->next(), "Fred", "%var%", i, false); tok = tokenizer.findClassFunction(tok->next(), "Fred", "%var%", i, false);
ASSERT_EQUALS(0, tok ? 1 : 0); ASSERT_EQUALS(0, tok ? 1 : 0);
} }