Patch adds support for copying of those
objective-c++ class objects which have GC'able objc object
pointers and need to use ObjC's objc_memmove_collectable
API (radar 8070772). 

llvm-svn: 106061
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index d1818b8..e3d20bd 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -6232,6 +6232,12 @@
                (FD->getType()->isObjCObjectPointerType() ||
                 FD->getType().isObjCGCStrong()))
       Record->setHasObjectMember(true);
+    else if (Context.getAsArrayType(FD->getType())) {
+      QualType BaseType = Context.getBaseElementType(FD->getType());
+      if (Record && BaseType->isRecordType() && 
+          BaseType->getAs<RecordType>()->getDecl()->hasObjectMember())
+        Record->setHasObjectMember(true);
+    }
     // Keep track of the number of named members.
     if (FD->getIdentifier())
       ++NumNamedMembers;
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index aa2be17..0fb30d8 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -4557,6 +4557,8 @@
   
   // \brief Reference to the __builtin_memcpy function.
   Expr *BuiltinMemCpyRef = 0;
+  // \brief Reference to the objc_memmove_collectable function.
+  Expr *CollectableMemCpyRef = 0;
   
   // Assign non-static members.
   for (CXXRecordDecl::field_iterator Field = ClassDecl->field_begin(),
@@ -4633,9 +4635,34 @@
       // Take the address of the field references for "from" and "to".
       From = CreateBuiltinUnaryOp(Loc, UnaryOperator::AddrOf, move(From));
       To = CreateBuiltinUnaryOp(Loc, UnaryOperator::AddrOf, move(To));
-      
+          
+      bool NeedsCollectableMemCpy = 
+          (BaseType->isRecordType() && 
+           BaseType->getAs<RecordType>()->getDecl()->hasObjectMember());
+          
+      if (NeedsCollectableMemCpy) {
+        if (!CollectableMemCpyRef) {
+          // Create a reference to the objc_memmove_collectable function.
+          LookupResult R(*this, &Context.Idents.get("objc_memmove_collectable"), 
+                         Loc, LookupOrdinaryName);
+          LookupName(R, TUScope, true);
+        
+          FunctionDecl *CollectableMemCpy = R.getAsSingle<FunctionDecl>();
+          if (!CollectableMemCpy) {
+            // Something went horribly wrong earlier, and we will have 
+            // complained about it.
+            Invalid = true;
+            continue;
+          }
+        
+          CollectableMemCpyRef = BuildDeclRefExpr(CollectableMemCpy, 
+                                                  CollectableMemCpy->getType(),
+                                                  Loc, 0).takeAs<Expr>();
+          assert(CollectableMemCpyRef && "Builtin reference cannot fail");
+        }
+      }
       // Create a reference to the __builtin_memcpy builtin function.
-      if (!BuiltinMemCpyRef) {
+      else if (!BuiltinMemCpyRef) {
         LookupResult R(*this, &Context.Idents.get("__builtin_memcpy"), Loc,
                        LookupOrdinaryName);
         LookupName(R, TUScope, true);
@@ -4661,10 +4688,12 @@
       llvm::SmallVector<SourceLocation, 4> Commas; // FIXME: Silly
       Commas.push_back(Loc);
       Commas.push_back(Loc);
-      OwningExprResult Call = ActOnCallExpr(/*Scope=*/0, 
-                                            Owned(BuiltinMemCpyRef->Retain()),
-                                            Loc, move_arg(CallArgs), 
-                                            Commas.data(), Loc);
+      OwningExprResult Call = ActOnCallExpr(/*Scope=*/0,
+                                  NeedsCollectableMemCpy ?
+                                    Owned(CollectableMemCpyRef->Retain()) :
+                                    Owned(BuiltinMemCpyRef->Retain()),
+                                  Loc, move_arg(CallArgs), 
+                                  Commas.data(), Loc);
       assert(!Call.isInvalid() && "Call to __builtin_memcpy cannot fail!");
       Statements.push_back(Call.takeAs<Expr>());
       continue;