summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/CGExpr.cpp17
-rw-r--r--test/SemaCXX/blocks.cpp20
2 files changed, 37 insertions, 0 deletions
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 06c657fa92..b4d0e13993 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -335,6 +335,23 @@ CodeGenFunction::EmitReferenceBindingToExpr(const Expr* E,
llvm::Value *Value = EmitExprForReferenceBinding(*this, E, ReferenceTemporary,
ReferenceTemporaryDtor,
InitializedDecl);
+ if (E->getType()->isBooleanType()) {
+ // special handling for __block variable of bool type bound to
+ // a reference type.
+ bool block_byref_var = false;
+ if (const BlockDeclRefExpr *BE = dyn_cast<BlockDeclRefExpr>(E))
+ block_byref_var = BE->isByRef();
+ else if (const DeclRefExpr *BD = dyn_cast<DeclRefExpr>(E)) {
+ const NamedDecl *ND = BD->getDecl();
+ if (const VarDecl *VD = dyn_cast<VarDecl>(ND))
+ block_byref_var = VD->hasAttr<BlocksAttr>();
+ }
+ if (block_byref_var) {
+ const llvm::Type *T = ConvertTypeForMem(E->getType());
+ T = llvm::PointerType::getUnqual(T);
+ Value = Builder.CreateBitCast(Value, T);
+ }
+ }
if (!ReferenceTemporaryDtor)
return RValue::get(Value);
diff --git a/test/SemaCXX/blocks.cpp b/test/SemaCXX/blocks.cpp
index baa79e7d89..4fd9941a2e 100644
--- a/test/SemaCXX/blocks.cpp
+++ b/test/SemaCXX/blocks.cpp
@@ -41,3 +41,23 @@ namespace test2 {
return Power(2).calculate(10);
}
}
+
+// rdar: // 8382559
+namespace radar8382559 {
+ void func(bool& outHasProperty);
+
+ int test3() {
+ __attribute__((__blocks__(byref))) bool hasProperty = false;
+ bool (^b)() = ^ {
+ func(hasProperty);
+ if (hasProperty)
+ hasProperty = 0;
+ return hasProperty;
+ };
+ func(hasProperty);
+ b();
+ if (hasProperty)
+ hasProperty = 1;
+ return hasProperty = 1;
+ }
+}