From 7d6fc23022d355b630993cabf139c8ae91354b9c Mon Sep 17 00:00:00 2001 From: abhijit-sawant Date: Mon, 21 Dec 2020 01:14:52 -0500 Subject: [PATCH] Checking in fix for issue 9957 - - False negative: duplInheritedMember (#2964) --- lib/checkclass.cpp | 32 +++++++++++++++++++------------- lib/checkclass.h | 2 ++ test/testclass.cpp | 14 ++++++++++++++ 3 files changed, 35 insertions(+), 13 deletions(-) diff --git a/lib/checkclass.cpp b/lib/checkclass.cpp index d0c464d49..a6b5f0371 100644 --- a/lib/checkclass.cpp +++ b/lib/checkclass.cpp @@ -2439,22 +2439,28 @@ void CheckClass::checkDuplInheritedMembers() // Iterate over all classes for (const Type &classIt : mSymbolDatabase->typeList) { // Iterate over the parent classes - for (const Type::BaseInfo &parentClassIt : classIt.derivedFrom) { - // Check if there is info about the 'Base' class - if (!parentClassIt.type || !parentClassIt.type->classScope) - continue; - // Check if they have a member variable in common - for (const Variable &classVarIt : classIt.classScope->varlist) { - for (const Variable &parentClassVarIt : parentClassIt.type->classScope->varlist) { - if (classVarIt.name() == parentClassVarIt.name() && !parentClassVarIt.isPrivate()) { // Check if the class and its parent have a common variable - duplInheritedMembersError(classVarIt.nameToken(), parentClassVarIt.nameToken(), - classIt.name(), parentClassIt.type->name(), classVarIt.name(), - classIt.classScope->type == Scope::eStruct, - parentClassIt.type->classScope->type == Scope::eStruct); - } + checkDuplInheritedMembersRecursive(&classIt, &classIt); + } +} + +void CheckClass::checkDuplInheritedMembersRecursive(const Type* typeCurrent, const Type* typeBase) +{ + for (const Type::BaseInfo &parentClassIt : typeBase->derivedFrom) { + // Check if there is info about the 'Base' class + if (!parentClassIt.type || !parentClassIt.type->classScope) + continue; + // Check if they have a member variable in common + for (const Variable &classVarIt : typeCurrent->classScope->varlist) { + for (const Variable &parentClassVarIt : parentClassIt.type->classScope->varlist) { + if (classVarIt.name() == parentClassVarIt.name() && !parentClassVarIt.isPrivate()) { // Check if the class and its parent have a common variable + duplInheritedMembersError(classVarIt.nameToken(), parentClassVarIt.nameToken(), + typeCurrent->name(), parentClassIt.type->name(), classVarIt.name(), + typeCurrent->classScope->type == Scope::eStruct, + parentClassIt.type->classScope->type == Scope::eStruct); } } } + checkDuplInheritedMembersRecursive(typeCurrent, parentClassIt.type); } } diff --git a/lib/checkclass.h b/lib/checkclass.h index cedd8f4fa..9649a309e 100644 --- a/lib/checkclass.h +++ b/lib/checkclass.h @@ -38,6 +38,7 @@ class Scope; class Settings; class SymbolDatabase; class Token; +class Type; /// @addtogroup Checks /// @{ @@ -185,6 +186,7 @@ private: void overrideError(const Function *funcInBase, const Function *funcInDerived); void thisUseAfterFree(const Token *self, const Token *free, const Token *use); void unsafeClassRefMemberError(const Token *tok, const std::string &varname); + void checkDuplInheritedMembersRecursive(const Type* typeCurrent, const Type* typeBase); void getErrorMessages(ErrorLogger *errorLogger, const Settings *settings) const OVERRIDE { CheckClass c(nullptr, settings, errorLogger); diff --git a/test/testclass.cpp b/test/testclass.cpp index 515525c56..1cfbf055b 100644 --- a/test/testclass.cpp +++ b/test/testclass.cpp @@ -557,6 +557,20 @@ private: "}"); ASSERT_EQUALS("", errout.str()); + // #9957 + checkDuplInheritedMembers("class Base {\n" + " public:\n" + " int i;\n" + "};\n" + "class Derived1: public Base {\n" + " public:\n" + " int j;\n" + "};\n" + "class Derived2 : public Derived1 {\n" + " int i;\n" + "};"); + ASSERT_EQUALS("[test.cpp:3] -> [test.cpp:10]: (warning) The class 'Derived2' defines member variable with name 'i' also defined in its parent class 'Base'.\n", errout.str()); + } void checkCopyConstructor(const char code[]) {