188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks//=- DirectIvarAssignment.cpp - Check rules on ObjC properties -*- C++ ----*-==// 288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks// 388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks// The LLVM Compiler Infrastructure 488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks// 588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks// This file is distributed under the University of Illinois Open Source 688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks// License. See LICENSE.TXT for details. 788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks// 888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks//===----------------------------------------------------------------------===// 988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks// 10fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks// Check that Objective C properties are set with the setter, not though a 11fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks// direct assignment. 12fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks// 13fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks// Two versions of a checker exist: one that checks all methods and the other 14fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks// that only checks the methods annotated with 15fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks// __attribute__((annotate("objc_no_direct_instance_variable_assignment"))) 16fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks// 17fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks// The checker does not warn about assignments to Ivars, annotated with 18fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks// __attribute__((objc_allow_direct_instance_variable_assignment"))). This 19fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks// annotation serves as a false positive suppression mechanism for the 20fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks// checker. The annotation is allowed on properties and Ivars. 2188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks// 2288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks//===----------------------------------------------------------------------===// 2388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 2488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks#include "ClangSACheckers.h" 2539a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks#include "clang/AST/Attr.h" 2688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks#include "clang/AST/DeclObjC.h" 2788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks#include "clang/AST/StmtVisitor.h" 2855fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/BugReporter/BugReporter.h" 2955fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/Checker.h" 3055fc873017f10f6f566b182b70f6fc22aefa3464Chandler Carruth#include "clang/StaticAnalyzer/Core/PathSensitive/AnalysisManager.h" 3188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks#include "llvm/ADT/DenseMap.h" 3288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 3388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaksusing namespace clang; 3488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaksusing namespace ento; 3588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 3688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaksnamespace { 3788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 3839a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks/// The default method filter, which is used to filter out the methods on which 3939a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks/// the check should not be performed. 4039a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks/// 4139a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks/// Checks for the init, dealloc, and any other functions that might be allowed 4239a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks/// to perform direct instance variable assignment based on their name. 43a79a20e054312bc6673d4ddb8254d8d2681bed9cBenjamin Kramerstatic bool DefaultMethodFilter(const ObjCMethodDecl *M) { 44a79a20e054312bc6673d4ddb8254d8d2681bed9cBenjamin Kramer if (M->getMethodFamily() == OMF_init || M->getMethodFamily() == OMF_dealloc || 45a79a20e054312bc6673d4ddb8254d8d2681bed9cBenjamin Kramer M->getMethodFamily() == OMF_copy || 46a79a20e054312bc6673d4ddb8254d8d2681bed9cBenjamin Kramer M->getMethodFamily() == OMF_mutableCopy || 47a79a20e054312bc6673d4ddb8254d8d2681bed9cBenjamin Kramer M->getSelector().getNameForSlot(0).find("init") != StringRef::npos || 48a79a20e054312bc6673d4ddb8254d8d2681bed9cBenjamin Kramer M->getSelector().getNameForSlot(0).find("Init") != StringRef::npos) 49a79a20e054312bc6673d4ddb8254d8d2681bed9cBenjamin Kramer return true; 50a79a20e054312bc6673d4ddb8254d8d2681bed9cBenjamin Kramer return false; 51a79a20e054312bc6673d4ddb8254d8d2681bed9cBenjamin Kramer} 5239a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks 5388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaksclass DirectIvarAssignment : 5488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks public Checker<check::ASTDecl<ObjCImplementationDecl> > { 5588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 5688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks typedef llvm::DenseMap<const ObjCIvarDecl*, 5788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks const ObjCPropertyDecl*> IvarToPropertyMapTy; 5888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 5988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks /// A helper class, which walks the AST and locates all assignments to ivars 6088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks /// in the given function. 6188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks class MethodCrawler : public ConstStmtVisitor<MethodCrawler> { 6288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks const IvarToPropertyMapTy &IvarToPropMap; 6388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks const ObjCMethodDecl *MD; 6488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks const ObjCInterfaceDecl *InterfD; 6588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks BugReporter &BR; 66651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const CheckerBase *Checker; 6788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks LocationOrAnalysisDeclContext DCtx; 6888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 6988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks public: 7088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks MethodCrawler(const IvarToPropertyMapTy &InMap, const ObjCMethodDecl *InMD, 71651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const ObjCInterfaceDecl *InID, BugReporter &InBR, 72651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines const CheckerBase *Checker, AnalysisDeclContext *InDCtx) 73651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines : IvarToPropMap(InMap), MD(InMD), InterfD(InID), BR(InBR), 74651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines Checker(Checker), DCtx(InDCtx) {} 7588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 7688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks void VisitStmt(const Stmt *S) { VisitChildren(S); } 7788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 7888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks void VisitBinaryOperator(const BinaryOperator *BO); 7988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 8088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks void VisitChildren(const Stmt *S) { 81a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar for (const Stmt *Child : S->children()) 82a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar if (Child) 83a4de17562d13d7a8188108243c4cfbd52f33229aPirama Arumuga Nainar this->Visit(Child); 8488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks } 8588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks }; 8688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 8788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zakspublic: 88a79a20e054312bc6673d4ddb8254d8d2681bed9cBenjamin Kramer bool (*ShouldSkipMethod)(const ObjCMethodDecl *); 8939a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks 9039a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks DirectIvarAssignment() : ShouldSkipMethod(&DefaultMethodFilter) {} 9139a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks 9288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks void checkASTDecl(const ObjCImplementationDecl *D, AnalysisManager& Mgr, 9388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks BugReporter &BR) const; 9488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks}; 9588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 9688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaksstatic const ObjCIvarDecl *findPropertyBackingIvar(const ObjCPropertyDecl *PD, 97bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks const ObjCInterfaceDecl *InterD, 98bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks ASTContext &Ctx) { 9988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks // Check for synthesized ivars. 10088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks ObjCIvarDecl *ID = PD->getPropertyIvarDecl(); 10188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (ID) 10288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks return ID; 10388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 104bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks ObjCInterfaceDecl *NonConstInterD = const_cast<ObjCInterfaceDecl*>(InterD); 105bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks 10688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks // Check for existing "_PropName". 107bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks ID = NonConstInterD->lookupInstanceVariable(PD->getDefaultSynthIvarName(Ctx)); 10888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (ID) 10988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks return ID; 11088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 11188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks // Check for existing "PropName". 11288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks IdentifierInfo *PropIdent = PD->getIdentifier(); 113bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks ID = NonConstInterD->lookupInstanceVariable(PropIdent); 11488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 11588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks return ID; 11688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks} 11788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 11888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaksvoid DirectIvarAssignment::checkASTDecl(const ObjCImplementationDecl *D, 11988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks AnalysisManager& Mgr, 12088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks BugReporter &BR) const { 12188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks const ObjCInterfaceDecl *InterD = D->getClassInterface(); 12288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 12388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 12488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks IvarToPropertyMapTy IvarToPropMap; 12588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 12688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks // Find all properties for this class. 127651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *PD : InterD->properties()) { 12888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks // Find the corresponding IVar. 129bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks const ObjCIvarDecl *ID = findPropertyBackingIvar(PD, InterD, 130bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks Mgr.getASTContext()); 13188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 13288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (!ID) 13388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks continue; 13488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 13588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks // Store the IVar to property mapping. 13688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks IvarToPropMap[ID] = PD; 13788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks } 13888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 13988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (IvarToPropMap.empty()) 14088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks return; 14188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 142651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *M : D->instance_methods()) { 14388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks AnalysisDeclContext *DCtx = Mgr.getAnalysisDeclContext(M); 14488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 14539a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks if ((*ShouldSkipMethod)(M)) 14688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks continue; 14788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 14888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks const Stmt *Body = M->getBody(); 149bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks assert(Body); 15088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 151651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines MethodCrawler MC(IvarToPropMap, M->getCanonicalDecl(), InterD, BR, this, 152651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines DCtx); 15388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks MC.VisitStmt(Body); 15488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks } 15588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks} 15688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 157fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaksstatic bool isAnnotatedToAllowDirectAssignment(const Decl *D) { 158651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *Ann : D->specific_attrs<AnnotateAttr>()) 159d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks if (Ann->getAnnotation() == 160d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks "objc_allow_direct_instance_variable_assignment") 161d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks return true; 162d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks return false; 163d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks} 164d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks 16588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaksvoid DirectIvarAssignment::MethodCrawler::VisitBinaryOperator( 16688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks const BinaryOperator *BO) { 16788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (!BO->isAssignmentOp()) 16888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks return; 16988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 170bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks const ObjCIvarRefExpr *IvarRef = 171bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks dyn_cast<ObjCIvarRefExpr>(BO->getLHS()->IgnoreParenCasts()); 17288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 17388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (!IvarRef) 17488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks return; 17588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 17688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (const ObjCIvarDecl *D = IvarRef->getDecl()) { 17788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks IvarToPropertyMapTy::const_iterator I = IvarToPropMap.find(D); 178d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks 17988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (I != IvarToPropMap.end()) { 18088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks const ObjCPropertyDecl *PD = I->second; 181fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks // Skip warnings on Ivars, annotated with 182d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks // objc_allow_direct_instance_variable_assignment. This annotation serves 183fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks // as a false positive suppression mechanism for the checker. The 184fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks // annotation is allowed on properties and ivars. 185fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks if (isAnnotatedToAllowDirectAssignment(PD) || 186fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks isAnnotatedToAllowDirectAssignment(D)) 187d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks return; 18888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 18988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks ObjCMethodDecl *GetterMethod = 19088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks InterfD->getInstanceMethod(PD->getGetterName()); 19188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks ObjCMethodDecl *SetterMethod = 19288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks InterfD->getInstanceMethod(PD->getSetterName()); 19388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 19488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (SetterMethod && SetterMethod->getCanonicalDecl() == MD) 19588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks return; 19688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 19788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (GetterMethod && GetterMethod->getCanonicalDecl() == MD) 19888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks return; 19988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 200651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines BR.EmitBasicReport( 201651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines MD, Checker, "Property access", categories::CoreFoundationObjectiveC, 20288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks "Direct assignment to an instance variable backing a property; " 203651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines "use the setter instead", 204651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines PathDiagnosticLocation(IvarRef, BR.getSourceManager(), DCtx)); 20588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks } 20688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks } 20788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks} 20888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks} 20988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 21039a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks// Register the checker that checks for direct accesses in all functions, 21139a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks// except for the initialization and copy routines. 21288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaksvoid ento::registerDirectIvarAssignment(CheckerManager &mgr) { 21388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks mgr.registerChecker<DirectIvarAssignment>(); 21488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks} 21539a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks 21639a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks// Register the checker that checks for direct accesses in functions annotated 217a05d2741c40c71b59cf6d2f8bbc5d433a5d0e6deTed Kremenek// with __attribute__((annotate("objc_no_direct_instance_variable_assignment"))). 218a79a20e054312bc6673d4ddb8254d8d2681bed9cBenjamin Kramerstatic bool AttrFilter(const ObjCMethodDecl *M) { 219651f13cea278ec967336033dd032faef0e9fc2ecStephen Hines for (const auto *Ann : M->specific_attrs<AnnotateAttr>()) 220a79a20e054312bc6673d4ddb8254d8d2681bed9cBenjamin Kramer if (Ann->getAnnotation() == "objc_no_direct_instance_variable_assignment") 221a79a20e054312bc6673d4ddb8254d8d2681bed9cBenjamin Kramer return false; 222a79a20e054312bc6673d4ddb8254d8d2681bed9cBenjamin Kramer return true; 22339a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks} 22439a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks 22539a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaksvoid ento::registerDirectIvarAssignmentForAnnotatedFunctions( 22639a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks CheckerManager &mgr) { 22739a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks mgr.registerChecker<DirectIvarAssignment>()->ShouldSkipMethod = &AttrFilter; 22839a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks} 229