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

llvm-svn: 149184
diff --git a/clang/lib/CodeGen/CGObjCMac.cpp b/clang/lib/CodeGen/CGObjCMac.cpp
index ecf6181..8bd9638 100644
--- a/clang/lib/CodeGen/CGObjCMac.cpp
+++ b/clang/lib/CodeGen/CGObjCMac.cpp
@@ -1392,63 +1392,6 @@
                                       const ObjCInterfaceDecl *Interface,
                                       const ObjCIvarDecl *Ivar);
 };
-
-/// A helper class for performing the null-initialization of a return
-/// value.
-struct NullReturnState {
-  llvm::BasicBlock *NullBB;
-  llvm::BasicBlock *callBB;
-  NullReturnState() : NullBB(0), callBB(0) {}
-
-  void init(CodeGenFunction &CGF, llvm::Value *receiver) {
-    // Make blocks for the null-init and call edges.
-    NullBB = CGF.createBasicBlock("msgSend.nullinit");
-    callBB = CGF.createBasicBlock("msgSend.call");
-
-    // Check for a null receiver and, if there is one, jump to the
-    // null-init test.
-    llvm::Value *isNull = CGF.Builder.CreateIsNull(receiver);
-    CGF.Builder.CreateCondBr(isNull, NullBB, callBB);
-
-    // Otherwise, start performing the call.
-    CGF.EmitBlock(callBB);
-  }
-
-  RValue complete(CodeGenFunction &CGF, RValue result, QualType resultType) {
-    if (!NullBB) return result;
-
-    // Finish the call path.
-    llvm::BasicBlock *contBB = CGF.createBasicBlock("msgSend.cont");
-    if (CGF.HaveInsertPoint()) CGF.Builder.CreateBr(contBB);
-
-    // Emit the null-init block and perform the null-initialization there.
-    CGF.EmitBlock(NullBB);
-    if (!resultType->isAnyComplexType()) {
-      assert(result.isAggregate() && "null init of non-aggregate result?");
-      CGF.EmitNullInitialization(result.getAggregateAddr(), resultType);
-      // Jump to the continuation block.
-      CGF.EmitBlock(contBB);
-      return result;
-    }
-
-    // _Complex type
-    // FIXME. Now easy to handle any other scalar type whose result is returned
-    // in memory due to ABI limitations.
-    CGF.EmitBlock(contBB);
-    CodeGenFunction::ComplexPairTy CallCV = result.getComplexVal();
-    llvm::Type *MemberType = CallCV.first->getType();
-    llvm::Constant *ZeroCV = llvm::Constant::getNullValue(MemberType);
-    // Create phi instruction for scalar complex value.
-    llvm::PHINode *PHIReal = CGF.Builder.CreatePHI(MemberType, 2);
-    PHIReal->addIncoming(ZeroCV, NullBB);
-    PHIReal->addIncoming(CallCV.first, callBB);
-    llvm::PHINode *PHIImag = CGF.Builder.CreatePHI(MemberType, 2);
-    PHIImag->addIncoming(ZeroCV, NullBB);
-    PHIImag->addIncoming(CallCV.second, callBB);
-    return RValue::getComplex(PHIReal, PHIImag);
-  }
-};
-
 } // end anonymous namespace
 
 /* *** Helper Functions *** */
@@ -1655,7 +1598,23 @@
 
   llvm::Constant *Fn = NULL;
   if (CGM.ReturnTypeUsesSRet(FnInfo)) {
-    if (!IsSuper) nullReturn.init(CGF, Arg0);
+    if (!IsSuper) {
+      bool nullCheckAlreadyDone = false;
+      // We have already done this computation once and flag could have been
+      // passed down. But such cases are extremely rare and we do this lazily,
+      // instead of absorbing cost of passing down a flag for all cases.
+      if (CGM.getLangOptions().ObjCAutoRefCount && Method)
+        for (ObjCMethodDecl::param_const_iterator i = Method->param_begin(), 
+             e = Method->param_end(); i != e; ++i) {
+          if ((*i)->hasAttr<NSConsumedAttr>()) {
+            nullCheckAlreadyDone = true;
+            break;
+          } 
+        }
+      if (!nullCheckAlreadyDone)
+        nullReturn.init(CGF, Arg0);
+    }
+    
     Fn = (ObjCABI == 2) ?  ObjCTypes.getSendStretFn2(IsSuper)
       : ObjCTypes.getSendStretFn(IsSuper);
   } else if (CGM.ReturnTypeUsesFPRet(ResultType)) {