diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index bceb70306001..5d5d45267a58 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -372,10 +372,13 @@ public: return const_cast(this)->getDeclContext(); } - /// Finds the innermost non-closure context of this declaration. - /// That is, walk out the DeclContext chain, skipping any blocks. - DeclContext *getNonClosureContext(); - const DeclContext *getNonClosureContext() const { + /// Find the innermost non-closure ancestor of this declaration, + /// walking up through blocks, lambdas, etc. If that ancestor is + /// not a code context (!isFunctionOrMethod()), returns null. + /// + /// A declaration may be its own non-closure context. + Decl *getNonClosureContext(); + const Decl *getNonClosureContext() const { return const_cast(this)->getNonClosureContext(); } @@ -1114,8 +1117,8 @@ public: /// \brief Find the nearest non-closure ancestor of this context, /// i.e. the innermost semantic parent of this context which is not /// a closure. A context may be its own non-closure ancestor. - DeclContext *getNonClosureAncestor(); - const DeclContext *getNonClosureAncestor() const { + Decl *getNonClosureAncestor(); + const Decl *getNonClosureAncestor() const { return const_cast(this)->getNonClosureAncestor(); } diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 402d83683aaa..8549b1713745 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -704,21 +704,37 @@ void Decl::CheckAccessDeclContext() const { #endif } -DeclContext *Decl::getNonClosureContext() { - return getDeclContext()->getNonClosureAncestor(); +static Decl::Kind getKind(const Decl *D) { return D->getKind(); } +static Decl::Kind getKind(const DeclContext *DC) { return DC->getDeclKind(); } + +/// Starting at a given context (a Decl or DeclContext), look for a +/// code context that is not a closure (a lambda, block, etc.). +template static Decl *getNonClosureContext(T *D) { + if (getKind(D) == Decl::CXXMethod) { + CXXMethodDecl *MD = cast(D); + if (MD->getParent()->isLambda() && + MD->getOverloadedOperator() == OO_Call) + return getNonClosureContext(MD->getParent()->getParent()); + return MD; + } else if (FunctionDecl *FD = dyn_cast(D)) { + return FD; + } else if (ObjCMethodDecl *MD = dyn_cast(D)) { + return MD; + } else if (BlockDecl *BD = dyn_cast(D)) { + return getNonClosureContext(BD->getParent()); + } else if (CapturedDecl *CD = dyn_cast(D)) { + return getNonClosureContext(CD->getParent()); + } else { + return 0; + } } -DeclContext *DeclContext::getNonClosureAncestor() { - DeclContext *DC = this; +Decl *Decl::getNonClosureContext() { + return ::getNonClosureContext(this); +} - // This is basically "while (DC->isClosure()) DC = DC->getParent();" - // except that it's significantly more efficient to cast to a known - // decl type and call getDeclContext() than to call getParent(). - while (isa(DC)) - DC = cast(DC)->getDeclContext(); - - assert(!DC->isClosure()); - return DC; +Decl *DeclContext::getNonClosureAncestor() { + return ::getNonClosureContext(this); } //===----------------------------------------------------------------------===// diff --git a/clang/lib/CodeGen/CGBlocks.cpp b/clang/lib/CodeGen/CGBlocks.cpp index dd0ef41750d5..ded019e64ae8 100644 --- a/clang/lib/CodeGen/CGBlocks.cpp +++ b/clang/lib/CodeGen/CGBlocks.cpp @@ -695,8 +695,8 @@ llvm::Value *CodeGenFunction::EmitBlockLiteral(const CGBlockInfo &blockInfo) { bool isLambdaConv = blockInfo.getBlockDecl()->isConversionFromLambda(); llvm::Constant *blockFn = CodeGenFunction(CGM, true).GenerateBlockFunction(CurGD, blockInfo, - CurFuncDecl, LocalDeclMap, - isLambdaConv); + LocalDeclMap, + isLambdaConv); blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy); // If there is nothing to capture, we can emit this as a global block. @@ -1034,7 +1034,7 @@ CodeGenModule::GetAddrOfGlobalBlock(const BlockExpr *blockExpr, llvm::DenseMap LocalDeclMap; blockFn = CodeGenFunction(*this).GenerateBlockFunction(GlobalDecl(), blockInfo, - 0, LocalDeclMap, + LocalDeclMap, false); } blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy); @@ -1088,7 +1088,6 @@ static llvm::Constant *buildGlobalBlock(CodeGenModule &CGM, llvm::Function * CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, const CGBlockInfo &blockInfo, - const Decl *outerFnDecl, const DeclMapTy &ldm, bool IsLambdaConversionToBlock) { const BlockDecl *blockDecl = blockInfo.getBlockDecl(); @@ -1148,7 +1147,6 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, // Begin generating the function. StartFunction(blockDecl, fnType->getResultType(), fn, fnInfo, args, blockInfo.getBlockExpr()->getBody()->getLocStart()); - CurFuncDecl = outerFnDecl; // StartFunction sets this to blockDecl // Okay. Undo some of what StartFunction did. @@ -1184,23 +1182,6 @@ CodeGenFunction::GenerateBlockFunction(GlobalDecl GD, CXXThisValue = Builder.CreateLoad(addr, "this"); } - // LoadObjCSelf() expects there to be an entry for 'self' in LocalDeclMap; - // appease it. - if (const ObjCMethodDecl *method - = dyn_cast_or_null(CurFuncDecl)) { - const VarDecl *self = method->getSelfDecl(); - - // There might not be a capture for 'self', but if there is... - if (blockInfo.Captures.count(self)) { - const CGBlockInfo::Capture &capture = blockInfo.getCapture(self); - - llvm::Value *selfAddr = Builder.CreateStructGEP(BlockPointer, - capture.getIndex(), - "block.captured-self"); - LocalDeclMap[self] = selfAddr; - } - } - // Also force all the constant captures. for (BlockDecl::capture_const_iterator ci = blockDecl->capture_begin(), ce = blockDecl->capture_end(); ci != ce; ++ci) { diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index 4b6fe42fccf5..5157dff538dd 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -1196,7 +1196,7 @@ void CodeGenFunction::EmitFunctionProlog(const CGFunctionInfo &FI, // initialize the return value. TODO: it might be nice to have // a more general mechanism for this that didn't require synthesized // return statements. - if (const FunctionDecl *FD = dyn_cast_or_null(CurFuncDecl)) { + if (const FunctionDecl *FD = dyn_cast_or_null(CurCodeDecl)) { if (FD->hasImplicitReturnZero()) { QualType RetTy = FD->getResultType().getUnqualifiedType(); llvm::Type* LLVMTy = CGM.getTypes().ConvertType(RetTy); diff --git a/clang/lib/CodeGen/CGClass.cpp b/clang/lib/CodeGen/CGClass.cpp index 2b9a55b2a698..3fd075701d03 100644 --- a/clang/lib/CodeGen/CGClass.cpp +++ b/clang/lib/CodeGen/CGClass.cpp @@ -290,7 +290,7 @@ llvm::Value *CodeGenFunction::GetVTTParameter(GlobalDecl GD, return 0; } - const CXXRecordDecl *RD = cast(CurFuncDecl)->getParent(); + const CXXRecordDecl *RD = cast(CurCodeDecl)->getParent(); const CXXRecordDecl *Base = cast(GD.getDecl())->getParent(); llvm::Value *VTT; @@ -2232,10 +2232,10 @@ void CodeGenFunction::EmitLambdaBlockInvokeBody() { } void CodeGenFunction::EmitLambdaToBlockPointerBody(FunctionArgList &Args) { - if (cast(CurFuncDecl)->isVariadic()) { + if (cast(CurCodeDecl)->isVariadic()) { // FIXME: Making this work correctly is nasty because it requires either // cloning the body of the call operator or making the call operator forward. - CGM.ErrorUnsupported(CurFuncDecl, "lambda conversion to variadic function"); + CGM.ErrorUnsupported(CurCodeDecl, "lambda conversion to variadic function"); return; } diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index f426a52bcd2d..64670c5e81e4 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -2495,6 +2495,17 @@ LValue CodeGenFunction::EmitMemberExpr(const MemberExpr *E) { llvm_unreachable("Unhandled member declaration!"); } +/// Given that we are currently emitting a lambda, emit an l-value for +/// one of its members. +LValue CodeGenFunction::EmitLValueForLambdaField(const FieldDecl *Field) { + assert(cast(CurCodeDecl)->getParent()->isLambda()); + assert(cast(CurCodeDecl)->getParent() == Field->getParent()); + QualType LambdaTagType = + getContext().getTagDeclType(Field->getParent()); + LValue LambdaLV = MakeNaturalAlignAddrLValue(CXXABIThisValue, LambdaTagType); + return EmitLValueForField(LambdaLV, Field); +} + LValue CodeGenFunction::EmitLValueForField(LValue base, const FieldDecl *field) { if (field->isBitField()) { diff --git a/clang/lib/CodeGen/CGObjC.cpp b/clang/lib/CodeGen/CGObjC.cpp index d0e4cd49dcd5..713509bf6738 100644 --- a/clang/lib/CodeGen/CGObjC.cpp +++ b/clang/lib/CodeGen/CGObjC.cpp @@ -1401,8 +1401,10 @@ bool CodeGenFunction::IvarTypeWithAggrGCObjects(QualType Ty) { } llvm::Value *CodeGenFunction::LoadObjCSelf() { - const ObjCMethodDecl *OMD = cast(CurFuncDecl); - return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self"); + VarDecl *Self = cast(CurFuncDecl)->getSelfDecl(); + DeclRefExpr DRE(Self, /*is enclosing local*/ (CurFuncDecl != CurCodeDecl), + Self->getType(), VK_LValue, SourceLocation()); + return EmitLoadOfScalar(EmitDeclRefLValue(&DRE)); } QualType CodeGenFunction::TypeOfSelfObject() { diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 122e95b26632..493ee91ec7ec 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -471,7 +471,8 @@ void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD, OpenCLKernelMetadata->addOperand(kernelMDNode); } -void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, +void CodeGenFunction::StartFunction(GlobalDecl GD, + QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, @@ -479,7 +480,8 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, const Decl *D = GD.getDecl(); DidCallStackSave = false; - CurCodeDecl = CurFuncDecl = D; + CurCodeDecl = D; + CurFuncDecl = (D ? D->getNonClosureContext() : 0); FnRetTy = RetTy; CurFn = Fn; CurFnInfo = &FnInfo; @@ -578,12 +580,7 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, LambdaThisCaptureField); if (LambdaThisCaptureField) { // If this lambda captures this, load it. - QualType LambdaTagType = - getContext().getTagDeclType(LambdaThisCaptureField->getParent()); - LValue LambdaLV = MakeNaturalAlignAddrLValue(CXXABIThisValue, - LambdaTagType); - LValue ThisLValue = EmitLValueForField(LambdaLV, - LambdaThisCaptureField); + LValue ThisLValue = EmitLValueForLambdaField(LambdaThisCaptureField); CXXThisValue = EmitLoadOfLValue(ThisLValue).getScalarVal(); } } else { diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 17df1dad3ef0..7a8a5a6e0bf9 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -579,8 +579,8 @@ public: typedef std::pair ComplexPairTy; CGBuilderTy Builder; - /// CurFuncDecl - Holds the Decl for the current function or ObjC method. - /// This excludes BlockDecls. + /// CurFuncDecl - Holds the Decl for the current outermost + /// non-closure context. const Decl *CurFuncDecl; /// CurCodeDecl - This is the inner-most code context, which includes blocks. const Decl *CurCodeDecl; @@ -1451,7 +1451,6 @@ public: llvm::Function *GenerateBlockFunction(GlobalDecl GD, const CGBlockInfo &Info, - const Decl *OuterFuncDecl, const DeclMapTy &ldm, bool IsLambdaConversionToBlock); @@ -1482,7 +1481,8 @@ public: void GenerateCode(GlobalDecl GD, llvm::Function *Fn, const CGFunctionInfo &FnInfo); - void StartFunction(GlobalDecl GD, QualType RetTy, + void StartFunction(GlobalDecl GD, + QualType RetTy, llvm::Function *Fn, const CGFunctionInfo &FnInfo, const FunctionArgList &Args, @@ -2379,6 +2379,7 @@ public: llvm::Value *EmitIvarOffset(const ObjCInterfaceDecl *Interface, const ObjCIvarDecl *Ivar); LValue EmitLValueForField(LValue Base, const FieldDecl* Field); + LValue EmitLValueForLambdaField(const FieldDecl *Field); /// EmitLValueForFieldInitialization - Like EmitLValueForField, except that /// if the Field is a reference, this will return the address of the reference diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index fed86eed5176..53dc3d8885ab 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -1334,7 +1334,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, bool Sema::isSelfExpr(Expr *receiver) { // 'self' is objc 'self' in an objc method only. ObjCMethodDecl *method = - dyn_cast(CurContext->getNonClosureAncestor()); + dyn_cast_or_null(CurContext->getNonClosureAncestor()); if (!method) return false; receiver = receiver->IgnoreParenLValueCasts(); diff --git a/clang/test/CodeGenObjC/debug-info-block-captured-self.m b/clang/test/CodeGenObjC/debug-info-block-captured-self.m index 0316013b3102..183e91b6ec57 100644 --- a/clang/test/CodeGenObjC/debug-info-block-captured-self.m +++ b/clang/test/CodeGenObjC/debug-info-block-captured-self.m @@ -59,7 +59,6 @@ typedef enum { // CHECK: call void @llvm.dbg.declare(metadata !{i8* [[BLOCK_DESC]]}, metadata ![[BDMD:[0-9]+]]) // CHECK: %[[TMP1:.*]] = bitcast // CHECK-NEXT: store -// CHECK-NEXT: %[[TMP2:.*]] = getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %[[TMP1]] // CHECK: call void @llvm.dbg.declare(metadata !{<{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>** {{.*}}}, metadata ![[SELF:.*]]) // make sure we are still in the same function // CHECK: define {{.*}}__copy_helper_block_ diff --git a/clang/test/CodeGenObjC/debug-info-blocks.m b/clang/test/CodeGenObjC/debug-info-blocks.m index f50ddf0d8aeb..3d91c9ea5cd4 100644 --- a/clang/test/CodeGenObjC/debug-info-blocks.m +++ b/clang/test/CodeGenObjC/debug-info-blocks.m @@ -7,11 +7,10 @@ // CHECK: define {{.*}}_block_invoke // CHECK: %[[BLOCK:.*]] = bitcast i8* %.block_descriptor to <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>*, !dbg // CHECK-NEXT: store <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %[[BLOCK]], <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>** %[[ALLOCA:.*]], align -// CHECK-NEXT: getelementptr inbounds <{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>* %[[BLOCK]], i32 0, i32 5 // CHECK-NEXT: call void @llvm.dbg.declare(metadata !{<{ i8*, i32, i32, i8*, %struct.__block_descriptor*, %0* }>** %[[ALLOCA]]}, metadata ![[SELF:[0-9]+]]) // CHECK-NEXT: call void @llvm.dbg.declare(metadata !{%1** %d}, metadata ![[D:[0-9]+]]) -// CHECK: ![[SELF]] = {{.*}} [ DW_TAG_auto_variable ] [self] [line 52] -// CHECK: ![[D]] = {{.*}} [d] [line 50] +// CHECK: ![[SELF]] = {{.*}} [ DW_TAG_auto_variable ] [self] [line 51] +// CHECK: ![[D]] = {{.*}} [d] [line 49] typedef unsigned int NSUInteger; diff --git a/clang/test/CodeGenObjCXX/lambda-expressions.mm b/clang/test/CodeGenObjCXX/lambda-expressions.mm index 7c1e2e4f57ff..c73e1727d637 100644 --- a/clang/test/CodeGenObjCXX/lambda-expressions.mm +++ b/clang/test/CodeGenObjCXX/lambda-expressions.mm @@ -38,6 +38,28 @@ void f2() { global = []{ return 3; }; } // ARC: define internal i32 @___Z2f2v_block_invoke // ARC: call i32 @"_ZZ2f2vENK3$_1clEv +template void take_lambda(T &&lambda) { lambda(); } +void take_block(void (^block)()) { block(); } + +// rdar://13800041 +@interface A +- (void) test; +@end +@interface B : A @end +@implementation B +- (void) test { + take_block(^{ + take_lambda([=]{ + take_block(^{ + take_lambda([=] { + [super test]; + }); + }); + }); + }); +} +@end + // ARC: attributes [[NUW]] = { nounwind{{.*}} } // MRC: attributes [[NUW]] = { nounwind{{.*}} }