[cfe-commits] r115338 - in /cfe/trunk: include/clang-c/Index.h test/Index/local-symbols.m test/Index/overrides.cpp test/Index/overrides.m test/Index/properties-class-extensions.m tools/c-index-test/c-index-test.c tools/libclang/CIndex.cpp tools/libclang/libclang.darwin.exports tools/libclang/libclang.exports
Douglas Gregor
dgregor at apple.com
Fri Oct 1 13:25:15 PDT 2010
Author: dgregor
Date: Fri Oct 1 15:25:15 2010
New Revision: 115338
URL: http://llvm.org/viewvc/llvm-project?rev=115338&view=rev
Log:
Extend libclang with an API that determines, given a C++ virtual
member function or an Objective-C method, which other member
functions/methods it overrides.
Added:
cfe/trunk/test/Index/overrides.cpp
cfe/trunk/test/Index/overrides.m
Modified:
cfe/trunk/include/clang-c/Index.h
cfe/trunk/test/Index/local-symbols.m
cfe/trunk/test/Index/properties-class-extensions.m
cfe/trunk/tools/c-index-test/c-index-test.c
cfe/trunk/tools/libclang/CIndex.cpp
cfe/trunk/tools/libclang/libclang.darwin.exports
cfe/trunk/tools/libclang/libclang.exports
Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=115338&r1=115337&r2=115338&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Fri Oct 1 15:25:15 2010
@@ -1417,7 +1417,59 @@
* and the lexical context of the second \c C::f is the translation unit.
*/
CINDEX_LINKAGE CXCursor clang_getCursorLexicalParent(CXCursor cursor);
-
+
+/**
+ * \brief Determine the set of methods that are overridden by the given
+ * method.
+ *
+ * In both Objective-C and C++, a method (aka virtual member function,
+ * in C++) can override a virtual method in a base class. For
+ * Objective-C, a method is said to override any method in the class's
+ * interface (if we're coming from an implementation), its protocols,
+ * or its categories, that has the same selector and is of the same
+ * kind (class or instance). If no such method exists, the search
+ * continues to the class's superclass, its protocols, and its
+ * categories, and so on.
+ *
+ * For C++, a virtual member function overrides any virtual member
+ * function with the same signature that occurs in its base
+ * classes. With multiple inheritance, a virtual member function can
+ * override several virtual member functions coming from different
+ * base classes.
+ *
+ * In all cases, this function determines the immediate overridden
+ * method, rather than all of the overridden methods. For example, if
+ * a method is originally declared in a class A, then overridden in B
+ * (which in inherits from A) and also in C (which inherited from B),
+ * then the only overridden method returned from this function when
+ * invoked on C's method will be B's method. The client may then
+ * invoke this function again, given the previously-found overridden
+ * methods, to map out the complete method-override set.
+ *
+ * \param cursor A cursor representing an Objective-C or C++
+ * method. This routine will compute the set of methods that this
+ * method overrides.
+ *
+ * \param overridden A pointer whose pointee will be replaced with a
+ * pointer to an array of cursors, representing the set of overridden
+ * methods. If there are no overridden methods, the pointee will be
+ * set to NULL. The pointee must be freed via a call to
+ * \c clang_disposeOverriddenCursors().
+ *
+ * \param num_overridden A pointer to the number of overridden
+ * functions, will be set to the number of overridden functions in the
+ * array pointed to by \p overridden.
+ */
+CINDEX_LINKAGE void clang_getOverriddenCursors(CXCursor cursor,
+ CXCursor **overridden,
+ unsigned *num_overridden);
+
+/**
+ * \brief Free the set of overridden cursors returned by \c
+ * clang_getOverriddenCursors().
+ */
+CINDEX_LINKAGE void clang_disposeOverriddenCursors(CXCursor *overridden);
+
/**
* @}
*/
Modified: cfe/trunk/test/Index/local-symbols.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/local-symbols.m?rev=115338&r1=115337&r2=115338&view=diff
==============================================================================
--- cfe/trunk/test/Index/local-symbols.m (original)
+++ cfe/trunk/test/Index/local-symbols.m Fri Oct 1 15:25:15 2010
@@ -32,7 +32,7 @@
// CHECK: local-symbols.m:9:1: ObjCInstanceMethodDecl=bar:9:1 Extent=[9:1 - 9:12]
// CHECK: local-symbols.m:9:4: TypeRef=id:0:0 Extent=[9:4 - 9:6]
// CHECK: local-symbols.m:12:1: ObjCImplementationDecl=Foo:12:1 (Definition) Extent=[12:1 - 16:2]
-// CHECK: local-symbols.m:13:1: ObjCInstanceMethodDecl=bar:13:1 (Definition) Extent=[13:1 - 15:2]
+// CHECK: local-symbols.m:13:1: ObjCInstanceMethodDecl=bar:13:1 (Definition) [Overrides @9:1] Extent=[13:1 - 15:2]
// CHECK: local-symbols.m:13:4: TypeRef=id:0:0 Extent=[13:4 - 13:6]
// CHECK: local-symbols.m:14:10: UnexposedExpr= Extent=[14:10 - 14:11]
// CHECK: local-symbols.m:14:10: UnexposedExpr= Extent=[14:10 - 14:11]
Added: cfe/trunk/test/Index/overrides.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/overrides.cpp?rev=115338&view=auto
==============================================================================
--- cfe/trunk/test/Index/overrides.cpp (added)
+++ cfe/trunk/test/Index/overrides.cpp Fri Oct 1 15:25:15 2010
@@ -0,0 +1,20 @@
+struct A {
+ virtual void f(int);
+};
+
+struct B {
+ virtual void f(int);
+ virtual void g();
+};
+
+struct C : B, A {
+ virtual void g();
+};
+
+struct D : C {
+ virtual void f(int);
+};
+
+// RUN: c-index-test -test-load-source local %s | FileCheck %s
+// CHECK: overrides.cpp:11:16: CXXMethod=g:11:16 [Overrides @7:16] Extent=[11:16 - 11:19]
+// CHECK: overrides.cpp:15:16: CXXMethod=f:15:16 [Overrides @2:16, @6:16] Extent=[15:16 - 15:22]
Added: cfe/trunk/test/Index/overrides.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/overrides.m?rev=115338&view=auto
==============================================================================
--- cfe/trunk/test/Index/overrides.m (added)
+++ cfe/trunk/test/Index/overrides.m Fri Oct 1 15:25:15 2010
@@ -0,0 +1,35 @@
+
+ at protocol P1
+- (void)protoMethod;
+- (void)protoMethodWithParam:(int)param;
+ at end
+
+ at protocol P3
+- (void)protoMethod;
+ at end
+
+ at protocol P2 <P1>
+- (void)protoMethod;
+ at end
+
+ at interface A
+- (void)method;
++ (void)methodWithParam:(int)param;
+ at end
+
+ at interface B : A <P2, P3>
+- (void)method;
+- (void)protoMethod;
+ at end
+
+ at implementation B
+- (void)method { }
++ (void)methodWithParam:(int)param { }
+ at end
+
+// RUN: c-index-test -test-load-source local %s | FileCheck %s
+// CHECK: overrides.m:12:1: ObjCInstanceMethodDecl=protoMethod:12:1 [Overrides @3:1] Extent=[12:1 - 12:21]
+// CHECK: overrides.m:21:1: ObjCInstanceMethodDecl=method:21:1 [Overrides @16:1] Extent=[21:1 - 21:16]
+// CHECK: overrides.m:22:1: ObjCInstanceMethodDecl=protoMethod:22:1 [Overrides @12:1, @8:1] Extent=[22:1 - 22:21]
+// CHECK: overrides.m:26:1: ObjCInstanceMethodDecl=method:26:1 (Definition) [Overrides @21:1] Extent=[26:1 - 26:19]
+// CHECK: overrides.m:27:1: ObjCClassMethodDecl=methodWithParam::27:1 (Definition) [Overrides @17:1] Extent=[27:1 - 27:39]
Modified: cfe/trunk/test/Index/properties-class-extensions.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/properties-class-extensions.m?rev=115338&r1=115337&r2=115338&view=diff
==============================================================================
--- cfe/trunk/test/Index/properties-class-extensions.m (original)
+++ cfe/trunk/test/Index/properties-class-extensions.m Fri Oct 1 15:25:15 2010
@@ -80,7 +80,7 @@
// CHECK: properties-class-extensions.m:30:12: ObjCClassRef=Rdar8467189_Foo:28:12 Extent=[30:12 - 30:27]
// CHECK: properties-class-extensions.m:31:40: ObjCPropertyDecl=Rdar8467189_Bar:31:40 Extent=[31:40 - 31:55]
// CHECK: properties-class-extensions.m:31:23: ObjCClassRef=Rdar8467189_Bar:24:8 Extent=[31:23 - 31:38]
-// CHECK: properties-class-extensions.m:31:40: ObjCInstanceMethodDecl=Rdar8467189_Bar:31:40 Extent=[31:40 - 31:55]
+// CHECK: properties-class-extensions.m:31:40: ObjCInstanceMethodDecl=Rdar8467189_Bar:31:40 [Overrides @26:39] Extent=[31:40 - 31:55]
// CHECK: properties-class-extensions.m:31:40: ObjCInstanceMethodDecl=setRdar8467189_Bar::31:40 Extent=[31:40 - 31:55]
// CHECK: properties-class-extensions.m:31:40: ParmDecl=Rdar8467189_Bar:31:40 (Definition) Extent=[31:40 - 31:55]
// CHECK: properties-class-extensions.m:35:12: ObjCInterfaceDecl=Qux:35:12 Extent=[35:1 - 36:5]
Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=115338&r1=115337&r2=115338&view=diff
==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Fri Oct 1 15:25:15 2010
@@ -167,7 +167,9 @@
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 @@
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);
+ }
}
}
Modified: cfe/trunk/tools/libclang/CIndex.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CIndex.cpp?rev=115338&r1=115337&r2=115338&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CIndex.cpp (original)
+++ cfe/trunk/tools/libclang/CIndex.cpp Fri Oct 1 15:25:15 2010
@@ -4065,6 +4065,117 @@
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"
Modified: cfe/trunk/tools/libclang/libclang.darwin.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.darwin.exports?rev=115338&r1=115337&r2=115338&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.darwin.exports (original)
+++ cfe/trunk/tools/libclang/libclang.darwin.exports Fri Oct 1 15:25:15 2010
@@ -21,6 +21,7 @@
_clang_disposeCodeCompleteResults
_clang_disposeDiagnostic
_clang_disposeIndex
+_clang_disposeOverriddenCursors
_clang_disposeString
_clang_disposeTokens
_clang_disposeTranslationUnit
@@ -77,6 +78,7 @@
_clang_getNumDiagnostics
_clang_getNumOverloadedDecls
_clang_getOverloadedDecl
+_clang_getOverriddenCursors
_clang_getPointeeType
_clang_getRange
_clang_getRangeEnd
Modified: cfe/trunk/tools/libclang/libclang.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=115338&r1=115337&r2=115338&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.exports (original)
+++ cfe/trunk/tools/libclang/libclang.exports Fri Oct 1 15:25:15 2010
@@ -21,6 +21,7 @@
clang_disposeCodeCompleteResults
clang_disposeDiagnostic
clang_disposeIndex
+clang_disposeOverriddenCursors
clang_disposeString
clang_disposeTokens
clang_disposeTranslationUnit
@@ -77,6 +78,7 @@
clang_getNumDiagnostics
clang_getNumOverloadedDecls
clang_getOverloadedDecl
+clang_getOverriddenCursors
clang_getPointeeType
clang_getRange
clang_getRangeEnd
More information about the cfe-commits
mailing list