1 //===--- ForbiddenSubclassingCheck.cpp - clang-tidy -----------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "ForbiddenSubclassingCheck.h" 10 #include "../utils/OptionsUtils.h" 11 #include "clang/AST/ASTContext.h" 12 #include "clang/ASTMatchers/ASTMatchFinder.h" 13 #include "llvm/ADT/Hashing.h" 14 #include "llvm/ADT/SmallVector.h" 15 16 using namespace clang::ast_matchers; 17 18 namespace clang { 19 namespace tidy { 20 namespace objc { 21 22 namespace { 23 24 constexpr char DefaultForbiddenSuperClassNames[] = 25 "ABNewPersonViewController;" 26 "ABPeoplePickerNavigationController;" 27 "ABPersonViewController;" 28 "ABUnknownPersonViewController;" 29 "NSHashTable;" 30 "NSMapTable;" 31 "NSPointerArray;" 32 "NSPointerFunctions;" 33 "NSTimer;" 34 "UIActionSheet;" 35 "UIAlertView;" 36 "UIImagePickerController;" 37 "UITextInputMode;" 38 "UIWebView"; 39 40 } // namespace 41 42 ForbiddenSubclassingCheck::ForbiddenSubclassingCheck( 43 StringRef Name, 44 ClangTidyContext *Context) 45 : ClangTidyCheck(Name, Context), 46 ForbiddenSuperClassNames( 47 utils::options::parseStringList( 48 Options.get("ClassNames", DefaultForbiddenSuperClassNames))) { 49 } 50 51 void ForbiddenSubclassingCheck::registerMatchers(MatchFinder *Finder) { 52 Finder->addMatcher( 53 objcInterfaceDecl( 54 isDerivedFrom(objcInterfaceDecl(hasAnyName(ForbiddenSuperClassNames)) 55 .bind("superclass"))) 56 .bind("subclass"), 57 this); 58 } 59 60 void ForbiddenSubclassingCheck::check( 61 const MatchFinder::MatchResult &Result) { 62 const auto *SubClass = Result.Nodes.getNodeAs<ObjCInterfaceDecl>( 63 "subclass"); 64 assert(SubClass != nullptr); 65 const auto *SuperClass = Result.Nodes.getNodeAs<ObjCInterfaceDecl>( 66 "superclass"); 67 assert(SuperClass != nullptr); 68 diag(SubClass->getLocation(), 69 "Objective-C interface %0 subclasses %1, which is not " 70 "intended to be subclassed") 71 << SubClass 72 << SuperClass; 73 } 74 75 void ForbiddenSubclassingCheck::storeOptions( 76 ClangTidyOptions::OptionMap &Opts) { 77 Options.store( 78 Opts, 79 "ForbiddenSuperClassNames", 80 utils::options::serializeStringList(ForbiddenSuperClassNames)); 81 } 82 83 } // namespace objc 84 } // namespace tidy 85 } // namespace clang 86