diff options
author | John McCall <rjmccall@apple.com> | 2013-05-03 07:33:41 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2013-05-03 07:33:41 +0000 |
commit | f5ebf9bf1df10ac15ba32a4b24dfe171b7848c58 (patch) | |
tree | b992749c6b861c9c330b77a12113bda06f3b6908 /lib/AST/DeclBase.cpp | |
parent | 2faee99ab67105e834d11df7db80a78a3e3ed37b (diff) |
Correctly emit certain implicit references to 'self' even within
a lambda.
Bug #1 is that CGF's CurFuncDecl was "stuck" at lambda invocation
functions. Fix that by generally improving getNonClosureContext
to look through lambdas and captured statements but only report
code contexts, which is generally what's wanted. Audit uses of
CurFuncDecl and getNonClosureAncestor for correctness.
Bug #2 is that lambdas weren't specially mapping 'self' when inside
an ObjC method. Fix that by removing the requirement for that
and using the normal EmitDeclRefLValue path in LoadObjCSelf.
rdar://13800041
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@181000 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/DeclBase.cpp')
-rw-r--r-- | lib/AST/DeclBase.cpp | 40 |
1 files changed, 28 insertions, 12 deletions
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 402d83683a..8549b17137 100644 --- a/lib/AST/DeclBase.cpp +++ b/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 <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); } //===----------------------------------------------------------------------===// |