Automatic Reference Counting.

Language-design credit goes to a lot of people, but I particularly want
to single out Blaine Garst and Patrick Beard for their contributions.

Compiler implementation credit goes to Argyrios, Doug, Fariborz, and myself,
in no particular order.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133103 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGClass.cpp b/lib/CodeGen/CGClass.cpp
index 5725d80..066f0d5 100644
--- a/lib/CodeGen/CGClass.cpp
+++ b/lib/CodeGen/CGClass.cpp
@@ -398,7 +398,8 @@
                                               BaseClassDecl,
                                               isBaseVirtual);
 
-  AggValueSlot AggSlot = AggValueSlot::forAddr(V, false, /*Lifetime*/ true);
+  AggValueSlot AggSlot = AggValueSlot::forAddr(V, Qualifiers(), 
+                                               /*Lifetime*/ true);
 
   CGF.EmitAggExpr(BaseInit->getInit(), AggSlot);
   
@@ -428,10 +429,20 @@
       CGF.Builder.CreateStore(Next, ArrayIndexVar);      
     }
 
-    AggValueSlot Slot = AggValueSlot::forAddr(Dest, LHS.isVolatileQualified(),
-                                              /*Lifetime*/ true);
-    
-    CGF.EmitAggExpr(MemberInit->getInit(), Slot);
+    if (!CGF.hasAggregateLLVMType(T)) {
+      CGF.EmitScalarInit(MemberInit->getInit(), 0, Dest, false, 
+                         LHS.isVolatileQualified(), 
+                         CGF.getContext().getTypeAlign(T),
+                         T);
+    } else if (T->isAnyComplexType()) {
+      CGF.EmitComplexExprIntoAddr(MemberInit->getInit(), Dest, 
+                                  LHS.isVolatileQualified());
+    } else {    
+      AggValueSlot Slot = AggValueSlot::forAddr(Dest, LHS.getQuals(),
+                                                /*Lifetime*/ true);
+      
+      CGF.EmitAggExpr(MemberInit->getInit(), Slot);
+    }
     
     return;
   }
@@ -540,15 +551,16 @@
 
   // FIXME: If there's no initializer and the CXXCtorInitializer
   // was implicitly generated, we shouldn't be zeroing memory.
