CheckClass: refactored the code, use symboldatabase instead of name comparisons when possible, fixed a FN.

This commit is contained in:
Daniel Marjamäki 2016-05-16 09:36:26 +02:00
parent 22542e7547
commit bce15b1ade
3 changed files with 21 additions and 21 deletions

View File

@ -41,8 +41,7 @@ static const CWE CWE665(665U);
static const CWE CWE758(758U); static const CWE CWE758(758U);
static const CWE CWE762(762U); static const CWE CWE762(762U);
static const char * getFunctionTypeName( static const char * getFunctionTypeName(Function::Type type)
Function::Type type)
{ {
switch (type) { switch (type) {
case Function::eConstructor: case Function::eConstructor:
@ -873,7 +872,7 @@ void CheckClass::suggestInitializationList(const Token* tok, const std::string&
// ClassCheck: Unused private functions // ClassCheck: Unused private functions
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
static bool checkFunctionUsage(const std::string& name, const Scope* scope) static bool checkFunctionUsage(const Function *privfunc, const Scope* scope)
{ {
if (!scope) if (!scope)
return true; // Assume it is used, if scope is not seen return true; // Assume it is used, if scope is not seen
@ -882,14 +881,16 @@ static bool checkFunctionUsage(const std::string& name, const Scope* scope)
if (func->functionScope) { if (func->functionScope) {
if (Token::Match(func->tokenDef, "%name% (")) { if (Token::Match(func->tokenDef, "%name% (")) {
for (const Token *ftok = func->tokenDef->tokAt(2); ftok && ftok->str() != ")"; ftok = ftok->next()) { for (const Token *ftok = func->tokenDef->tokAt(2); ftok && ftok->str() != ")"; ftok = ftok->next()) {
if (Token::Match(ftok, "= %name% [(,)]") && ftok->strAt(1) == name) if (Token::Match(ftok, "= %name% [(,)]") && ftok->strAt(1) == privfunc->name())
return true; return true;
if (ftok->str() == "(") if (ftok->str() == "(")
ftok = ftok->link(); ftok = ftok->link();
} }
} }
for (const Token *ftok = func->functionScope->classDef->linkAt(1); ftok != func->functionScope->classEnd; ftok = ftok->next()) { for (const Token *ftok = func->functionScope->classDef->linkAt(1); ftok != func->functionScope->classEnd; ftok = ftok->next()) {
if (ftok->str() == name) // Function used. TODO: Handle overloads if (ftok->function() == privfunc)
return true;
if (ftok->varId() == 0U && !ftok->function() && ftok->str() == privfunc->name()) // TODO: This condition should be redundant
return true; return true;
} }
} else if ((func->type != Function::eCopyConstructor && } else if ((func->type != Function::eCopyConstructor &&
@ -900,7 +901,7 @@ static bool checkFunctionUsage(const std::string& name, const Scope* scope)
for (std::list<Scope*>::const_iterator i = scope->nestedList.begin(); i != scope->nestedList.end(); ++i) { for (std::list<Scope*>::const_iterator i = scope->nestedList.begin(); i != scope->nestedList.end(); ++i) {
if ((*i)->isClassOrStruct()) if ((*i)->isClassOrStruct())
if (checkFunctionUsage(name, *i)) // Check nested classes, which can access private functions of their base if (checkFunctionUsage(privfunc, *i)) // Check nested classes, which can access private functions of their base
return true; return true;
} }
@ -910,7 +911,7 @@ static bool checkFunctionUsage(const std::string& name, const Scope* scope)
if (tok) if (tok)
tok = tok->tokAt(2); tok = tok->tokAt(2);
while (tok && tok->str() != ";") { while (tok && tok->str() != ";") {
if (tok->str() == name && (tok->strAt(-1) == "." || tok->strAt(-2) == scope->className)) if (tok->function() == privfunc)
return true; return true;
tok = tok->next(); tok = tok->next();
} }
@ -952,20 +953,19 @@ void CheckClass::privateFunctions()
} }
while (!privateFuncs.empty()) { while (!privateFuncs.empty()) {
const std::string& funcName = privateFuncs.front()->tokenDef->str();
// Check that all private functions are used // Check that all private functions are used
bool used = checkFunctionUsage(funcName, scope); // Usage in this class bool used = checkFunctionUsage(privateFuncs.front(), scope); // Usage in this class
// Check in friend classes // Check in friend classes
const std::list<Type::FriendInfo>& friendList = scope->definedType->friendList; const std::list<Type::FriendInfo>& friendList = scope->definedType->friendList;
for (std::list<Type::FriendInfo>::const_iterator it = friendList.begin(); !used && it != friendList.end(); ++it) { for (std::list<Type::FriendInfo>::const_iterator it = friendList.begin(); !used && it != friendList.end(); ++it) {
if (it->type) if (it->type)
used = checkFunctionUsage(funcName, it->type->classScope); used = checkFunctionUsage(privateFuncs.front(), it->type->classScope);
else else
used = true; // Assume, it is used if we do not see friend class used = true; // Assume, it is used if we do not see friend class
} }
if (!used) if (!used)
unusedPrivateFunctionError(privateFuncs.front()->tokenDef, scope->className, funcName); unusedPrivateFunctionError(privateFuncs.front()->tokenDef, scope->className, privateFuncs.front()->name());
privateFuncs.pop_front(); privateFuncs.pop_front();
} }

View File

@ -374,16 +374,16 @@ std::string MathLib::normalizeCharacterLiteral(const std::string& iLiteral)
switch (iLiteral[idx]) { switch (iLiteral[idx]) {
case 'x': case 'x':
// Hexa-decimal number: skip \x and interpret the next two characters // Hexa-decimal number: skip \x and interpret the next two characters
{ {
if (++idx == iLiteralLen) if (++idx == iLiteralLen)
throw InternalError(0, "Internal Error. MathLib::toLongNumber: Unhandled char constant '" + iLiteral + "'."); throw InternalError(0, "Internal Error. MathLib::toLongNumber: Unhandled char constant '" + iLiteral + "'.");
std::string tempBuf; std::string tempBuf;
tempBuf.push_back(iLiteral[idx]);
if (++idx != iLiteralLen)
tempBuf.push_back(iLiteral[idx]); tempBuf.push_back(iLiteral[idx]);
if (++idx != iLiteralLen) normalizedLiteral.push_back(static_cast<char>(MathLib::toULongNumber("0x" + tempBuf)));
tempBuf.push_back(iLiteral[idx]); continue;
normalizedLiteral.push_back(static_cast<char>(MathLib::toULongNumber("0x" + tempBuf))); }
continue;
}
case 'u': case 'u':
case 'U': case 'U':
// Unicode string; just skip the \u or \U // Unicode string; just skip the \u or \U

View File

@ -408,7 +408,7 @@ private:
" void f() { }\n" " void f() { }\n"
" void f(int) { }\n" " void f(int) { }\n"
"};"); "};");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("[test.cpp:10]: (style) Unused private function: 'A::f'\n", errout.str());
} }
void incompleteImplementation() { void incompleteImplementation() {