]> granicus.if.org Git - clang/commitdiff
objc gc: assigning to an objc object struct member through an ivar
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 30 Sep 2011 18:23:36 +0000 (18:23 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 30 Sep 2011 18:23:36 +0000 (18:23 +0000)
pointer to this struct must go through the none ivar writer barrier.

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

lib/CodeGen/CGExpr.cpp
test/CodeGenObjC/objc2-write-barrier-5.m

index 1f5bb32dea1f11a9e8c9c91de268f463f1b79198..05eb6a38431c63b7bdee2ee73911b1fc3db9e6c1 100644 (file)
@@ -1213,11 +1213,23 @@ void CodeGenFunction::EmitStoreThroughExtVectorComponentLValue(RValue Src,
 // generating write-barries API. It is currently a global, ivar,
 // or neither.
 static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
-                                 LValue &LV) {
+                                 LValue &LV,
+                                 bool IsMemberAccess=false) {
   if (Ctx.getLangOptions().getGC() == LangOptions::NonGC)
     return;
   
   if (isa<ObjCIvarRefExpr>(E)) {
+    QualType ExpTy = E->getType();
+    if (IsMemberAccess && ExpTy->isPointerType()) {
+      // If ivar is a structure pointer, assigning to field of
+      // this struct follows gcc's behavior and makes it a non-ivar 
+      // writer-barrier conservatively.
+      ExpTy = ExpTy->getAs<PointerType>()->getPointeeType();
+      if (ExpTy->isRecordType()) {
+        LV.setObjCIvar(false);
+        return;
+      }
+    }
     LV.setObjCIvar(true);
     ObjCIvarRefExpr *Exp = cast<ObjCIvarRefExpr>(const_cast<Expr*>(E));
     LV.setBaseIvarExp(Exp->getBase());
@@ -1237,12 +1249,12 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
   }
   
   if (const UnaryOperator *Exp = dyn_cast<UnaryOperator>(E)) {
-    setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
+    setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess);
     return;
   }
   
   if (const ParenExpr *Exp = dyn_cast<ParenExpr>(E)) {
-    setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
+    setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess);
     if (LV.isObjCIvar()) {
       // If cast is to a structure pointer, follow gcc's behavior and make it
       // a non-ivar write-barrier.
@@ -1261,17 +1273,17 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
   }
 
   if (const ImplicitCastExpr *Exp = dyn_cast<ImplicitCastExpr>(E)) {
-    setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
+    setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess);
     return;
   }
   
   if (const CStyleCastExpr *Exp = dyn_cast<CStyleCastExpr>(E)) {
-    setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
+    setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess);
     return;
   }
 
   if (const ObjCBridgedCastExpr *Exp = dyn_cast<ObjCBridgedCastExpr>(E)) {
-    setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV);
+    setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV, IsMemberAccess);
     return;
   }
 
@@ -1287,9 +1299,9 @@ static void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E,
       LV.setGlobalObjCRef(false);
     return;
   }
-  
+
   if (const MemberExpr *Exp = dyn_cast<MemberExpr>(E)) {
-    setObjCGCLValueClass(Ctx, Exp->getBase(), LV);
+    setObjCGCLValueClass(Ctx, Exp->getBase(), LV, true);
     // We don't know if member is an 'ivar', but this flag is looked at
     // only in the context of LV.isObjCIvar().
     LV.setObjCArray(E->getType()->isArrayType());
index 373df0cc16b93749f5c31355e5413ee8a8b560db..b4403c1ef6757dee9f69fc515426f3de53db847b 100644 (file)
@@ -1,9 +1,9 @@
 // RUN: %clang_cc1 -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o %t %s
 // RUN: grep objc_assign_ivar %t | count 0
-// RUN: grep objc_assign_strongCast %t | count 5
+// RUN: grep objc_assign_strongCast %t | count 8
 // RUN: %clang_cc1 -x objective-c++ -triple x86_64-apple-darwin10 -fobjc-gc -emit-llvm -o %t %s
 // RUN: grep objc_assign_ivar %t | count 0
-// RUN: grep objc_assign_strongCast %t | count 5
+// RUN: grep objc_assign_strongCast %t | count 8
 
 @interface TestUnarchiver 
 {
@@ -27,3 +27,20 @@ struct unarchive_list {
 }
 
 @end
+
+// rdar://10191569
+@interface I
+{
+  struct S {
+    id _timer;
+  } *p_animationState;
+}
+@end
+
+@implementation I
+- (void) Meth {
+  p_animationState->_timer = 0;
+  (*p_animationState)._timer = 0;
+  (&(*p_animationState))->_timer = 0;
+}
+@end