-  RValue RHS;
-  if (FieldType->isReferenceType()) {
-    RHS = CGF.EmitReferenceBindingToExpr(MemberInit->getInit(), Field);
-    CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
-  } else if (FieldType->isArrayType() && !MemberInit->getInit()) {
+  if (FieldType->isArrayType() && !MemberInit->getInit()) {
     CGF.EmitNullInitialization(LHS.getAddress(), Field->getType());
   } else if (!CGF.hasAggregateLLVMType(Field->getType())) {
-    RHS = RValue::get(CGF.EmitScalarExpr(MemberInit->getInit()));
-    CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
+    if (LHS.isSimple()) {
+      CGF.EmitExprAsInit(MemberInit->getInit(), Field, LHS.getAddress(),
+                         CGF.getContext().getDeclAlign(Field), false);
+    } else {
+      RValue RHS = RValue::get(CGF.EmitScalarExpr(MemberInit->getInit()));
+      CGF.EmitStoreThroughLValue(RHS, LHS, FieldType);
+    }
   } else if (MemberInit->getInit()->getType()->isAnyComplexType()) {
     CGF.EmitComplexExprIntoAddr(MemberInit->getInit(), LHS.getAddress(),
                                 LHS.isVolatileQualified());
@@ -576,11 +588,11 @@
       llvm::Value *Zero = llvm::Constant::getNullValue(SizeTy);
       CGF.Builder.CreateStore(Zero, ArrayIndexVar);
       
-      // If we are copying an array of scalars or classes with trivial copy 
+      // If we are copying an array of PODs or classes with trivial copy 
       // constructors, perform a single aggregate copy.
-      const RecordType *Record = BaseElementTy->getAs<RecordType>();
-      if (!Record || 
-          cast<CXXRecordDecl>(Record->getDecl())->hasTrivialCopyConstructor()) {
+      const CXXRecordDecl *Record = BaseElementTy->getAsCXXRecordDecl();
+      if (BaseElementTy.isPODType(CGF.getContext()) ||
+          (Record && Record->hasTrivialCopyConstructor())) {
         // Find the source pointer. We knows it's the last argument because
         // we know we're in a copy constructor.
         unsigned SrcArgIndex = Args.size() - 1;
@@ -925,12 +937,8 @@
     CallArrayFieldDtor(const FieldDecl *Field) : Field(Field) {}
 
     void Emit(CodeGenFunction &CGF, bool IsForEH) {
-      QualType FieldType = Field->getType();
-      const ConstantArrayType *Array =
-        CGF.getContext().getAsConstantArrayType(FieldType);
-      
-      QualType BaseType =
-        CGF.getContext().getBaseElementType(Array->getElementType());
+      QualType FieldType = Field->getType();      
+      QualType BaseType = CGF.getContext().getBaseElementType(FieldType);
       const CXXRecordDecl *FieldClassDecl = BaseType->getAsCXXRecordDecl();
 
       llvm::Value *ThisPtr = CGF.LoadCXXThis();
@@ -938,9 +946,12 @@
                                           // FIXME: Qualifiers?
                                           /*CVRQualifiers=*/0);
 
-      const llvm::Type *BasePtr = CGF.ConvertType(BaseType)->getPointerTo();
-      llvm::Value *BaseAddrPtr =
-        CGF.Builder.CreateBitCast(LHS.getAddress(), BasePtr);
+      const llvm::Type *BasePtr 
+        = CGF.ConvertType(BaseType)->getPointerTo();
+      llvm::Value *BaseAddrPtr
+        = CGF.Builder.CreateBitCast(LHS.getAddress(), BasePtr);
+      const ConstantArrayType *Array
+        = CGF.getContext().getAsConstantArrayType(FieldType);
       CGF.EmitCXXAggrDestructorCall(FieldClassDecl->getDestructor(),
                                     Array, BaseAddrPtr);
     }
@@ -1042,19 +1053,26 @@
       getContext().getAsConstantArrayType(FieldType);
     if (Array)
       FieldType = getContext().getBaseElementType(Array->getElementType());
-    
-    const RecordType *RT = FieldType->getAs<RecordType>();
-    if (!RT)
-      continue;
-    
-    CXXRecordDecl *FieldClassDecl = cast<CXXRecordDecl>(RT->getDecl());
-    if (FieldClassDecl->hasTrivialDestructor())
-        continue;
 
-    if (Array)
-      EHStack.pushCleanup<CallArrayFieldDtor>(NormalAndEHCleanup, Field);
-    else
-      EHStack.pushCleanup<CallFieldDtor>(NormalAndEHCleanup, Field);
+    switch (FieldType.isDestructedType()) {
+    case QualType::DK_none:
+      continue;
+        
+    case QualType::DK_cxx_destructor:
+      if (Array)
+        EHStack.pushCleanup<CallArrayFieldDtor>(NormalAndEHCleanup, Field);
+      else
+        EHStack.pushCleanup<CallFieldDtor>(NormalAndEHCleanup, Field);
+      break;
+        
+    case QualType::DK_objc_strong_lifetime:
+      PushARCFieldReleaseCleanup(getARCCleanupKind(), Field);
+      break;
+
+    case QualType::DK_objc_weak_lifetime:
+      PushARCFieldWeakReleaseCleanup(getARCCleanupKind(), Field);
+      break;
+    }
   }
 }
 
@@ -1384,7 +1402,8 @@
 
   llvm::Value *ThisPtr = LoadCXXThis();
 
-  AggValueSlot AggSlot = AggValueSlot::forAddr(ThisPtr, false, /*Lifetime*/ true);
+  AggValueSlot AggSlot =
+    AggValueSlot::forAddr(ThisPtr, Qualifiers(), /*Lifetime*/ true);
 
   EmitAggExpr(Ctor->init_begin()[0]->getInit(), AggSlot);