mirror of https://github.com/microsoft/clang.git
[libclang] Enhance clang_Cursor_isDynamicCall and clang_Cursor_getReceiverType to handle ObjC property references
Also enhance clang_Cursor_getReceiverType to handle C++ method calls. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@301568 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
5411d2255c
commit
41e19f971f
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue