Author: kremenek Date: Thu Oct 30 10:13:43 2008 New Revision: 58431 URL: http://llvm.org/viewvc/llvm-project?rev=58431&view=rev Log: Patch by Nikita Zhuk:
Fix PR 2978 false positive for missing release in -dealloc of an ivar retained via a property and then released by assigning nil to that property: http://llvm.org/bugs/show_bug.cgi?id=2978 Modified: cfe/trunk/lib/Analysis/CheckObjCDealloc.cpp Modified: cfe/trunk/lib/Analysis/CheckObjCDealloc.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CheckObjCDealloc.cpp?rev=58431&r1=58430&r2=58431&view=diff ============================================================================== --- cfe/trunk/lib/Analysis/CheckObjCDealloc.cpp (original) +++ cfe/trunk/lib/Analysis/CheckObjCDealloc.cpp Thu Oct 30 10:13:43 2008 @@ -28,10 +28,11 @@ if (ObjCMessageExpr* ME = dyn_cast<ObjCMessageExpr>(S)) if (ME->getSelector() == Dealloc) - if (Expr* Receiver = ME->getReceiver()->IgnoreParenCasts()) - if (PredefinedExpr* E = dyn_cast<PredefinedExpr>(Receiver)) - if (E->getIdentType() == PredefinedExpr::ObjCSuper) - return true; + if(ME->getReceiver()) + if (Expr* Receiver = ME->getReceiver()->IgnoreParenCasts()) + if (PredefinedExpr* E = dyn_cast<PredefinedExpr>(Receiver)) + if (E->getIdentType() == PredefinedExpr::ObjCSuper) + return true; // Recurse to children. @@ -42,17 +43,44 @@ return false; } -static bool scan_ivar_release(Stmt* S, ObjCIvarDecl* ID, Selector Release ) { +static bool scan_ivar_release(Stmt* S, ObjCIvarDecl* ID, + const ObjCPropertyDecl* PD, + Selector Release, + IdentifierInfo* SelfII, + ASTContext& Ctx) { + + // [mMyIvar release] if (ObjCMessageExpr* ME = dyn_cast<ObjCMessageExpr>(S)) if (ME->getSelector() == Release) - if (Expr* Receiver = ME->getReceiver()->IgnoreParenCasts()) - if (ObjCIvarRefExpr* E = dyn_cast<ObjCIvarRefExpr>(Receiver)) - if (E->getDecl() == ID) - return true; + if(ME->getReceiver()) + if (Expr* Receiver = ME->getReceiver()->IgnoreParenCasts()) + if (ObjCIvarRefExpr* E = dyn_cast<ObjCIvarRefExpr>(Receiver)) + if (E->getDecl() == ID) + return true; + // [self setMyIvar:nil]; + if (ObjCMessageExpr* ME = dyn_cast<ObjCMessageExpr>(S)) + if(ME->getReceiver()) + if (Expr* Receiver = ME->getReceiver()->IgnoreParenCasts()) + if (DeclRefExpr* E = dyn_cast<DeclRefExpr>(Receiver)) + if (E->getDecl()->getIdentifier() == SelfII) + if (ME->getMethodDecl() == PD->getSetterMethodDecl() && + ME->getNumArgs() == 1 && + ME->getArg(0)->isNullPointerConstant(Ctx)) + return true; + + // self.myIvar = nil; + if (BinaryOperator* BO = dyn_cast<BinaryOperator>(S)) + if (BO->isAssignmentOp()) + if(ObjCPropertyRefExpr* PRE = + dyn_cast<ObjCPropertyRefExpr>(BO->getLHS()->IgnoreParenCasts())) + if(PRE->getProperty() == PD) + if(BO->getRHS()->isNullPointerConstant(Ctx)) + return true; + // Recurse to children. for (Stmt::child_iterator I = S->child_begin(), E= S->child_end(); I!=E; ++I) - if (*I && scan_ivar_release(*I, ID, Release)) + if (*I && scan_ivar_release(*I, ID, PD, Release, SelfII, Ctx)) return true; return false; @@ -151,6 +179,9 @@ IdentifierInfo* RII = &Ctx.Idents.get("release"); Selector RS = Ctx.Selectors.getSelector(0, &RII); + // Get the "self" identifier + IdentifierInfo* SelfII = &Ctx.Idents.get("self"); + // Scan for missing and extra releases of ivars used by implementations // of synthesized properties for (ObjCImplementationDecl::propimpl_iterator I = D->propimpl_begin(), @@ -178,7 +209,8 @@ // ivar must be released if and only if the kind of setter was not 'assign' bool requiresRelease = PD->getSetterKind() != ObjCPropertyDecl::Assign; - if(scan_ivar_release(MD->getBody(), ID, RS) != requiresRelease) { + if(scan_ivar_release(MD->getBody(), ID, PD, RS, SelfII, Ctx) + != requiresRelease) { const char *name; const char* category = "Memory (Core Foundation/Objective-C)"; _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
