aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>2012-11-01 02:01:34 +0000
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>2012-11-01 02:01:34 +0000
commite4a990f34904eb572c8d6aa1deef19465214359c (patch)
tree9c7bf79a737d86e06432da8272545c1faf6858af
parent3cdd84318a3ae43fa31da849f1a6d3eeb8a39d2d (diff)
[libclang] Introduce clang_Cursor_getReceiverType which returns the CXType for
the receiver of an ObjC message expression. rdar://12578643 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@167201 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--include/clang-c/Index.h8
-rw-r--r--include/clang/AST/ExprObjC.h11
-rw-r--r--lib/AST/Expr.cpp36
-rw-r--r--test/Index/cursor-dynamic-call.mm8
-rw-r--r--tools/c-index-test/c-index-test.c6
-rw-r--r--tools/libclang/CXCursor.cpp13
-rw-r--r--tools/libclang/libclang.exports1
7 files changed, 59 insertions, 24 deletions
diff --git a/include/clang-c/Index.h b/include/clang-c/Index.h
index 299fa8f98b..2b52c0c89c 100644
--- a/include/clang-c/Index.h
+++ b/include/clang-c/Index.h
@@ -24,7 +24,7 @@
#include "clang-c/CXString.h"
#define CINDEX_VERSION_MAJOR 0
-#define CINDEX_VERSION_MINOR 5
+#define CINDEX_VERSION_MINOR 6
#define CINDEX_VERSION_ENCODE(major, minor) ( \
((major) * 10000) \
@@ -3197,6 +3197,12 @@ CINDEX_LINKAGE int clang_Cursor_getObjCSelectorIndex(CXCursor);
CINDEX_LINKAGE int clang_Cursor_isDynamicCall(CXCursor C);
/**
+ * \brief Given a cursor pointing to an ObjC message, returns the CXType of the
+ * receiver.
+ */
+CINDEX_LINKAGE CXType clang_Cursor_getReceiverType(CXCursor C);
+
+/**
* \brief Given a cursor that represents a declaration, return the associated
* comment's source range. The range may include multiple consecutive comments
* with whitespace in between.
diff --git a/include/clang/AST/ExprObjC.h b/include/clang/AST/ExprObjC.h
index 748aaa1694..27f5da0ce7 100644
--- a/include/clang/AST/ExprObjC.h
+++ b/include/clang/AST/ExprObjC.h
@@ -1195,6 +1195,17 @@ public:
return SourceLocation();
}
+ /// \brief Retrieve the receiver type to which this message is being directed.
+ ///
+ /// This routine cross-cuts all of the different kinds of message
+ /// sends to determine what the underlying (statically known) type
+ /// of the receiver will be; use \c getReceiverKind() to determine
+ /// whether the message is a class or an instance method, whether it
+ /// is a send to super or not, etc.
+ ///
+ /// \returns The type of the receiver.
+ QualType getReceiverType() const;
+
/// \brief Retrieve the Objective-C interface to which this message
/// is being directed, if known.
///
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 4a8033f878..114aad5463 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -3442,33 +3442,29 @@ Selector ObjCMessageExpr::getSelector() const {
return Selector(SelectorOrMethod);
}
-ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const {
+QualType ObjCMessageExpr::getReceiverType() const {
switch (getReceiverKind()) {
case Instance:
- if (const ObjCObjectPointerType *Ptr
- = getInstanceReceiver()->getType()->getAs<ObjCObjectPointerType>())
- return Ptr->getInterfaceDecl();
- break;
-
+ return getInstanceReceiver()->getType();
case Class:
- if (const ObjCObjectType *Ty
- = getClassReceiver()->getAs<ObjCObjectType>())
- return Ty->getInterface();
- break;
-
+ return getClassReceiver();
case SuperInstance:
- if (const ObjCObjectPointerType *Ptr
- = getSuperType()->getAs<ObjCObjectPointerType>())
- return Ptr->getInterfaceDecl();
- break;
-
case SuperClass:
- if (const ObjCObjectType *Iface
- = getSuperType()->getAs<ObjCObjectType>())
- return Iface->getInterface();
- break;
+ return getSuperType();
}
+ llvm_unreachable("unexpected receiver kind");
+}
+
+ObjCInterfaceDecl *ObjCMessageExpr::getReceiverInterface() const {
+ QualType T = getReceiverType();
+
+ if (const ObjCObjectPointerType *Ptr = T->getAs<ObjCObjectPointerType>())
+ return Ptr->getInterfaceDecl();
+
+ if (const ObjCObjectType *Ty = T->getAs<ObjCObjectType>())
+ return Ty->getInterface();
+
return 0;
}
diff --git a/test/Index/cursor-dynamic-call.mm b/test/Index/cursor-dynamic-call.mm
index f9d6a8716d..ac9e6d351a 100644
--- a/test/Index/cursor-dynamic-call.mm
+++ b/test/Index/cursor-dynamic-call.mm
@@ -50,10 +50,12 @@ void foo(SS *ss, IS* is, Class cls) {
// CHECK: 8:11 MemberRefExpr=meth:3:16 {{.*}} Dynamic-call
// CHECK-NOT: 9:9 {{.*}} Dynamic-call
-// CHECK: 25:3 ObjCMessageExpr=meth:14:8 {{.*}} Dynamic-call
+// CHECK: 25:3 ObjCMessageExpr=meth:14:8 {{.*}} Dynamic-call Receiver-type=ObjCObjectPointer
// CHECK-NOT: 26:3 {{.*}} Dynamic-call
// CHECK-NOT: 29:3 {{.*}} Dynamic-call
+// CHECK: 29:3 {{.*}} Receiver-type=ObjCInterface
// CHECK: 34:7 MemberRefExpr=meth:3:16 {{.*}} Dynamic-call
-// CHECK: 35:3 ObjCMessageExpr=meth:14:8 {{.*}} Dynamic-call
+// CHECK: 35:3 ObjCMessageExpr=meth:14:8 {{.*}} Dynamic-call Receiver-type=ObjCObjectPointer
// CHECK-NOT: 36:3 {{.*}} Dynamic-call
-// CHECK: 37:3 ObjCMessageExpr=ClsMeth:15:8 {{.*}} Dynamic-call
+// CHECK: 36:3 {{.*}} Receiver-type=ObjCInterface
+// CHECK: 37:3 ObjCMessageExpr=ClsMeth:15:8 {{.*}} Dynamic-call Receiver-type=ObjCClass
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 2df2e4be3e..3e4404cbaa 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -1955,6 +1955,12 @@ static int inspect_cursor_at(int argc, const char **argv) {
printf(" Selector index=%d",clang_Cursor_getObjCSelectorIndex(Cursor));
if (clang_Cursor_isDynamicCall(Cursor))
printf(" Dynamic-call");
+ if (Cursor.kind == CXCursor_ObjCMessageExpr) {
+ CXType T = clang_Cursor_getReceiverType(Cursor);
+ CXString S = clang_getTypeKindSpelling(T.kind);
+ printf(" Receiver-type=%s", clang_getCString(S));
+ clang_disposeString(S);
+ }
{
CXModule mod = clang_Cursor_getModule(Cursor);
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index ce517023f4..8d3e1690ed 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -15,6 +15,7 @@
#include "CXTranslationUnit.h"
#include "CXCursor.h"
+#include "CXType.h"
#include "CXString.h"
#include "clang/Frontend/ASTUnit.h"
#include "clang/AST/Decl.h"
@@ -1172,4 +1173,16 @@ int clang_Cursor_isDynamicCall(CXCursor C) {
return 0;
}
+CXType clang_Cursor_getReceiverType(CXCursor C) {
+ CXTranslationUnit TU = cxcursor::getCursorTU(C);
+ const Expr *E = 0;
+ if (clang_isExpression(C.kind))
+ E = getCursorExpr(C);
+
+ if (const ObjCMessageExpr *MsgE = dyn_cast_or_null<ObjCMessageExpr>(E))
+ return cxtype::MakeCXType(MsgE->getReceiverType(), TU);
+
+ return cxtype::MakeCXType(QualType(), TU);
+}
+
} // end: extern "C"
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index ec77fafa7b..4495b66bdc 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -13,6 +13,7 @@ clang_Cursor_getNumArguments
clang_Cursor_getObjCSelectorIndex
clang_Cursor_getSpellingNameRange
clang_Cursor_getTranslationUnit
+clang_Cursor_getReceiverType
clang_Cursor_isDynamicCall
clang_Cursor_isNull
clang_Cursor_getModule