diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2011-04-29 21:53:21 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2011-04-29 21:53:21 +0000 |
commit | 2c7168c660ab2b961ad48087e02cca96f7bb94d2 (patch) | |
tree | 75a0bfc3cf47ff301aae42d85fa36ccee2dcc3a9 /lib/CodeGen/CGExprAgg.cpp | |
parent | 8c367589b68019b040f73d44282fc30e4f526f62 (diff) |
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
Diffstat (limited to 'lib/CodeGen/CGExprAgg.cpp')
-rw-r--r-- | lib/CodeGen/CGExprAgg.cpp | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/lib/CodeGen/CGExprAgg.cpp b/lib/CodeGen/CGExprAgg.cpp index 87d3819e48..2f2f7c1fe5 100644 --- a/lib/CodeGen/CGExprAgg.cpp +++ b/lib/CodeGen/CGExprAgg.cpp @@ -393,7 +393,24 @@ void AggExprEmitter::VisitBinAssign(const BinaryOperator *E) { 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 |