[libclang] Introduce clang_Cursor_getReceiverType which returns the CXType for

the receiver of an ObjC message expression.

rdar://12578643

llvm-svn: 167201
This commit is contained in:
Argyrios Kyrtzidis 2012-11-01 02:01:34 +00:00
parent b351c8d692
commit b26a24cca2
7 changed files with 59 additions and 24 deletions

View 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

View 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.
///

View 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;
}

View 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

View 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);

View 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"

View 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