diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/c-index-test/c-index-test.c | 19 | ||||
-rw-r--r-- | tools/libclang/CIndex.cpp | 111 | ||||
-rw-r--r-- | tools/libclang/libclang.darwin.exports | 2 | ||||
-rw-r--r-- | tools/libclang/libclang.exports | 2 |
4 files changed, 133 insertions, 1 deletions
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c index 874c73282c..f83162295d 100644 --- a/tools/c-index-test/c-index-test.c +++ b/tools/c-index-test/c-index-test.c @@ -167,7 +167,9 @@ static void PrintCursor(CXCursor Cursor) { CXCursor Referenced; unsigned line, column; CXCursor SpecializationOf; - + CXCursor *overridden; + unsigned num_overridden; + ks = clang_getCursorKindSpelling(Cursor.kind); string = clang_getCursorSpelling(Cursor); printf("%s=%s", clang_getCString(ks), @@ -251,6 +253,21 @@ static void PrintCursor(CXCursor Cursor) { clang_getCString(Name), line, column); clang_disposeString(Name); } + + clang_getOverriddenCursors(Cursor, &overridden, &num_overridden); + if (num_overridden) { + unsigned I; + printf(" [Overrides "); + for (I = 0; I != num_overridden; ++I) { + CXSourceLocation Loc = clang_getCursorLocation(overridden[I]); + clang_getInstantiationLocation(Loc, 0, &line, &column, 0); + if (I) + printf(", "); + printf("@%d:%d", line, column); + } + printf("]"); + clang_disposeOverriddenCursors(overridden); + } } } diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp index f41906209d..a291f47c01 100644 --- a/tools/libclang/CIndex.cpp +++ b/tools/libclang/CIndex.cpp @@ -4065,6 +4065,117 @@ CXCursor clang_getCursorLexicalParent(CXCursor cursor) { return clang_getNullCursor(); } +static void CollectOverriddenMethods(DeclContext *Ctx, + ObjCMethodDecl *Method, + llvm::SmallVectorImpl<ObjCMethodDecl *> &Methods) { + if (!Ctx) + return; + + // If we have a class or category implementation, jump straight to the + // interface. + if (ObjCImplDecl *Impl = dyn_cast<ObjCImplDecl>(Ctx)) + return CollectOverriddenMethods(Impl->getClassInterface(), Method, Methods); + + ObjCContainerDecl *Container = dyn_cast<ObjCContainerDecl>(Ctx); + if (!Container) + return; + + // Check whether we have a matching method at this level. + if (ObjCMethodDecl *Overridden = Container->getMethod(Method->getSelector(), + Method->isInstanceMethod())) + if (Method != Overridden) { + // We found an override at this level; there is no need to look + // into other protocols or categories. + Methods.push_back(Overridden); + return; + } + + if (ObjCProtocolDecl *Protocol = dyn_cast<ObjCProtocolDecl>(Container)) { + for (ObjCProtocolDecl::protocol_iterator P = Protocol->protocol_begin(), + PEnd = Protocol->protocol_end(); + P != PEnd; ++P) + CollectOverriddenMethods(*P, Method, Methods); + } + + if (ObjCCategoryDecl *Category = dyn_cast<ObjCCategoryDecl>(Container)) { + for (ObjCCategoryDecl::protocol_iterator P = Category->protocol_begin(), + PEnd = Category->protocol_end(); + P != PEnd; ++P) + CollectOverriddenMethods(*P, Method, Methods); + } + + if (ObjCInterfaceDecl *Interface = dyn_cast<ObjCInterfaceDecl>(Container)) { + for (ObjCInterfaceDecl::protocol_iterator P = Interface->protocol_begin(), + PEnd = Interface->protocol_end(); + P != PEnd; ++P) + CollectOverriddenMethods(*P, Method, Methods); + + for (ObjCCategoryDecl *Category = Interface->getCategoryList(); + Category; Category = Category->getNextClassCategory()) + CollectOverriddenMethods(Category, Method, Methods); + + // We only look into the superclass if we haven't found anything yet. + if (Methods.empty()) + if (ObjCInterfaceDecl *Super = Interface->getSuperClass()) + return CollectOverriddenMethods(Super, Method, Methods); + } +} + +void clang_getOverriddenCursors(CXCursor cursor, + CXCursor **overridden, + unsigned *num_overridden) { + if (overridden) + *overridden = 0; + if (num_overridden) + *num_overridden = 0; + if (!overridden || !num_overridden) + return; + + if (!clang_isDeclaration(cursor.kind)) + return; + + Decl *D = getCursorDecl(cursor); + if (!D) + return; + + // Handle C++ member functions. + ASTUnit *CXXUnit = getCursorASTUnit(cursor); + if (CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) { + *num_overridden = CXXMethod->size_overridden_methods(); + if (!*num_overridden) + return; + + *overridden = new CXCursor [*num_overridden]; + unsigned I = 0; + for (CXXMethodDecl::method_iterator + M = CXXMethod->begin_overridden_methods(), + MEnd = CXXMethod->end_overridden_methods(); + M != MEnd; (void)++M, ++I) + (*overridden)[I] = MakeCXCursor(const_cast<CXXMethodDecl*>(*M), CXXUnit); + return; + } + + ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D); + if (!Method) + return; + + // Handle Objective-C methods. + llvm::SmallVector<ObjCMethodDecl *, 4> Methods; + CollectOverriddenMethods(Method->getDeclContext(), Method, Methods); + + if (Methods.empty()) + return; + + *num_overridden = Methods.size(); + *overridden = new CXCursor [Methods.size()]; + for (unsigned I = 0, N = Methods.size(); I != N; ++I) + (*overridden)[I] = MakeCXCursor(Methods[I], CXXUnit); +} + +void clang_disposeOverriddenCursors(CXCursor *overridden) { + delete [] overridden; +} + } // end: extern "C" diff --git a/tools/libclang/libclang.darwin.exports b/tools/libclang/libclang.darwin.exports index da1a6eefc6..d2e246e7e8 100644 --- a/tools/libclang/libclang.darwin.exports +++ b/tools/libclang/libclang.darwin.exports @@ -21,6 +21,7 @@ _clang_defaultSaveOptions _clang_disposeCodeCompleteResults _clang_disposeDiagnostic _clang_disposeIndex +_clang_disposeOverriddenCursors _clang_disposeString _clang_disposeTokens _clang_disposeTranslationUnit @@ -77,6 +78,7 @@ _clang_getNumCompletionChunks _clang_getNumDiagnostics _clang_getNumOverloadedDecls _clang_getOverloadedDecl +_clang_getOverriddenCursors _clang_getPointeeType _clang_getRange _clang_getRangeEnd diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports index 511c85d26f..d8ae1e47b3 100644 --- a/tools/libclang/libclang.exports +++ b/tools/libclang/libclang.exports @@ -21,6 +21,7 @@ clang_defaultSaveOptions clang_disposeCodeCompleteResults clang_disposeDiagnostic clang_disposeIndex +clang_disposeOverriddenCursors clang_disposeString clang_disposeTokens clang_disposeTranslationUnit @@ -77,6 +78,7 @@ clang_getNumCompletionChunks clang_getNumDiagnostics clang_getNumOverloadedDecls clang_getOverloadedDecl +clang_getOverriddenCursors clang_getPointeeType clang_getRange clang_getRangeEnd |