block variables on lhs need be ir-gen'ed after the
rhs when its 'forwarding' pointer may be modified
in rhs evaluation as result of call to Block_copy.
// rdar://9309454
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@130545 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp
index 87d3819..2f2f7c1 100644
--- a/lib/CodeGen/CGExprAgg.cpp
+++ b/lib/CodeGen/CGExprAgg.cpp
@@ -393,7 +393,24 @@
E->getRHS()->getType())
&& "Invalid assignment");
- // FIXME: __block variables need the RHS evaluated first!
+ if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E->getLHS()))
+ if (const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
+ if (VD->hasAttr<BlocksAttr>() &&
+ E->getRHS()->HasSideEffects(CGF.getContext())) {
+ // When __block variable on LHS, the RHS must be evaluated first
+ // as it may change the 'forwarding' field via call to Block_copy.
+ LValue RHS = CGF.EmitLValue(E->getRHS());
+ LValue LHS = CGF.EmitLValue(E->getLHS());
+ bool GCollection = false;
+ if (CGF.getContext().getLangOptions().getGCMode())
+ GCollection = TypeRequiresGCollection(E->getLHS()->getType());
+ // Codegen the RHS so that it stores directly into the LHS.
+ Dest = AggValueSlot::forLValue(LHS, true, GCollection);
+ EmitFinalDestCopy(E, RHS, true);
+ return;
+ }
+ }
+
LValue LHS = CGF.EmitLValue(E->getLHS());
// We have to special case property setters, otherwise we must have