[libclang] Enhance clang_Cursor_isDynamicCall and clang_Cursor_getReceiverType to...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 27 Apr 2017 17:23:04 +0000 (17:23 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Thu, 27 Apr 2017 17:23:04 +0000 (17:23 +0000)
Also enhance clang_Cursor_getReceiverType to handle C++ method calls.

llvm-svn: 301568

clang/include/clang-c/Index.h
clang/test/Index/cursor-dynamic-call.mm
clang/tools/c-index-test/c-index-test.c
clang/tools/libclang/CXCursor.cpp

index 9acc9b7..c3a4822 100644 (file)
@@ -3975,8 +3975,8 @@ CINDEX_LINKAGE int clang_Cursor_getObjCSelectorIndex(CXCursor);
 CINDEX_LINKAGE int clang_Cursor_isDynamicCall(CXCursor C);
 
 /**
- * \brief Given a cursor pointing to an Objective-C message, returns the CXType
- * of the receiver.
+ * \brief Given a cursor pointing to an Objective-C message or property
+ * reference, or C++ method call, returns the CXType of the receiver.
  */
 CINDEX_LINKAGE CXType clang_Cursor_getReceiverType(CXCursor C);
 
index a926c3d..33d1c68 100644 (file)
@@ -49,6 +49,14 @@ void test2() {
   id o = [[Test alloc] init];
 }
 
+@interface Test2 : NSObject
+@property (assign) id someProp;
+@end
+
+void test3(Test2 *o) {
+  id v = o.someProp;
+}
+
 // RUN: c-index-test -cursor-at=%s:8:11 \
 // RUN:              -cursor-at=%s:9:11 \
 // RUN:              -cursor-at=%s:25:11 \
@@ -59,6 +67,7 @@ void test2() {
 // RUN:              -cursor-at=%s:36:9 \
 // RUN:              -cursor-at=%s:37:9 \
 // RUN:              -cursor-at=%s:49:26 \
+// RUN:              -cursor-at=%s:57:12 \
 // RUN:       %s | FileCheck %s
 
 // CHECK:     8:11 MemberRefExpr=meth:3:16 {{.*}} Dynamic-call
@@ -67,9 +76,10 @@ void test2() {
 // 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:     34:7 MemberRefExpr=meth:3:16 {{.*}} Dynamic-call Receiver-type=Pointer
 // CHECK:     35:3 ObjCMessageExpr=meth:14:8 {{.*}} Dynamic-call Receiver-type=ObjCObjectPointer
 // CHECK-NOT: 36:3 {{.*}} Dynamic-call
 // CHECK:     36:3 {{.*}} Receiver-type=ObjCInterface
 // CHECK:     37:3 ObjCMessageExpr=ClsMeth:15:8 {{.*}} Dynamic-call Receiver-type=ObjCClass
 // CHECK-NOT: 49:10 {{.*}} Dynamic-call
+// CHECK:     57:12 MemberRefExpr=someProp:53:23 {{.*}} Dynamic-call  Receiver-type=ObjCObjectPointer
index e8763ff..0978ccb 100644 (file)
@@ -2437,11 +2437,14 @@ static void inspect_print_cursor(CXCursor Cursor) {
            clang_Cursor_getObjCSelectorIndex(Cursor));
   if (clang_Cursor_isDynamicCall(Cursor))
     printf(" Dynamic-call");
-  if (Cursor.kind == CXCursor_ObjCMessageExpr) {
+  if (Cursor.kind == CXCursor_ObjCMessageExpr ||
+      Cursor.kind == CXCursor_MemberRefExpr) {
     CXType T = clang_Cursor_getReceiverType(Cursor);
-    CXString S = clang_getTypeKindSpelling(T.kind);
-    printf(" Receiver-type=%s", clang_getCString(S));
-    clang_disposeString(S);
+    if (T.kind != CXType_Invalid) {
+      CXString S = clang_getTypeKindSpelling(T.kind);
+      printf(" Receiver-type=%s", clang_getCString(S));
+      clang_disposeString(S);
+    }
   }
 
   {
index c19aa65..6a2dbfd 100644 (file)
@@ -1523,6 +1523,10 @@ int clang_Cursor_isDynamicCall(CXCursor C) {
     return true;
   }
 
+  if (auto *PropRefE = dyn_cast<ObjCPropertyRefExpr>(E)) {
+    return !PropRefE->isSuperReceiver();
+  }
+
   const MemberExpr *ME = nullptr;
   if (isa<MemberExpr>(E))
     ME = cast<MemberExpr>(E);
@@ -1532,7 +1536,9 @@ int clang_Cursor_isDynamicCall(CXCursor C) {
   if (ME) {
     if (const CXXMethodDecl *
           MD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl()))
-      return MD->isVirtual() && !ME->hasQualifier();
+      return MD->isVirtual() &&
+             ME->performsVirtualDispatch(
+                 cxcursor::getCursorContext(C).getLangOpts());
   }
 
   return 0;
@@ -1547,5 +1553,24 @@ CXType clang_Cursor_getReceiverType(CXCursor C) {
   if (const ObjCMessageExpr *MsgE = dyn_cast_or_null<ObjCMessageExpr>(E))
     return cxtype::MakeCXType(MsgE->getReceiverType(), TU);
 
+  if (auto *PropRefE = dyn_cast<ObjCPropertyRefExpr>(E)) {
+    return cxtype::MakeCXType(
+        PropRefE->getReceiverType(cxcursor::getCursorContext(C)), TU);
+  }
+
+  const MemberExpr *ME = nullptr;
+  if (isa<MemberExpr>(E))
+    ME = cast<MemberExpr>(E);
+  else if (const CallExpr *CE = dyn_cast<CallExpr>(E))
+    ME = dyn_cast_or_null<MemberExpr>(CE->getCallee());
+
+  if (ME) {
+    if (const CXXMethodDecl *
+          MD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl())) {
+      auto receiverTy = ME->getBase()->IgnoreImpCasts()->getType();
+      return cxtype::MakeCXType(receiverTy, TU);
+    }
+  }
+
   return cxtype::MakeCXType(QualType(), TU);
 }