From: Fariborz Jahanian Date: Fri, 29 Apr 2011 21:53:21 +0000 (+0000) Subject: block variables on lhs need be ir-gen'ed after the X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2c7168c660ab2b961ad48087e02cca96f7bb94d2;p=clang 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 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(E->getLHS())) + if (const VarDecl *VD = dyn_cast(DRE->getDecl())) { + if (VD->hasAttr() && + 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 diff --git a/test/CodeGen/block-byref-aggr.c b/test/CodeGen/block-byref-aggr.c new file mode 100644 index 0000000000..3027df0486 --- /dev/null +++ b/test/CodeGen/block-byref-aggr.c @@ -0,0 +1,17 @@ +// RUN: %clang_cc1 %s -emit-llvm -o - -fblocks -triple x86_64-apple-darwin10 | FileCheck %s +// rdar://9309454 + +typedef struct { int v; } RetType; + +RetType func(); + +int main () { + __attribute__((__blocks__(byref))) RetType a = {100}; + + a = func(); +} +// CHECK: [[C1:%.*]] = call i32 (...)* @func() +// CHECK-NEXT: [[CO:%.*]] = getelementptr +// CHECK-NEXT: store i32 [[C1]], i32* [[CO]] +// CHECK-NEXT: [[FORWARDING:%.*]] = getelementptr inbounds [[BR:%.*]]* [[A:%.*]], i32 0, i32 1 +// CHECK-NEXT: [[O:%.*]] = load [[BR]]** [[FORWARDING]]