]> granicus.if.org Git - clang/commitdiff
patch for generating objc'2 objc_assign_ivar. WIP.
authorFariborz Jahanian <fjahanian@apple.com>
Wed, 16 Sep 2009 23:11:23 +0000 (23:11 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Wed, 16 Sep 2009 23:11:23 +0000 (23:11 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82090 91177308-0d34-0410-b5e6-96231b3b80d8

lib/CodeGen/CGExpr.cpp
lib/CodeGen/CGObjCMac.cpp
test/CodeGenObjC/objc-assign-ivar.m [new file with mode: 0644]

index 4dc7c265bb3516737e0c6671de6efec7e623e91d..fa3e492416884b1b3ceb28d2cb88a7c91110c7c9 100644 (file)
@@ -492,17 +492,9 @@ void CodeGenFunction::EmitStoreThroughLValue(RValue Src, LValue Dst,
     // load of a __strong object.
     llvm::Value *LvalueDst = Dst.getAddress();
     llvm::Value *src = Src.getScalarVal();
-#if 0
-    // FIXME: We cannot positively determine if we have an 'ivar' assignment,
-    // object assignment or an unknown assignment. For now, generate call to
-    // objc_assign_strongCast assignment which is a safe, but consevative
-    // assumption.
     if (Dst.isObjCIvar())
       CGM.getObjCRuntime().EmitObjCIvarAssign(*this, src, LvalueDst);
-    else
-      CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst);
-#endif
-    if (Dst.isGlobalObjCRef())
+    else if (Dst.isGlobalObjCRef())
       CGM.getObjCRuntime().EmitObjCGlobalAssign(*this, src, LvalueDst);
     else
       CGM.getObjCRuntime().EmitObjCStrongCastAssign(*this, src, LvalueDst);
@@ -703,6 +695,10 @@ void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, LValue &LV) {
       !Ctx.getLangOptions().ObjCNewGCAPI)
     return;
   
+  if (isa<ObjCIvarRefExpr>(E)) {
+    LV.SetObjCIvar(LV, true);
+    return;
+  }
   if (const DeclRefExpr *Exp = dyn_cast<DeclRefExpr>(E)) {
     if (const VarDecl *VD = dyn_cast<VarDecl>(Exp->getDecl())) {
       if ((VD->isBlockVarDecl() && !VD->hasLocalStorage()) ||
@@ -1033,7 +1029,6 @@ EmitExtVectorElementExpr(const ExtVectorElementExpr *E) {
 
 LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
   bool isUnion = false;
-  bool isIvar = false;
   bool isNonGC = false;
   Expr *BaseExpr = E->getBase();
   llvm::Value *BaseValue = NULL;
@@ -1057,8 +1052,6 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
     CVRQualifiers = BaseExpr->getType().getCVRQualifiers();
   } else {
     LValue BaseLV = EmitLValue(BaseExpr);
-    if (BaseLV.isObjCIvar())
-      isIvar = true;
     if (BaseLV.isNonGC())
       isNonGC = true;
     // FIXME: this isn't right for bitfields.
@@ -1074,7 +1067,6 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) {
   assert(Field && "No code generation for non-field member references");
   LValue MemExpLV = EmitLValueForField(BaseValue, Field, isUnion,
                                        CVRQualifiers);
-  LValue::SetObjCIvar(MemExpLV, isIvar);
   LValue::SetObjCNonGC(MemExpLV, isNonGC);
   setObjCGCLValueClass(getContext(), E, MemExpLV);
   return MemExpLV;
@@ -1425,7 +1417,10 @@ LValue CodeGenFunction::EmitObjCIvarRefLValue(const ObjCIvarRefExpr *E) {
     CVRQualifiers = ObjectTy.getCVRQualifiers();
   }
 
-  return EmitLValueForIvar(ObjectTy, BaseValue, E->getDecl(), CVRQualifiers);
+  LValue LV = 
+    EmitLValueForIvar(ObjectTy, BaseValue, E->getDecl(), CVRQualifiers);
+  setObjCGCLValueClass(getContext(), E, LV);
+  return LV;
 }
 
 LValue
index 5f3009074a216fa2e88b173e18276085d03ca165..7fd1198a880b828d87237dccf4d68749db89d917 100644 (file)
@@ -129,7 +129,6 @@ LValue CGObjCRuntime::EmitValueForIvarAtOffset(CodeGen::CodeGenFunction &CGF,
 
   LValue LV = LValue::MakeAddr(V, IvarTy.getCVRQualifiers()|CVRQualifiers,
                                CGF.CGM.getContext().getObjCGCAttrKind(IvarTy));
-  LValue::SetObjCIvar(LV, true);
   return LV;
 }
 
diff --git a/test/CodeGenObjC/objc-assign-ivar.m b/test/CodeGenObjC/objc-assign-ivar.m
new file mode 100644 (file)
index 0000000..f78b2ee
--- /dev/null
@@ -0,0 +1,47 @@
+// RUN: clang-cc -fnext-runtime -fobjc-gc -fobjc-newgc-api -emit-llvm -o %t %s &&
+// RUN: grep -F '@objc_assign_ivar' %t  | count 11 &&
+// RUN: true
+
+typedef struct {
+  id  element;
+  id elementArray[10];
+  __strong id cfElement;
+  __strong id cfElementArray[10];
+} struct_with_ids_t;
+
+
+@interface NSString @end
+
+@interface Foo  {
+@public
+// assignments to any/all of these fields should generate objc_assign_ivar
+  __strong id dict;
+  __strong id dictArray[3];
+  id ivar;
+  id array[10];
+  id nsobject;
+  NSString *stringArray[10];
+  struct_with_ids_t inner;
+}
+@end
+
+// The test cases
+int IvarAssigns;
+void *rhs = 0;
+#define ASSIGNTEST(expr, global) expr = rhs
+
+void testIvars() {
+  Foo *foo;
+  ASSIGNTEST(foo->ivar, IvarAssigns);                                   // objc_assign_ivar
+  ASSIGNTEST(foo->dict, IvarAssigns);                                   // objc_assign_ivar
+  ASSIGNTEST(foo->dictArray[0], IvarAssigns);                           // objc_assign_ivar
+  ASSIGNTEST(foo->array[0], IvarAssigns);                               // objc_assign_ivar
+  ASSIGNTEST(foo->nsobject, IvarAssigns);                               // objc_assign_ivar
+  ASSIGNTEST(foo->stringArray[0], IvarAssigns);                         // objc_assign_ivar
+  ASSIGNTEST(foo->inner.element, IvarAssigns);                          // objc_assign_ivar
+  ASSIGNTEST(foo->inner.elementArray[0], IvarAssigns);                  // objc_assign_ivar
+  ASSIGNTEST(foo->inner.cfElement, IvarAssigns);                        // objc_assign_ivar
+  ASSIGNTEST(foo->inner.cfElementArray[0], IvarAssigns);                // objc_assign_ivar
+
+}
+