From: Fariborz Jahanian Date: Mon, 31 Oct 2011 23:44:33 +0000 (+0000) Subject: Adds IRGen support for captured rvalue references in blocks. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d8c4551fa22a9c346e6a9e56333915197c97e394;p=clang 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 --- 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(variable), type, VK_LValue, + DeclRefExpr notNested(const_cast(variable), VT, VK_LValue, SourceLocation()); - BlockDeclRefExpr nested(const_cast(variable), type, + BlockDeclRefExpr nested(const_cast(variable), VT, VK_LValue, SourceLocation(), /*byref*/ false); Expr *declRef = (ci->isNested() ? static_cast(&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; 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]]