]> granicus.if.org Git - clang/commitdiff
Variation of objc_copyStruct API generation when
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 13 Apr 2010 18:32:24 +0000 (18:32 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 13 Apr 2010 18:32:24 +0000 (18:32 +0000)
property (atomic/nonatomic) is of aggregate type with
gc'able member objects) (NeXT runtime).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101156 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGObjC.cpp
lib/CodeGen/CodeGenFunction.h
test/CodeGenObjC/atomic-aggregate-property.m

index ffdcbdcdea629fb5631ac2f5fc7d538c78a7d9d3..c40fe939b655e96623cdb9f8ec6c23bfe7fb22fb 100644 (file)
@@ -148,19 +148,21 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
                                          const ObjCPropertyImplDecl *PID) {
   ObjCIvarDecl *Ivar = PID->getPropertyIvarDecl();
   const ObjCPropertyDecl *PD = PID->getPropertyDecl();
+  bool IsAtomic =
+    !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic);
   ObjCMethodDecl *OMD = PD->getGetterMethodDecl();
   assert(OMD && "Invalid call to generate getter (empty method)");
   // FIXME: This is rather murky, we create this here since they will not have
   // been created by Sema for us.
   OMD->createImplicitParams(getContext(), IMP->getClassInterface());
   StartObjCMethod(OMD, IMP->getClassInterface());
-
+  
   // Determine if we should use an objc_getProperty call for
   // this. Non-atomic properties are directly evaluated.
   // atomic 'copy' and 'retain' properties are also directly
   // evaluated in gc-only mode.
   if (CGM.getLangOptions().getGCMode() != LangOptions::GCOnly &&
-      !(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic) &&
+      IsAtomic &&
       (PD->getSetterKind() == ObjCPropertyDecl::Copy ||
        PD->getSetterKind() == ObjCPropertyDecl::Retain)) {
     llvm::Value *GetPropertyFn =
@@ -208,7 +210,8 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
       StoreComplexToAddr(Pair, ReturnValue, LV.isVolatileQualified());
     }
     else if (hasAggregateLLVMType(Ivar->getType())) {
-      if (!(PD->getPropertyAttributes() & ObjCPropertyDecl::OBJC_PR_nonatomic)
+      bool IsStrong = false;
+      if ((IsAtomic || (IsStrong = IvarTypeWithAggrGCObjects(Ivar->getType())))
           && CurFnInfo->getReturnInfo().getKind() == ABIArgInfo::Indirect
           && CGM.getObjCRuntime().GetCopyStructFunction()) {
         llvm::Value *GetCopyStructFn =
@@ -232,12 +235,15 @@ void CodeGenFunction::GenerateObjCGetter(ObjCImplementationDecl *IMP,
         // FIXME. Implement when Atomic is false; But when struct has
         // gc'able data member!
         llvm::Value *isAtomic =
-          llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 1);
+        llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 
+                               IsAtomic ? 1 : 0);
         Args.push_back(std::make_pair(RValue::get(isAtomic), 
                                       getContext().BoolTy));
-        llvm::Value *False =
-          llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 0);
-        Args.push_back(std::make_pair(RValue::get(False), getContext().BoolTy));
+        llvm::Value *hasStrong =
+          llvm::ConstantInt::get(Types.ConvertType(getContext().BoolTy), 
+                                 IsStrong ? 1 : 0);
+        Args.push_back(std::make_pair(RValue::get(hasStrong), 
+                                      getContext().BoolTy));
         EmitCall(Types.getFunctionInfo(getContext().VoidTy, Args,
                                        FunctionType::ExtInfo()),
                  GetCopyStructFn, ReturnValueSlot(), Args);
@@ -396,6 +402,14 @@ bool CodeGenFunction::IndirectObjCSetterArg(const CGFunctionInfo &FI) {
   return (AI.getKind() == ABIArgInfo::Indirect);
 }
 
+bool CodeGenFunction::IvarTypeWithAggrGCObjects(QualType Ty) {
+  if (CGM.getLangOptions().getGCMode() == LangOptions::NonGC)
+    return false;
+  if (const RecordType *FDTTy = Ty.getTypePtr()->getAs<RecordType>())
+    return FDTTy->getDecl()->hasObjectMember();
+  return false;
+}
+
 llvm::Value *CodeGenFunction::LoadObjCSelf() {
   const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
   // See if we need to lazily forward self inside a block literal.
index 10f100d3f45d6fda503ce36c2a473d1134db7030..793b988f04abb06dc7ad7fd89d15c5a656f3c4a2 100644 (file)
@@ -480,6 +480,7 @@ public:
   void GenerateObjCSetter(ObjCImplementationDecl *IMP,
                           const ObjCPropertyImplDecl *PID);
   bool IndirectObjCSetterArg(const CGFunctionInfo &FI);
+  bool IvarTypeWithAggrGCObjects(QualType Ty);
 
   //===--------------------------------------------------------------------===//
   //                                  Block Bits
index 66762c436f41545a2d11818e27a96e28a29bc43c..2896d379e75a0d8b5897d7f15c37144d3249ac3f 100644 (file)
@@ -1,19 +1,28 @@
-// RUN: %clang_cc1 -triple x86_64-apple-darwin10  -fobjc-nonfragile-abi -emit-llvm -o - %s | FileCheck -check-prefix LP64 %s
+// RUN: %clang_cc1 -triple x86_64-apple-darwin10  -fobjc-nonfragile-abi -fobjc-gc -emit-llvm -o - %s | FileCheck -check-prefix LP64 %s
 // rdar: // 7849824
 
 struct s {
   double a, b, c, d;  
 };
 
+struct s1 {
+    int i;
+    id j;
+    id k;
+};
+
 @interface A 
 @property (readwrite) double x;
 @property (readwrite) struct s y;
+@property (nonatomic, readwrite) struct s1 z;
 @end
 
 @implementation A
 @synthesize x;
 @synthesize y;
+@synthesize z;
 @end
 
 // CHECK-LP64: call void @objc_copyStruct
 // CHECK-LP64: call void @objc_copyStruct
+// CHECK-LP64: call void @objc_copyStruct