diff options
-rw-r--r-- | include/clang-c/Index.h | 23 | ||||
-rw-r--r-- | tools/libclang/CIndex.cpp | 35 | ||||
-rw-r--r-- | tools/libclang/libclang.exports | 1 |
3 files changed, 59 insertions, 0 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h index bb76c564cc..20c8c11994 100644 --- a/include/clang-c/Index.h +++ b/include/clang-c/Index.h @@ -1828,6 +1828,29 @@ typedef enum CXChildVisitResult (*CXCursorVisitor)(CXCursor cursor, CINDEX_LINKAGE unsigned clang_visitChildren(CXCursor parent, CXCursorVisitor visitor, CXClientData client_data); +#ifdef __has_feature +# if __has_feature(blocks) +/** + * \brief Visitor invoked for each cursor found by a traversal. + * + * This visitor block will be invoked for each cursor found by + * clang_visitChildrenWithBlock(). Its first argument is the cursor being + * visited, its second argument is the parent visitor for that cursor. + * + * The visitor should return one of the \c CXChildVisitResult values + * to direct clang_visitChildrenWithBlock(). + */ +typedef enum CXChildVisitResult + (^CXCursorVisitorBlock)(CXCursor cursor, CXCursor parent); + +/** + * Visits the children of a cursor using the specified block. Behaves + * identically to clang_visitChildren() in all other respects. + */ +unsigned clang_visitChildrenWithBlock(CXCursor parent, + CXCursorVisitorBlock block); +# endif +#endif /** * @} diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index e07c25d77a..ac57a6941c 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -2467,6 +2467,41 @@ unsigned clang_visitChildren(CXCursor parent, return CursorVis.VisitChildren(parent); } +#ifndef __has_feature +#define __has_feature(x) 0 +#endif +#if __has_feature(blocks) +typedef enum CXChildVisitResult + (^CXCursorVisitorBlock)(CXCursor cursor, CXCursor parent); + +static enum CXChildVisitResult visitWithBlock(CXCursor cursor, CXCursor parent, + CXClientData client_data) { + CXCursorVisitorBlock block = (CXCursorVisitorBlock)client_data; + return block(cursor, parent); +} +#else +// If we are compiled with a compiler that doesn't have native blocks support, +// define and call the block manually, so the +typedef struct _CXChildVisitResult +{ + void *isa; + int flags; + int reserved; + enum CXChildVisitResult(*invoke)(struct _CXChildVisitResult*, CXCursor, CXCursor); +} *CXCursorVisitorBlock; + +static enum CXChildVisitResult visitWithBlock(CXCursor cursor, CXCursor parent, + CXClientData client_data) { + CXCursorVisitorBlock block = (CXCursorVisitorBlock)client_data; + return block->invoke(block, cursor, parent); +} +#endif + + +unsigned clang_visitChildrenWithBlock(CXCursor parent, CXCursorVisitorBlock block) { + return clang_visitChildren(parent, visitWithBlock, block); +} + static CXString getDeclSpelling(Decl *D) { NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D); if (!ND) diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index 9935a584b9..fd96be35b2 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -113,3 +113,4 @@ clang_saveTranslationUnit clang_sortCodeCompletionResults clang_tokenize clang_visitChildren +clang_visitChildrenWithBlock |