diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index bf249cea9d5fb0b27d954c4db686f7f6e69c8ad8..b35d134d05345f9ba25f27a0a2cce01ba1c7823d 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -299,6 +299,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 { + return const_cast(this)->getNonClosureContext(); + } + TranslationUnitDecl *getTranslationUnitDecl(); const TranslationUnitDecl *getTranslationUnitDecl() const { return const_cast(this)->getTranslationUnitDecl(); @@ -787,6 +794,10 @@ public: return cast(this)->getASTContext(); } + bool isClosure() const { + return DeclKind == Decl::Block; + } + bool isFunctionOrMethod() const { switch (DeclKind) { case Decl::Block: diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index be379d522dd4658233ab8124ef5fd59f6b233151..81df00d6c7e8ac29f5be6be8ea006ad9bd68e263 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/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(DC)) { + DC = cast(DC)->getDeclContext(); + continue; + } + } while (false); + + assert(!DC->isClosure()); + return DC; +} //===----------------------------------------------------------------------===// // DeclContext Implementation