diff options
Diffstat (limited to 'clang-tools-extra/clang-tidy/objc')
4 files changed, 101 insertions, 0 deletions
diff --git a/clang-tools-extra/clang-tidy/objc/CMakeLists.txt b/clang-tools-extra/clang-tidy/objc/CMakeLists.txt index 4eeb14844a5..0a12e4a850d 100644 --- a/clang-tools-extra/clang-tidy/objc/CMakeLists.txt +++ b/clang-tools-extra/clang-tidy/objc/CMakeLists.txt @@ -4,6 +4,7 @@ add_clang_library(clangTidyObjCModule AvoidNSErrorInitCheck.cpp AvoidSpinlockCheck.cpp ForbiddenSubclassingCheck.cpp + MissingHashCheck.cpp ObjCTidyModule.cpp PropertyDeclarationCheck.cpp SuperSelfCheck.cpp diff --git a/clang-tools-extra/clang-tidy/objc/MissingHashCheck.cpp b/clang-tools-extra/clang-tidy/objc/MissingHashCheck.cpp new file mode 100644 index 00000000000..0da5571b2f2 --- /dev/null +++ b/clang-tools-extra/clang-tidy/objc/MissingHashCheck.cpp @@ -0,0 +1,62 @@ +//===--- MissingHashCheck.cpp - clang-tidy --------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "MissingHashCheck.h" +#include "clang/AST/ASTContext.h" +#include "clang/ASTMatchers/ASTMatchFinder.h" + +using namespace clang::ast_matchers; + +namespace clang { +namespace tidy { +namespace objc { + +namespace { + +AST_MATCHER_P(ObjCImplementationDecl, hasInterface, + ast_matchers::internal::Matcher<ObjCInterfaceDecl>, Base) { + const ObjCInterfaceDecl *InterfaceDecl = Node.getClassInterface(); + return Base.matches(*InterfaceDecl, Finder, Builder); +} + +AST_MATCHER_P(ObjCContainerDecl, hasInstanceMethod, + ast_matchers::internal::Matcher<ObjCMethodDecl>, Base) { + // Check each instance method against the provided matcher. + for (const auto *I : Node.instance_methods()) { + if (Base.matches(*I, Finder, Builder)) + return true; + } + return false; +} + +} // namespace + +void MissingHashCheck::registerMatchers(MatchFinder *Finder) { + // This check should only be applied to Objective-C sources. + if (!getLangOpts().ObjC) + return; + + Finder->addMatcher( + objcMethodDecl( + hasName("isEqual:"), isInstanceMethod(), + hasDeclContext(objcImplementationDecl( + hasInterface(isDirectlyDerivedFrom("NSObject")), + unless(hasInstanceMethod(hasName("hash")))) + .bind("impl"))), + this); +} + +void MissingHashCheck::check(const MatchFinder::MatchResult &Result) { + const auto *ID = Result.Nodes.getNodeAs<ObjCImplementationDecl>("impl"); + diag(ID->getLocation(), "%0 implements -isEqual: without implementing -hash") + << ID; +} + +} // namespace objc +} // namespace tidy +} // namespace clang diff --git a/clang-tools-extra/clang-tidy/objc/MissingHashCheck.h b/clang-tools-extra/clang-tidy/objc/MissingHashCheck.h new file mode 100644 index 00000000000..4ac74d58652 --- /dev/null +++ b/clang-tools-extra/clang-tidy/objc/MissingHashCheck.h @@ -0,0 +1,35 @@ +//===--- MissingHashCheck.h - clang-tidy ------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_MISSINGHASHCHECK_H +#define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_MISSINGHASHCHECK_H + +#include "../ClangTidyCheck.h" + +namespace clang { +namespace tidy { +namespace objc { + +/// Finds Objective-C implementations that implement -isEqual: without also +/// appropriately implementing -hash. +/// +/// For the user-facing documentation see: +/// http://clang.llvm.org/extra/clang-tidy/checks/objc-missing-hash.html +class MissingHashCheck : public ClangTidyCheck { +public: + MissingHashCheck(StringRef Name, ClangTidyContext *Context) + : ClangTidyCheck(Name, Context) {} + void registerMatchers(ast_matchers::MatchFinder *Finder) override; + void check(const ast_matchers::MatchFinder::MatchResult &Result) override; +}; + +} // namespace objc +} // namespace tidy +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_OBJC_MISSINGHASHCHECK_H diff --git a/clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp b/clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp index 636e2c02af6..c9b57d5e2c8 100644 --- a/clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp +++ b/clang-tools-extra/clang-tidy/objc/ObjCTidyModule.cpp @@ -12,6 +12,7 @@ #include "AvoidNSErrorInitCheck.h" #include "AvoidSpinlockCheck.h" #include "ForbiddenSubclassingCheck.h" +#include "MissingHashCheck.h" #include "PropertyDeclarationCheck.h" #include "SuperSelfCheck.h" @@ -30,6 +31,8 @@ public: "objc-avoid-spinlock"); CheckFactories.registerCheck<ForbiddenSubclassingCheck>( "objc-forbidden-subclassing"); + CheckFactories.registerCheck<MissingHashCheck>( + "objc-missing-hash"); CheckFactories.registerCheck<PropertyDeclarationCheck>( "objc-property-declaration"); CheckFactories.registerCheck<SuperSelfCheck>( |