aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFariborz Jahanian <fjahanian@apple.com>2011-10-31 23:44:33 +0000
committerFariborz Jahanian <fjahanian@apple.com>2011-10-31 23:44:33 +0000
commitd8c4551fa22a9c346e6a9e56333915197c97e394 (patch)
treea9bcb86538105736401aed5ffdd28c8acb66c8fd
parentc45061bd0c0fdad4df8eea7e9e5af186d11427e5 (diff)
Adds IRGen support for captured rvalue references in blocks.
In this case, temporary value is copied into block descriptor as their own copy to work on. // rdar://9971124 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@143399 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/CGBlocks.cpp30
-rw-r--r--lib/CodeGen/CGExpr.cpp4
-rw-r--r--test/CodeGenCXX/block-rvalue-reference-capture.cpp16
3 files changed, 38 insertions, 12 deletions
diff --git a/lib/CodeGen/CGBlocks.cpp b/lib/CodeGen/CGBlocks.cpp
index 9694953766..19262ec54f 100644
--- a/lib/CodeGen/CGBlocks.cpp
+++ b/lib/CodeGen/CGBlocks.cpp
@@ -380,13 +380,18 @@ static void computeBlockInfo(CodeGenModule &CGM, CGBlockInfo &info) {
}
}
- CharUnits size = C.getTypeSizeInChars(variable->getType());
- CharUnits align = C.getDeclAlign(variable);
+ bool IsRValReference = variable->getType()->isRValueReferenceType();
+ QualType VT =
+ IsRValReference ? variable->getType()->getPointeeType()
+ : variable->getType();
+ CharUnits size = C.getTypeSizeInChars(VT);
+ CharUnits align = C.getDeclAlign(variable, IsRValReference);
+
maxFieldAlign = std::max(maxFieldAlign, align);
llvm::Type *llvmType =
- CGM.getTypes().ConvertTypeForMem(variable->getType());
-
+ CGM.getTypes().ConvertTypeForMem(VT);
+
layout.push_back(BlockLayoutChunk(align, size, &*ci, llvmType));
}
@@ -594,30 +599,32 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const BlockExpr *blockExpr) {
EmitSynthesizedCXXCopyCtor(blockField, src, copyExpr);
// If it's a reference variable, copy the reference into the block field.
- } else if (type->isReferenceType()) {
+ } else if (type->isReferenceType() && !type->isRValueReferenceType()) {
Builder.CreateStore(Builder.CreateLoad(src, "ref.val"), blockField);
// Otherwise, fake up a POD copy into the block field.
} else {
+ QualType VT =
+ (!type->isRValueReferenceType()) ? type : type->getPointeeType();
// Fake up a new variable so that EmitScalarInit doesn't think
// we're referring to the variable in its own initializer.
ImplicitParamDecl blockFieldPseudoVar(/*DC*/ 0, SourceLocation(),
- /*name*/ 0, type);
+ /*name*/ 0, VT);
// We use one of these or the other depending on whether the
// reference is nested.
- DeclRefExpr notNested(const_cast<VarDecl*>(variable), type, VK_LValue,
+ DeclRefExpr notNested(const_cast<VarDecl*>(variable), VT, VK_LValue,
SourceLocation());
- BlockDeclRefExpr nested(const_cast<VarDecl*>(variable), type,
+ BlockDeclRefExpr nested(const_cast<VarDecl*>(variable), VT,
VK_LValue, SourceLocation(), /*byref*/ false);
Expr *declRef =
(ci->isNested() ? static_cast<Expr*>(&nested) : &notNested);
- ImplicitCastExpr l2r(ImplicitCastExpr::OnStack, type, CK_LValueToRValue,
+ ImplicitCastExpr l2r(ImplicitCastExpr::OnStack, VT, CK_LValueToRValue,
declRef, VK_RValue);
EmitExprAsInit(&l2r, &blockFieldPseudoVar,
- MakeAddrLValue(blockField, type,
+ MakeAddrLValue(blockField, VT,
getContext().getDeclAlign(variable)
.getQuantity()),
/*captured by init*/ false);
@@ -789,7 +796,8 @@ llvm::Value *CodeGenFunction::GetAddrOfBlockDecl(const VarDecl *variable,
variable->getNameAsString());
}
- if (variable->getType()->isReferenceType())
+ if (variable->getType()->isReferenceType() &&
+ !variable->getType()->isRValueReferenceType())
addr = Builder.CreateLoad(addr, "ref.tmp");
return addr;
diff --git a/lib/CodeGen/CGExpr.cpp b/lib/CodeGen/CGExpr.cpp
index 9ad3ae8352..9680185b7f 100644
--- a/lib/CodeGen/CGExpr.cpp
+++ b/lib/CodeGen/CGExpr.cpp
@@ -1409,8 +1409,10 @@ LValue CodeGenFunction::EmitDeclRefLValue(const DeclRefExpr *E) {
}
LValue CodeGenFunction::EmitBlockDeclRefLValue(const BlockDeclRefExpr *E) {
+ bool RefAsPointee =
+ E->getDecl()->getType()->isRValueReferenceType() ? true : false;
unsigned Alignment =
- getContext().getDeclAlign(E->getDecl()).getQuantity();
+ getContext().getDeclAlign(E->getDecl(), RefAsPointee).getQuantity();
return MakeAddrLValue(GetAddrOfBlockDecl(E), E->getType(), Alignment);
}
diff --git a/test/CodeGenCXX/block-rvalue-reference-capture.cpp b/test/CodeGenCXX/block-rvalue-reference-capture.cpp
new file mode 100644
index 0000000000..df99e42177
--- /dev/null
+++ b/test/CodeGenCXX/block-rvalue-reference-capture.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 %s -std=c++11 -fblocks -triple x86_64-apple-darwin -emit-llvm -o - | FileCheck %s
+// rdar://9971124
+
+int foo(int && i)
+{
+ return ^{ return i; }();
+}
+
+int main() {
+ return foo(100);
+}
+
+// CHECK: [[B:%.*]] = bitcast i8* [[BD:%.*]] to <{ {{.*}} i32 }>*
+// CHECK: [[C:%.*]] = getelementptr inbounds <{ {{.*}} i32 }>* [[B]]
+// CHECK: [[R:%.*]] = load i32* [[C]], align 4
+// CHECK: ret i32 [[R]]