]> granicus.if.org Git - clang/commitdiff
[libclang] Introduce clang_Cursor_getReceiverType which returns the CXType for
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 1 Nov 2012 02:01:34 +0000 (02:01 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 1 Nov 2012 02:01:34 +0000 (02:01 +0000)
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

include/clang-c/Index.h
include/clang/AST/ExprObjC.h
lib/AST/Expr.cpp
test/Index/cursor-dynamic-call.mm
tools/c-index-test/c-index-test.c
tools/libclang/CXCursor.cpp
tools/libclang/libclang.exports

index 299fa8f98bd4940551ba694fd69a8a8a953bc87f..2b52c0c89c1bdbe3c35c5d7c8f1e03491e43a555 100644 (file)
@@ -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)                       \
@@ -3196,6 +3196,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
index 748aaa16948a4fc96b0a82f8a38d64c4530051ae..27f5da0ce707859a7676b1c120b9150fde09e74f 100644 (file)
@@ -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.
   ///
index 4a8033f878d64758f2179249da32e880df3bb632..114aad54638d43ad5935ae991b4386d1e97e49f4 100644 (file)
@@ -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;
 }
 
index f9d6a8716d16742017f105c0b47f435149e0566e..ac9e6d351a0a477e83ec21f17455341f7673d2be 100644 (file)
@@ -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
index 2df2e4be3e50b97fb2ddc967e2e6406179ce5c57..3e4404cbaa094dfb58e87263befa02c7ad38ce79 100644 (file)
@@ -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);
index ce517023f4031cf5d48a0c969e8de15640c8271b..8d3e1690edc58b4dee2c47a6ee21f0c50be9d528 100644 (file)
@@ -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"
index ec77fafa7b60b91abad800e1cc7fdfa926363f40..4495b66bdc139028e3aa3ac4f70da26a92b707b9 100644 (file)
@@ -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