diff --git a/clang-tools-extra/clang-tidy/readability/ConvertMemberFunctionsToStatic.cpp b/clang-tools-extra/clang-tidy/readability/ConvertMemberFunctionsToStatic.cpp --- a/clang-tools-extra/clang-tidy/readability/ConvertMemberFunctionsToStatic.cpp +++ b/clang-tools-extra/clang-tidy/readability/ConvertMemberFunctionsToStatic.cpp @@ -71,6 +71,31 @@ return UsageOfThis.Used; } +/// Does any base class have a non-static method with the same name? +AST_MATCHER(CXXMethodDecl, isHiding) { + const IdentifierInfo *ThisIdentifier = Node.getIdentifier(); + if (!ThisIdentifier) + return false; + + const CXXRecordDecl *Record = Node.getParent(); + + auto StaticOrDifferentName = [ThisIdentifier](const CXXMethodDecl *Method) { + if (Method->isStatic()) + return true; + + const IdentifierInfo *Ident = Method->getIdentifier(); + if (!Ident) + return true; + + return Ident->getName() != ThisIdentifier->getName(); + }; + + return !Record->forallBases([StaticOrDifferentName](const CXXRecordDecl *Base) { + return llvm::all_of(Base->methods(), + StaticOrDifferentName); + }); +} + void ConvertMemberFunctionsToStatic::registerMatchers(MatchFinder *Finder) { Finder->addMatcher( cxxMethodDecl( @@ -86,7 +111,8 @@ // depending on template base class. ), isInsideMacroDefinition(), - hasCanonicalDecl(isInsideMacroDefinition()), usesThis()))) + hasCanonicalDecl(isInsideMacroDefinition()), isHiding(), + usesThis()))) .bind("x"), this); } diff --git a/clang-tools-extra/test/clang-tidy/readability-convert-member-functions-to-static.cpp b/clang-tools-extra/test/clang-tidy/readability-convert-member-functions-to-static.cpp --- a/clang-tools-extra/test/clang-tidy/readability-convert-member-functions-to-static.cpp +++ b/clang-tools-extra/test/clang-tidy/readability-convert-member-functions-to-static.cpp @@ -216,3 +216,21 @@ return; } }; + +class HiddingBase { + int f(); + + static int g(); +}; + +class HiddingDerived : public HiddingBase { + int f() { + return 0; + } + + int g() { + // CHECK-MESSAGES: :[[@LINE-1]]:7: warning: method 'g' can be made static + // CHECK-FIXES: {{^}} static int g() { + return 0; + } +};