return const_cast<Decl*>(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<Decl*>(this)->getNonClosureContext();
}
/// \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<DeclContext*>(this)->getNonClosureAncestor();
}
#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 <class T> static Decl *getNonClosureContext(T *D) {
+ if (getKind(D) == Decl::CXXMethod) {
+ CXXMethodDecl *MD = cast<CXXMethodDecl>(D);
+ if (MD->getParent()->isLambda() &&
+ MD->getOverloadedOperator() == OO_Call)
+ return getNonClosureContext(MD->getParent()->getParent());
+ return MD;
+ } else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) {
+ return FD;
+ } else if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
+ return MD;
+ } else if (BlockDecl *BD = dyn_cast<BlockDecl>(D)) {
+ return getNonClosureContext(BD->getParent());
+ } else if (CapturedDecl *CD = dyn_cast<CapturedDecl>(D)) {
+ return getNonClosureContext(CD->getParent());
+ } else {
+ return 0;
+ }
}
-DeclContext *DeclContext::getNonClosureAncestor() {
- DeclContext *DC = 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<BlockDecl>(DC))
- DC = cast<BlockDecl>(DC)->getDeclContext();
+Decl *Decl::getNonClosureContext() {
+ return ::getNonClosureContext(this);
+}
- assert(!DC->isClosure());
- return DC;
+Decl *DeclContext::getNonClosureAncestor() {
+ return ::getNonClosureContext(this);
}
//===----------------------------------------------------------------------===//
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.
llvm::DenseMap<const Decl*, llvm::Value*> LocalDeclMap;
blockFn = CodeGenFunction(*this).GenerateBlockFunction(GlobalDecl(),
blockInfo,
- 0, LocalDeclMap,
+ LocalDeclMap,
false);
}
blockFn = llvm::ConstantExpr::getBitCast(blockFn, VoidPtrTy);
llvm::Function *
CodeGenFunction::GenerateBlockFunction(GlobalDecl GD,
const CGBlockInfo &blockInfo,
- const Decl *outerFnDecl,
const DeclMapTy &ldm,
bool IsLambdaConversionToBlock) {
const BlockDecl *blockDecl = blockInfo.getBlockDecl();
// 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.
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<ObjCMethodDecl>(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) {
// 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<FunctionDecl>(CurFuncDecl)) {
+ if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurCodeDecl)) {
if (FD->hasImplicitReturnZero()) {
QualType RetTy = FD->getResultType().getUnqualifiedType();
llvm::Type* LLVMTy = CGM.getTypes().ConvertType(RetTy);
return 0;
}
- const CXXRecordDecl *RD = cast<CXXMethodDecl>(CurFuncDecl)->getParent();
+ const CXXRecordDecl *RD = cast<CXXMethodDecl>(CurCodeDecl)->getParent();
const CXXRecordDecl *Base = cast<CXXMethodDecl>(GD.getDecl())->getParent();
llvm::Value *VTT;
}
void CodeGenFunction::EmitLambdaToBlockPointerBody(FunctionArgList &Args) {
- if (cast<CXXMethodDecl>(CurFuncDecl)->isVariadic()) {
+ if (cast<CXXMethodDecl>(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;
}
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<CXXMethodDecl>(CurCodeDecl)->getParent()->isLambda());
+ assert(cast<CXXMethodDecl>(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()) {
}
llvm::Value *CodeGenFunction::LoadObjCSelf() {
- const ObjCMethodDecl *OMD = cast<ObjCMethodDecl>(CurFuncDecl);
- return Builder.CreateLoad(LocalDeclMap[OMD->getSelfDecl()], "self");
+ VarDecl *Self = cast<ObjCMethodDecl>(CurFuncDecl)->getSelfDecl();
+ DeclRefExpr DRE(Self, /*is enclosing local*/ (CurFuncDecl != CurCodeDecl),
+ Self->getType(), VK_LValue, SourceLocation());
+ return EmitLoadOfScalar(EmitDeclRefLValue(&DRE));
}
QualType CodeGenFunction::TypeOfSelfObject() {
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,
const Decl *D = GD.getDecl();
DidCallStackSave = false;
- CurCodeDecl = CurFuncDecl = D;
+ CurCodeDecl = D;
+ CurFuncDecl = (D ? D->getNonClosureContext() : 0);
FnRetTy = RetTy;
CurFn = Fn;
CurFnInfo = &FnInfo;
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 {
typedef std::pair<llvm::Value *, llvm::Value *> 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;
llvm::Function *GenerateBlockFunction(GlobalDecl GD,
const CGBlockInfo &Info,
- const Decl *OuterFuncDecl,
const DeclMapTy &ldm,
bool IsLambdaConversionToBlock);
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,
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
bool Sema::isSelfExpr(Expr *receiver) {
// 'self' is objc 'self' in an objc method only.
ObjCMethodDecl *method =
- dyn_cast<ObjCMethodDecl>(CurContext->getNonClosureAncestor());
+ dyn_cast_or_null<ObjCMethodDecl>(CurContext->getNonClosureAncestor());
if (!method) return false;
receiver = receiver->IgnoreParenLValueCasts();
// 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_
// 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;
// ARC: define internal i32 @___Z2f2v_block_invoke
// ARC: call i32 @"_ZZ2f2vENK3$_1clEv
+template <class T> 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{{.*}} }