aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2009-09-16 23:11:23 +0000
committerFariborz Jahanian <fjahanian@apple.com>2009-09-16 23:11:23 +0000
commitdbf3cfd39dd5234f90235e263ba2ff4cc61258bd (patch)
treef10ef988934a570c07a230e78504b18c9182f152
parentdd4a3b0065b9a7e7b00073df415a798886c090f3 (diff)
patch for generating objc'2 objc_assign_ivar. WIP.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@82090 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/CGExpr.cpp23
-rw-r--r--lib/CodeGen/CGObjCMac.cpp1
-rw-r--r--test/CodeGenObjC/objc-assign-ivar.m47
3 files changed, 56 insertions, 15 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 4dc7c265bb..fa3e492416 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -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
diff --git a/lib/CodeGen/CGObjCMac.cpp b/lib/CodeGen/CGObjCMac.cpp
index 5f3009074a..7fd1198a88 100644
--- a/lib/CodeGen/CGObjCMac.cpp
+++ b/lib/CodeGen/CGObjCMac.cpp
@@ -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
index 0000000000..f78b2eea6b
--- /dev/null
+++ b/test/CodeGenObjC/objc-assign-ivar.m
@@ -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
+
+}
+