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