diff options
author | John McCall <rjmccall@apple.com> | 2011-02-22 22:25:23 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-02-22 22:25:23 +0000 |
commit | aab9e315184d344bbd733f13b68915d02db7b32b (patch) | |
tree | 48d6c62f5300a7b07b8181f29c484bcdb4b7d94a | |
parent | 1756ce44b0e03d6a6fd2d42add6e3227d4d04d34 (diff) |
Provide a Decl::getNonClosureContext to look through any "closure" (i.e.
block and, eventually, C++ lambda) contexts.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@126252 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | include/clang/AST/DeclBase.h | 11 | ||||
-rw-r--r-- | lib/AST/DeclBase.cpp | 16 |
2 files changed, 27 insertions, 0 deletions
diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index bf249cea9d..b35d134d05 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -299,6 +299,13 @@ public: 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 { + return const_cast<Decl*>(this)->getNonClosureContext(); + } + TranslationUnitDecl *getTranslationUnitDecl(); const TranslationUnitDecl *getTranslationUnitDecl() const { return const_cast<Decl*>(this)->getTranslationUnitDecl(); @@ -787,6 +794,10 @@ public: return cast<Decl>(this)->getASTContext(); } + bool isClosure() const { + return DeclKind == Decl::Block; + } + bool isFunctionOrMethod() const { switch (DeclKind) { case Decl::Block: diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index be379d522d..81df00d6c7 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -465,6 +465,22 @@ void Decl::CheckAccessDeclContext() const { #endif } +DeclContext *Decl::getNonClosureContext() { + DeclContext *DC = getDeclContext(); + + // 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(). + do { + if (isa<BlockDecl>(DC)) { + DC = cast<BlockDecl>(DC)->getDeclContext(); + continue; + } + } while (false); + + assert(!DC->isClosure()); + return DC; +} //===----------------------------------------------------------------------===// // DeclContext Implementation |