diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2012-01-28 18:46:31 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2012-01-28 18:46:31 +0000 |
commit | de2fdc249e9c04757a7aaec029b231f4d7e6dbd7 (patch) | |
tree | 3bd7e701ef2f94c627b4de576e552d2e0c8c08bd /lib/CodeGen/CGObjC.cpp | |
parent | a49a2839266f0bac2b6286e9f49fdc0c292938fe (diff) |
objc-arc: Perform null check on receiver before sending methods which
consume one or more of their arguments. If not done, this will cause a leak
as method will not consume the argument when receiver is null.
// rdar://10444474
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149184 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/CGObjC.cpp')
-rw-r--r-- | lib/CodeGen/CGObjC.cpp | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index 446bef1249..49979f3279 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -136,7 +136,7 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E, bool isDelegateInit = E->isDelegateInitCall(); const ObjCMethodDecl *method = E->getMethodDecl(); - + // We don't retain the receiver in delegate init calls, and this is // safe because the receiver value is always loaded from 'self', // which we zero out. We don't want to Block_copy block receivers, @@ -191,6 +191,19 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E, break; } + // Check to see if receiver must be null checked before method is sent + // to the receiver. + NullReturnState nullReturn; + if (CGM.getLangOptions().ObjCAutoRefCount && method) + for (ObjCMethodDecl::param_const_iterator i = method->param_begin(), + e = method->param_end(); i != e; ++i) { + const ParmVarDecl *ParamDecl = (*i); + if (ParamDecl->hasAttr<NSConsumedAttr>()) { + nullReturn.init(*this, Receiver); + break; + } + } + if (retainSelf) Receiver = EmitARCRetainNonBlock(Receiver); @@ -262,8 +275,8 @@ RValue CodeGenFunction::EmitObjCMessageExpr(const ObjCMessageExpr *E, Builder.CreateStore(newSelf, selfAddr); } - - return AdjustRelatedResultType(*this, E, method, result); + RValue rvalue = AdjustRelatedResultType(*this, E, method, result); + return nullReturn.complete(*this, rvalue, ResultType); } namespace { @@ -292,6 +305,7 @@ struct FinishARCDealloc : EHScopeStack::Cleanup { method); } }; + } /// StartObjCMethod - Begin emission of an ObjCMethod. This generates |