Fix FN unusedStructMember with member functions, inheritance (#4978)
* Fix #551 Detect unused Private member variables * Fix FN unusedStructMember when there are member functions * Unused member * Warn for unused private variables in base class * Warn for private inheritance, add test
This commit is contained in:
parent
9cc56fb660
commit
35a46dfd00
|
@ -919,7 +919,7 @@ struct InvalidContainerAnalyzer {
|
|||
const Token* ftok;
|
||||
};
|
||||
std::unordered_map<int, Reference> expressions;
|
||||
ErrorPath errorPath;
|
||||
|
||||
void add(const std::vector<Reference>& refs) {
|
||||
for (const Reference& r : refs) {
|
||||
add(r);
|
||||
|
|
|
@ -1455,25 +1455,20 @@ void CheckUnusedVar::checkStructMemberUsage()
|
|||
continue;
|
||||
}
|
||||
|
||||
// Bail out if struct/union contains any functions
|
||||
if (!scope.functionList.empty())
|
||||
continue;
|
||||
|
||||
// Bail out for template struct, members might be used in non-matching instantiations
|
||||
if (scope.className.find('<') != std::string::npos)
|
||||
continue;
|
||||
|
||||
// bail out if struct is inherited
|
||||
bool bailout = std::any_of(symbolDatabase->scopeList.cbegin(), symbolDatabase->scopeList.cend(), [&](const Scope& derivedScope) {
|
||||
const bool isInherited = std::any_of(symbolDatabase->scopeList.cbegin(), symbolDatabase->scopeList.cend(), [&](const Scope& derivedScope) {
|
||||
const Type* dType = derivedScope.definedType;
|
||||
return dType && std::any_of(dType->derivedFrom.cbegin(), dType->derivedFrom.cend(), [&](const Type::BaseInfo& derivedFrom) {
|
||||
return derivedFrom.type == scope.definedType;
|
||||
return derivedFrom.type == scope.definedType && derivedFrom.access != AccessControl::Private;
|
||||
});
|
||||
});
|
||||
if (bailout)
|
||||
continue;
|
||||
|
||||
// bail out for extern/global struct
|
||||
bool bailout = false;
|
||||
for (const Variable* var : symbolDatabase->variableList()) {
|
||||
if (var && (var->isExtern() || (var->isGlobal() && !var->isStatic())) && var->typeEndToken()->str() == scope.className) {
|
||||
bailout = true;
|
||||
|
@ -1510,6 +1505,8 @@ void CheckUnusedVar::checkStructMemberUsage()
|
|||
// only warn for variables without side effects
|
||||
if (!var.typeStartToken()->isStandardType() && !var.isPointer() && !astIsContainer(var.nameToken()) && !isRecordTypeWithoutSideEffects(var.type()))
|
||||
continue;
|
||||
if (isInherited && !var.isPrivate())
|
||||
continue;
|
||||
|
||||
// Check if the struct member variable is used anywhere in the file
|
||||
bool use = false;
|
||||
|
|
|
@ -1876,6 +1876,34 @@ private:
|
|||
" int i{};\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("[test.cpp:2]: (style) class member 'C::i' is never used.\n", errout.str());
|
||||
|
||||
checkStructMemberUsage("class C {\n"
|
||||
" int i{}, j{};\n"
|
||||
"public:\n"
|
||||
" int& get() { return i; }\n"
|
||||
"};\n");
|
||||
ASSERT_EQUALS("[test.cpp:2]: (style) class member 'C::j' is never used.\n", errout.str());
|
||||
|
||||
checkStructMemberUsage("class C {\n"
|
||||
"private:\n"
|
||||
" int i;\n"
|
||||
"};\n"
|
||||
"class D : public C {};\n");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (style) class member 'C::i' is never used.\n", errout.str());
|
||||
|
||||
checkStructMemberUsage("class C {\n"
|
||||
"public:\n"
|
||||
" int i;\n"
|
||||
"};\n"
|
||||
"class D : C {};\n");
|
||||
ASSERT_EQUALS("[test.cpp:3]: (style) class member 'C::i' is never used.\n", errout.str());
|
||||
|
||||
checkStructMemberUsage("class C {\n"
|
||||
"public:\n"
|
||||
" int i;\n"
|
||||
"};\n"
|
||||
"class D : public C {};\n");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void functionVariableUsage_(const char* file, int line, const char code[], const char filename[] = "test.cpp") {
|
||||
|
|
Loading…
Reference in New Issue