]> granicus.if.org Git - clang/commitdiff
block variables on lhs need be ir-gen'ed after the
authorFariborz Jahanian <fjahanian@apple.com>
Fri, 29 Apr 2011 21:53:21 +0000 (21:53 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Fri, 29 Apr 2011 21:53:21 +0000 (21:53 +0000)
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

lib/CodeGen/CGExprAgg.cpp
test/CodeGen/block-byref-aggr.c [new file with mode: 0644]

index 87d3819e489f00415e9383aee14ce46ab380e074..2f2f7c1fe55fe3ab8d83016825816bbc8f0e6c82 100644 (file)
@@ -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
diff --git a/test/CodeGen/block-byref-aggr.c b/test/CodeGen/block-byref-aggr.c
new file mode 100644 (file)
index 0000000..3027df0
--- /dev/null
@@ -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]]