зеркало из https://github.com/microsoft/clang-1.git
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
This commit is contained in:
Родитель
c45061bd0c
Коммит
d8c4551fa2
|
@ -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) : ¬Nested);
|
||||
|
||||
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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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]]
|
Загрузка…
Ссылка в новой задаче