Refactorized CheckUnusedVar::checkStructMemberUsage(): Reimplemented check based on symboldatabase
This commit is contained in:
parent
e22c177003
commit
cda246da75
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue