From: Fariborz Jahanian Date: Wed, 30 Sep 2009 17:10:29 +0000 (+0000) Subject: Make clang produce gcc's objc_assign_StrongCast as a result... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=75b08f169fa47285ce5381091367793ed611195c;p=clang Make clang produce gcc's objc_assign_StrongCast as a result of type-cast of an ivar in assignment. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83150 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp index af8363dbb1..d89da3224f 100644 --- a/lib/CodeGen/CGExpr.cpp +++ b/lib/CodeGen/CGExpr.cpp @@ -719,8 +719,18 @@ void setObjCGCLValueClass(const ASTContext &Ctx, const Expr *E, LValue &LV) { } else if (const UnaryOperator *Exp = dyn_cast(E)) setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV); - else if (const ParenExpr *Exp = dyn_cast(E)) + else if (const ParenExpr *Exp = dyn_cast(E)) { setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV); + if (LV.isObjCIvar()) { + // If cast is to a structure pointer, follow gcc's behavior and make it + // a non-ivar write-barrier. + QualType ExpTy = E->getType(); + if (ExpTy->isPointerType()) + ExpTy = ExpTy->getAs()->getPointeeType(); + if (ExpTy->isRecordType()) + LV.SetObjCIvar(LV, false); + } + } else if (const ImplicitCastExpr *Exp = dyn_cast(E)) setObjCGCLValueClass(Ctx, Exp->getSubExpr(), LV); else if (const CStyleCastExpr *Exp = dyn_cast(E)) diff --git a/test/CodeGenObjC/objc2-write-barrier-5.m b/test/CodeGenObjC/objc2-write-barrier-5.m new file mode 100644 index 0000000000..5b8f02cc1e --- /dev/null +++ b/test/CodeGenObjC/objc2-write-barrier-5.m @@ -0,0 +1,27 @@ +// RUN: clang-cc -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: true + +@interface TestUnarchiver +{ + void *allUnarchivedObjects; +} +@end + +@implementation TestUnarchiver + +struct unarchive_list { + int ifield; + id *list; +}; + +- (id)init { + (*((struct unarchive_list *)allUnarchivedObjects)).list = 0; + ((struct unarchive_list *)allUnarchivedObjects)->list = 0; + (**((struct unarchive_list **)allUnarchivedObjects)).list = 0; + (*((struct unarchive_list **)allUnarchivedObjects))->list = 0; + return 0; +} + +@end