summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang-c/Index.h4
-rw-r--r--clang/test/Index/cursor-dynamic-call.mm12
-rw-r--r--clang/tools/c-index-test/c-index-test.c11
-rw-r--r--clang/tools/libclang/CXCursor.cpp27
4 files changed, 46 insertions, 8 deletions
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 9acc9b75bff..c3a48228869 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -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);
diff --git a/clang/test/Index/cursor-dynamic-call.mm b/clang/test/Index/cursor-dynamic-call.mm
index a926c3d03d4..33d1c68558f 100644
--- a/clang/test/Index/cursor-dynamic-call.mm
+++ b/clang/test/Index/cursor-dynamic-call.mm
@@ -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
diff --git a/clang/tools/c-index-test/c-index-test.c b/clang/tools/c-index-test/c-index-test.c
index e8763ffc00a..0978ccb28d7 100644
--- a/clang/tools/c-index-test/c-index-test.c
+++ b/clang/tools/c-index-test/c-index-test.c
@@ -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);
+ }
}
{
diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp
index c19aa65ac62..6a2dbfdeda3 100644
--- a/clang/tools/libclang/CXCursor.cpp
+++ b/clang/tools/libclang/CXCursor.cpp
@@ -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);
}
OpenPOWER on IntegriCloud