From: Fariborz Jahanian Date: Tue, 13 Apr 2010 18:32:24 +0000 (+0000) Subject: Variation of objc_copyStruct API generation when X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=15bd58842adaa4f8cca4e58047ed18e033858d9b;p=clang Variation of objc_copyStruct API generation when 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 --- diff --git a/lib/CodeGen/CGObjC.cpp b/lib/CodeGen/CGObjC.cpp index ffdcbdcdea..c40fe939b6 100644 --- a/lib/CodeGen/CGObjC.cpp +++ b/lib/CodeGen/CGObjC.cpp @@ -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()) + return FDTTy->getDecl()->hasObjectMember(); + return false; +} + llvm::Value *CodeGenFunction::LoadObjCSelf() { const ObjCMethodDecl *OMD = cast(CurFuncDecl); // See if we need to lazily forward self inside a block literal. diff --git a/lib/CodeGen/CodeGenFunction.h b/lib/CodeGen/CodeGenFunction.h index 10f100d3f4..793b988f04 100644 --- a/lib/CodeGen/CodeGenFunction.h +++ b/lib/CodeGen/CodeGenFunction.h @@ -480,6 +480,7 @@ public: void GenerateObjCSetter(ObjCImplementationDecl *IMP, const ObjCPropertyImplDecl *PID); bool IndirectObjCSetterArg(const CGFunctionInfo &FI); + bool IvarTypeWithAggrGCObjects(QualType Ty); //===--------------------------------------------------------------------===// // Block Bits diff --git a/test/CodeGenObjC/atomic-aggregate-property.m b/test/CodeGenObjC/atomic-aggregate-property.m index 66762c436f..2896d379e7 100644 --- a/test/CodeGenObjC/atomic-aggregate-property.m +++ b/test/CodeGenObjC/atomic-aggregate-property.m @@ -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