diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2011-10-31 23:44:33 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2011-10-31 23:44:33 +0000 |
commit | d8c4551fa22a9c346e6a9e56333915197c97e394 (patch) | |
tree | a9bcb86538105736401aed5ffdd28c8acb66c8fd /lib/CodeGen/CGBlocks.cpp | |
parent | c45061bd0c0fdad4df8eea7e9e5af186d11427e5 (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
Diffstat (limited to 'lib/CodeGen/CGBlocks.cpp')
-rw-r--r-- | lib/CodeGen/CGBlocks.cpp | 30 |
1 files changed, 19 insertions, 11 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) : ¬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; |