diff --git a/cppcheck.cbp b/cppcheck.cbp
index 8526213bb..917614137 100644
--- a/cppcheck.cbp
+++ b/cppcheck.cbp
@@ -11,7 +11,7 @@
-
+
diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp
index 5994f2fdc..b1537ca46 100644
--- a/lib/checkclass.cpp
+++ b/lib/checkclass.cpp
@@ -285,7 +285,7 @@ void CheckClass::initializeVarList(const Token *tok1, const Token *ftok, Var *va
{
callstack.push_back(ftok->str());
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)
{
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);
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 callstack;
initializeVarList(tok1, constructor_token, varlist, className, callstack, isStruct);
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)
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();
initializeVarList(tok1, constructor_token, varlist, className, callstack, isStruct);
}
diff --git a/lib/checkmemoryleak.cpp b/lib/checkmemoryleak.cpp
index 58ce15527..8e2b3c006 100644
--- a/lib/checkmemoryleak.cpp
+++ b/lib/checkmemoryleak.cpp
@@ -2319,7 +2319,7 @@ void CheckMemoryLeakInClass::variable(const std::string &classname, const Token
// Loop through all tokens. Inspect member functions
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)
{
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)
diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp
index e8f6c61d4..ebe5e2e12 100644
--- a/lib/tokenize.cpp
+++ b/lib/tokenize.cpp
@@ -1003,7 +1003,7 @@ bool Tokenizer::tokenize(std::istream &code, const char FileName[], const std::s
// simplify function pointers
simplifyFunctionPointers();
-
+//updateClassList();
setVarId();
if (!validate())
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()
{
- const char pattern_class[] = "class %var% [{:]";
_classInfoList.clear();
// Locate class
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 > > 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() << ","<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() << ","<tokAt(4));
+ tok1 = tok1->next();
+ }
+
+ tok1 = tokens();
+ while ((tok1 = Token::findmatch(tok1, "class|struct %var% [{:]")) != 0)
+ {
ClassInfo::MemberType memberType = ClassInfo::PRIVATE;
+ if (tok1->str() == "struct")
+ memberType = ClassInfo::PUBLIC;
+
+ const char *className = tok1->strAt(1);
+ tok1 = tok1->next();
int indentlevel = 0;
for (const Token *tok = tok1; tok; tok = tok->next())
{
@@ -1627,12 +1674,40 @@ void Tokenizer::updateClassList()
else if (Token::Match(tok, "%var% ("))
{
- // member function
+ ClassInfo::MemberFunctionInfo func;
+ if (tok->previous()->str() == "~")
+ {
+ // destructor
+ func._declaration = tok->previous();
+ func._name = "~ " + tok->str();
+ }
+ else
+ {
+ // member function
+ func._declaration = tok;
+ func._name = tok->str();
+ }
+
+ 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 << ","<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();
+ 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 << ","<tokAt(2))<<"\n";
_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)
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::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 internalPattern(std::string("!!~ ") + funcname + " (");
const std::string externalPattern(std::string(classname) + " :: " + funcname + " (");
diff --git a/lib/tokenize.h b/lib/tokenize.h
index 31cbfb1a6..9562260a2 100644
--- a/lib/tokenize.h
+++ b/lib/tokenize.h
@@ -115,7 +115,7 @@ public:
* @param isStruct is it a struct
* @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
@@ -390,6 +390,16 @@ private:
*/
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 */
void operator=(const Tokenizer &);
diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp
index ce76d39ca..6bafc7ef9 100644
--- a/test/testtokenize.cpp
+++ b/test/testtokenize.cpp
@@ -2316,9 +2316,9 @@ private:
int i;
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 ( ) {"));
- tok = Tokenizer::findClassFunction(tok->next(), "Fred", "%var%", i);
+ tok = tokenizer.findClassFunction(tok->next(), "Fred", "%var%", i);
ASSERT_EQUALS(0, tok ? 1 : 0);
}
@@ -2339,9 +2339,9 @@ private:
int i;
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 ( ) {"));
- tok = Tokenizer::findClassFunction(tok->next(), "Fred", "%var%", i, false);
+ tok = tokenizer.findClassFunction(tok->next(), "Fred", "%var%", i, false);
ASSERT_EQUALS(0, tok ? 1 : 0);
}