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. 4339a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaksstruct MethodFilter { 44aacadfea7a7174116dbde09937098763a3211396Daniel Jasper virtual ~MethodFilter() {} 4539a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks virtual bool operator()(ObjCMethodDecl *M) { 4639a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks if (M->getMethodFamily() == OMF_init || 4739a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks M->getMethodFamily() == OMF_dealloc || 4839a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks M->getMethodFamily() == OMF_copy || 4939a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks M->getMethodFamily() == OMF_mutableCopy || 5039a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks M->getSelector().getNameForSlot(0).find("init") != StringRef::npos || 5139a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks M->getSelector().getNameForSlot(0).find("Init") != StringRef::npos) 5239a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks return true; 5339a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks return false; 5439a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks } 5539a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks}; 5639a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks 5739a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaksstatic MethodFilter DefaultMethodFilter; 5839a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks 5988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaksclass DirectIvarAssignment : 6088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks public Checker<check::ASTDecl<ObjCImplementationDecl> > { 6188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 6288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks typedef llvm::DenseMap<const ObjCIvarDecl*, 6388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks const ObjCPropertyDecl*> IvarToPropertyMapTy; 6488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 6588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks /// A helper class, which walks the AST and locates all assignments to ivars 6688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks /// in the given function. 6788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks class MethodCrawler : public ConstStmtVisitor<MethodCrawler> { 6888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks const IvarToPropertyMapTy &IvarToPropMap; 6988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks const ObjCMethodDecl *MD; 7088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks const ObjCInterfaceDecl *InterfD; 7188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks BugReporter &BR; 7288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks LocationOrAnalysisDeclContext DCtx; 7388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 7488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks public: 7588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks MethodCrawler(const IvarToPropertyMapTy &InMap, const ObjCMethodDecl *InMD, 7688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks const ObjCInterfaceDecl *InID, 7788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks BugReporter &InBR, AnalysisDeclContext *InDCtx) 7888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks : IvarToPropMap(InMap), MD(InMD), InterfD(InID), BR(InBR), DCtx(InDCtx) {} 7988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 8088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks void VisitStmt(const Stmt *S) { VisitChildren(S); } 8188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 8288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks void VisitBinaryOperator(const BinaryOperator *BO); 8388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 8488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks void VisitChildren(const Stmt *S) { 8588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks for (Stmt::const_child_range I = S->children(); I; ++I) 8688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (*I) 8788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks this->Visit(*I); 8888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks } 8988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks }; 9088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 9188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zakspublic: 9239a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks MethodFilter *ShouldSkipMethod; 9339a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks 9439a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks DirectIvarAssignment() : ShouldSkipMethod(&DefaultMethodFilter) {} 9539a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks 9688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks void checkASTDecl(const ObjCImplementationDecl *D, AnalysisManager& Mgr, 9788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks BugReporter &BR) const; 9888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks}; 9988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 10088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaksstatic const ObjCIvarDecl *findPropertyBackingIvar(const ObjCPropertyDecl *PD, 101bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks const ObjCInterfaceDecl *InterD, 102bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks ASTContext &Ctx) { 10388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks // Check for synthesized ivars. 10488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks ObjCIvarDecl *ID = PD->getPropertyIvarDecl(); 10588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (ID) 10688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks return ID; 10788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 108bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks ObjCInterfaceDecl *NonConstInterD = const_cast<ObjCInterfaceDecl*>(InterD); 109bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks 11088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks // Check for existing "_PropName". 111bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks ID = NonConstInterD->lookupInstanceVariable(PD->getDefaultSynthIvarName(Ctx)); 11288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (ID) 11388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks return ID; 11488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 11588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks // Check for existing "PropName". 11688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks IdentifierInfo *PropIdent = PD->getIdentifier(); 117bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks ID = NonConstInterD->lookupInstanceVariable(PropIdent); 11888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 11988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks return ID; 12088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks} 12188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 12288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaksvoid DirectIvarAssignment::checkASTDecl(const ObjCImplementationDecl *D, 12388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks AnalysisManager& Mgr, 12488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks BugReporter &BR) const { 12588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks const ObjCInterfaceDecl *InterD = D->getClassInterface(); 12688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 12788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 12888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks IvarToPropertyMapTy IvarToPropMap; 12988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 13088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks // Find all properties for this class. 13188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks for (ObjCInterfaceDecl::prop_iterator I = InterD->prop_begin(), 13288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks E = InterD->prop_end(); I != E; ++I) { 13388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks ObjCPropertyDecl *PD = *I; 13488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 13588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks // Find the corresponding IVar. 136bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks const ObjCIvarDecl *ID = findPropertyBackingIvar(PD, InterD, 137bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks Mgr.getASTContext()); 13888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 13988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (!ID) 14088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks continue; 14188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 14288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks // Store the IVar to property mapping. 14388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks IvarToPropMap[ID] = PD; 14488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks } 14588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 14688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (IvarToPropMap.empty()) 14788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks return; 14888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 14988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks for (ObjCImplementationDecl::instmeth_iterator I = D->instmeth_begin(), 15088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks E = D->instmeth_end(); I != E; ++I) { 15188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 15288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks ObjCMethodDecl *M = *I; 15388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks AnalysisDeclContext *DCtx = Mgr.getAnalysisDeclContext(M); 15488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 15539a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks if ((*ShouldSkipMethod)(M)) 15688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks continue; 15788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 15888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks const Stmt *Body = M->getBody(); 159bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks assert(Body); 16088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 16188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks MethodCrawler MC(IvarToPropMap, M->getCanonicalDecl(), InterD, BR, DCtx); 16288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks MC.VisitStmt(Body); 16388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks } 16488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks} 16588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 166fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaksstatic bool isAnnotatedToAllowDirectAssignment(const Decl *D) { 167d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks for (specific_attr_iterator<AnnotateAttr> 168d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks AI = D->specific_attr_begin<AnnotateAttr>(), 169d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks AE = D->specific_attr_end<AnnotateAttr>(); AI != AE; ++AI) { 170d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks const AnnotateAttr *Ann = *AI; 171d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks if (Ann->getAnnotation() == 172d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks "objc_allow_direct_instance_variable_assignment") 173d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks return true; 174d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks } 175d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks return false; 176d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks} 177d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks 17888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaksvoid DirectIvarAssignment::MethodCrawler::VisitBinaryOperator( 17988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks const BinaryOperator *BO) { 18088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (!BO->isAssignmentOp()) 18188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks return; 18288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 183bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks const ObjCIvarRefExpr *IvarRef = 184bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks dyn_cast<ObjCIvarRefExpr>(BO->getLHS()->IgnoreParenCasts()); 18588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 18688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (!IvarRef) 18788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks return; 18888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 18988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (const ObjCIvarDecl *D = IvarRef->getDecl()) { 19088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks IvarToPropertyMapTy::const_iterator I = IvarToPropMap.find(D); 191d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks 19288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (I != IvarToPropMap.end()) { 19388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks const ObjCPropertyDecl *PD = I->second; 194fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks // Skip warnings on Ivars, annotated with 195d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks // objc_allow_direct_instance_variable_assignment. This annotation serves 196fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks // as a false positive suppression mechanism for the checker. The 197fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks // annotation is allowed on properties and ivars. 198fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks if (isAnnotatedToAllowDirectAssignment(PD) || 199fa2b53c5780a8a6f38803a26e3c6f9f0a9ba8b4dAnna Zaks isAnnotatedToAllowDirectAssignment(D)) 200d7b1d2467d8bf01be5068dbbad1a6324cee8bf4aAnna Zaks return; 20188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 20288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks ObjCMethodDecl *GetterMethod = 20388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks InterfD->getInstanceMethod(PD->getGetterName()); 20488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks ObjCMethodDecl *SetterMethod = 20588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks InterfD->getInstanceMethod(PD->getSetterName()); 20688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 20788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (SetterMethod && SetterMethod->getCanonicalDecl() == MD) 20888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks return; 20988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 21088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks if (GetterMethod && GetterMethod->getCanonicalDecl() == MD) 21188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks return; 21288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 21388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks BR.EmitBasicReport(MD, 21488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks "Property access", 21588a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks categories::CoreFoundationObjectiveC, 21688a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks "Direct assignment to an instance variable backing a property; " 217bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks "use the setter instead", PathDiagnosticLocation(IvarRef, 218bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks BR.getSourceManager(), 219bf24792e00a47fd9d74ff21e21d2cbffc6d62818Anna Zaks DCtx)); 22088a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks } 22188a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks } 22288a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks} 22388a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks} 22488a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks 22539a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks// Register the checker that checks for direct accesses in all functions, 22639a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks// except for the initialization and copy routines. 22788a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaksvoid ento::registerDirectIvarAssignment(CheckerManager &mgr) { 22888a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks mgr.registerChecker<DirectIvarAssignment>(); 22988a83e3f3bade5497ff371ed5a570b83d9373e3aAnna Zaks} 23039a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks 23139a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks// Register the checker that checks for direct accesses in functions annotated 232a05d2741c40c71b59cf6d2f8bbc5d433a5d0e6deTed Kremenek// with __attribute__((annotate("objc_no_direct_instance_variable_assignment"))). 23339a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaksnamespace { 23439a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaksstruct InvalidatorMethodFilter : MethodFilter { 235aacadfea7a7174116dbde09937098763a3211396Daniel Jasper virtual ~InvalidatorMethodFilter() {} 23639a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks virtual bool operator()(ObjCMethodDecl *M) { 23739a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks for (specific_attr_iterator<AnnotateAttr> 23839a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks AI = M->specific_attr_begin<AnnotateAttr>(), 23939a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks AE = M->specific_attr_end<AnnotateAttr>(); AI != AE; ++AI) { 24039a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks const AnnotateAttr *Ann = *AI; 241a05d2741c40c71b59cf6d2f8bbc5d433a5d0e6deTed Kremenek if (Ann->getAnnotation() == "objc_no_direct_instance_variable_assignment") 24239a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks return false; 24339a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks } 24439a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks return true; 24539a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks } 24639a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks}; 24739a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks 24839a62fcd3003785d9cc913ab2820be2f6f27bb40Anna ZaksInvalidatorMethodFilter AttrFilter; 24939a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks} 25039a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks 25139a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaksvoid ento::registerDirectIvarAssignmentForAnnotatedFunctions( 25239a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks CheckerManager &mgr) { 25339a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks mgr.registerChecker<DirectIvarAssignment>()->ShouldSkipMethod = &AttrFilter; 25439a62fcd3003785d9cc913ab2820be2f6f27bb40Anna Zaks} 255