From c3002f123042cbf0b3b8d192315fa1f4a58eea51 Mon Sep 17 00:00:00 2001 From: chrchr-github <78114321+chrchr-github@users.noreply.github.com> Date: Mon, 17 Apr 2023 20:34:39 +0200 Subject: [PATCH] Fix #551 Detect unused Private member variables (#4973) --- lib/checkunusedvar.cpp | 17 +++++++++++------ lib/checkunusedvar.h | 2 +- test/testunusedvar.cpp | 8 ++++++++ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index 181d2cb9c..3d9adf7fa 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -1437,7 +1437,7 @@ void CheckUnusedVar::checkStructMemberUsage() const SymbolDatabase *symbolDatabase = mTokenizer->getSymbolDatabase(); for (const Scope &scope : symbolDatabase->scopeList) { - if (scope.type != Scope::eStruct && scope.type != Scope::eUnion) + if (scope.type != Scope::eStruct && scope.type != Scope::eClass && scope.type != Scope::eUnion) continue; if (scope.bodyStart->fileIndex() != 0 || scope.className.empty()) @@ -1521,16 +1521,21 @@ void CheckUnusedVar::checkStructMemberUsage() break; } } - if (!use) - unusedStructMemberError(var.nameToken(), scope.className, var.name(), scope.type == Scope::eUnion); + if (!use) { + std::string prefix = "struct"; + if (scope.type == Scope::ScopeType::eClass) + prefix = "class"; + else if (scope.type == Scope::ScopeType::eUnion) + prefix = "union"; + unusedStructMemberError(var.nameToken(), scope.className, var.name(), prefix); + } } } } -void CheckUnusedVar::unusedStructMemberError(const Token *tok, const std::string &structname, const std::string &varname, bool isUnion) +void CheckUnusedVar::unusedStructMemberError(const Token* tok, const std::string& structname, const std::string& varname, const std::string& prefix) { - const std::string prefix = isUnion ? "union member " : "struct member "; - reportError(tok, Severity::style, "unusedStructMember", "$symbol:" + structname + "::" + varname + '\n' + prefix + "'$symbol' is never used.", CWE563, Certainty::normal); + reportError(tok, Severity::style, "unusedStructMember", "$symbol:" + structname + "::" + varname + '\n' + prefix + " member '$symbol' is never used.", CWE563, Certainty::normal); } bool CheckUnusedVar::isRecordTypeWithoutSideEffects(const Type* type) diff --git a/lib/checkunusedvar.h b/lib/checkunusedvar.h index 130cef26a..743a732ba 100644 --- a/lib/checkunusedvar.h +++ b/lib/checkunusedvar.h @@ -77,7 +77,7 @@ private: std::list checkedFuncs); // Error messages.. - void unusedStructMemberError(const Token *tok, const std::string &structname, const std::string &varname, bool isUnion = false); + void unusedStructMemberError(const Token *tok, const std::string &structname, const std::string &varname, const std::string& prefix = "struct"); void unusedVariableError(const Token *tok, const std::string &varname); void allocatedButUnusedVariableError(const Token *tok, const std::string &varname); void unreadVariableError(const Token *tok, const std::string &varname, bool modified); diff --git a/test/testunusedvar.cpp b/test/testunusedvar.cpp index 362bdfe11..4ff19d347 100644 --- a/test/testunusedvar.cpp +++ b/test/testunusedvar.cpp @@ -75,6 +75,7 @@ private: TEST_CASE(structmember21); // #4759 TEST_CASE(structmember22); // #11016 TEST_CASE(structmember23); + TEST_CASE(classmember); TEST_CASE(localvar1); TEST_CASE(localvar2); @@ -1870,6 +1871,13 @@ private: ASSERT_EQUALS("", errout.str()); } + void classmember() { + checkStructMemberUsage("class C {\n" + " int i{};\n" + "};\n"); + ASSERT_EQUALS("[test.cpp:2]: (style) class member 'C::i' is never used.\n", errout.str()); + } + void functionVariableUsage_(const char* file, int line, const char code[], const char filename[] = "test.cpp") { // Clear the error buffer.. errout.str("");