From d3b25c554a6543b7349f3f1c3cfffd6792cabbdc Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 30 Oct 2008 15:13:43 +0000 Subject: [PATCH] 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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@58431 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Analysis/CheckObjCDealloc.cpp | 54 ++++++++++++++++++++++++------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/lib/Analysis/CheckObjCDealloc.cpp b/lib/Analysis/CheckObjCDealloc.cpp index 617e91b5c3..741fc18964 100644 --- a/lib/Analysis/CheckObjCDealloc.cpp +++ b/lib/Analysis/CheckObjCDealloc.cpp @@ -28,10 +28,11 @@ static bool scan_dealloc(Stmt* S, Selector Dealloc) { if (ObjCMessageExpr* ME = dyn_cast(S)) if (ME->getSelector() == Dealloc) - if (Expr* Receiver = ME->getReceiver()->IgnoreParenCasts()) - if (PredefinedExpr* E = dyn_cast(Receiver)) - if (E->getIdentType() == PredefinedExpr::ObjCSuper) - return true; + if(ME->getReceiver()) + if (Expr* Receiver = ME->getReceiver()->IgnoreParenCasts()) + if (PredefinedExpr* E = dyn_cast(Receiver)) + if (E->getIdentType() == PredefinedExpr::ObjCSuper) + return true; // Recurse to children. @@ -42,17 +43,44 @@ static bool scan_dealloc(Stmt* S, Selector Dealloc) { 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(S)) if (ME->getSelector() == Release) - if (Expr* Receiver = ME->getReceiver()->IgnoreParenCasts()) - if (ObjCIvarRefExpr* E = dyn_cast(Receiver)) - if (E->getDecl() == ID) - return true; + if(ME->getReceiver()) + if (Expr* Receiver = ME->getReceiver()->IgnoreParenCasts()) + if (ObjCIvarRefExpr* E = dyn_cast(Receiver)) + if (E->getDecl() == ID) + return true; + // [self setMyIvar:nil]; + if (ObjCMessageExpr* ME = dyn_cast(S)) + if(ME->getReceiver()) + if (Expr* Receiver = ME->getReceiver()->IgnoreParenCasts()) + if (DeclRefExpr* E = dyn_cast(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(S)) + if (BO->isAssignmentOp()) + if(ObjCPropertyRefExpr* PRE = + dyn_cast(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 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D, 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 @@ void clang::CheckObjCDealloc(ObjCImplementationDecl* D, // 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)"; -- 2.40.0