Refactorized CheckUnusedVar::checkStructMemberUsage(): Reimplemented check based on symboldatabase

This commit is contained in:
PKEuS 2016-05-25 11:13:31 +02:00
parent e22c177003
commit cda246da75
1 changed files with 40 additions and 73 deletions

View File

@ -1215,26 +1215,15 @@ void CheckUnusedVar::checkStructMemberUsage()
const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase(); const SymbolDatabase *symbolDatabase = _tokenizer->getSymbolDatabase();
std::string structname; for (std::list<Scope>::const_iterator scope = symbolDatabase->scopeList.cbegin(); scope != symbolDatabase->scopeList.cend(); ++scope) {
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) { if (scope->type != Scope::eStruct && scope->type != Scope::eUnion)
if (tok->fileIndex() != 0)
continue; continue;
if (Token::Match(tok, "struct|union %type% {")) { if (scope->classStart->fileIndex() != 0 || scope->className.empty())
structname = tok->strAt(1); continue;
// Bail out if struct/union contain any functions // Bail out if struct/union contains any functions
for (const Token *tok2 = tok->tokAt(2); tok2; tok2 = tok2->next()) { if (!scope->functionList.empty())
if (tok2->str() == "(") {
structname.clear();
break;
}
if (tok2->str() == "}")
break;
}
if (structname.empty())
continue; continue;
// bail out if struct is inherited // bail out if struct is inherited
@ -1242,68 +1231,46 @@ void CheckUnusedVar::checkStructMemberUsage()
for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.cbegin(); i != symbolDatabase->scopeList.cend(); ++i) { for (std::list<Scope>::const_iterator i = symbolDatabase->scopeList.cbegin(); i != symbolDatabase->scopeList.cend(); ++i) {
if (i->definedType) { if (i->definedType) {
for (size_t j = 0; j < i->definedType->derivedFrom.size(); j++) { for (size_t j = 0; j < i->definedType->derivedFrom.size(); j++) {
if (i->definedType->derivedFrom[j].type == tok->tokAt(3)->scope()->definedType) { if (i->definedType->derivedFrom[j].type == scope->definedType) {
bailout = true; bailout = true;
break; break;
} }
} }
} }
} }
if (bailout) { if (bailout)
structname.clear();
continue; continue;
}
// bail out for extern/global struct // bail out for extern/global struct
for (size_t i = 0; i < symbolDatabase->getVariableListSize(); i++) { for (size_t i = 0; i < symbolDatabase->getVariableListSize(); i++) {
const Variable* var = symbolDatabase->getVariableFromVarId(i); const Variable* var = symbolDatabase->getVariableFromVarId(i);
if (var && (var->isExtern() || (var->isGlobal() && !var->isStatic())) && var->typeEndToken()->str() == structname) { if (var && (var->isExtern() || (var->isGlobal() && !var->isStatic())) && var->typeEndToken()->str() == scope->className) {
structname.clear(); bailout = true;
break; break;
} }
} }
if (bailout)
if (structname.empty())
continue; continue;
// Bail out if some data is casted to struct.. // Bail out if some data is casted to struct..
const std::string castPattern("( struct| " + tok->next()->str() + " * ) & %name% ["); const std::string castPattern("( struct| " + scope->className + " * ) & %name% [");
if (Token::findmatch(tok, castPattern.c_str())) if (Token::findmatch(scope->classEnd, castPattern.c_str()))
structname.clear();
if (structname.empty())
continue; continue;
// Try to prevent false positives when struct members are not used directly. // Try to prevent false positives when struct members are not used directly.
if (Token::findmatch(tok, (structname + " %type%| *").c_str())) if (Token::findmatch(scope->classEnd, (scope->className + " %type%| *").c_str()))
structname.clear();
}
if (tok->str() == "}")
structname.clear();
if (!structname.empty() && Token::Match(tok, "[{;]")) {
// declaring a POD member variable?
if (!tok->next()->isStandardType())
continue; continue;
// Declaring struct member variable.. for (std::list<Variable>::const_iterator var = scope->varlist.cbegin(); var != scope->varlist.cend(); ++var) {
const std::string* memberVarName; // declaring a POD member variable?
if (!var->typeStartToken()->isStandardType() && !var->isPointer())
if (Token::Match(tok->next(), "%type% %name% [;[]"))
memberVarName = &tok->strAt(2);
else if (Token::Match(tok->next(), "%type% %type%|* %name% [;[]"))
memberVarName = &tok->strAt(3);
else if (Token::Match(tok->next(), "%type% %type% * %name% [;[]"))
memberVarName = &tok->strAt(4);
else
continue; continue;
// Check if the struct member variable is used anywhere in the file // Check if the struct member variable is used anywhere in the file
if (Token::findsimplematch(_tokenizer->tokens(), (". " + *memberVarName).c_str())) if (Token::findsimplematch(_tokenizer->tokens(), (". " + var->name()).c_str()))
continue; continue;
unusedStructMemberError(tok->next(), structname, *memberVarName, tok->scope()->type == Scope::eUnion); unusedStructMemberError(var->nameToken(), scope->className, var->name(), scope->type == Scope::eUnion);
} }
} }
} }