in facebook-clang-plugins/libtooling/ASTExporter.h [4332:4393]
void ASTExporter<ATDWriter>::VisitObjCMessageExpr(const ObjCMessageExpr *Node) {
VisitExpr(Node);
bool IsDefinitionFound = false;
// Do not rely on Node->getMethodDecl() - it might be wrong if
// selector doesn't type check (ie. method of subclass is called)
const ObjCInterfaceDecl *receiver = Node->getReceiverInterface();
const Selector selector = Node->getSelector();
const ObjCMethodDecl *m_decl = NULL;
if (receiver) {
bool IsInst = Node->isInstanceMessage();
m_decl = receiver->lookupPrivateMethod(selector, IsInst);
// Look for definition first. It's possible that class redefines it without
// redeclaring. It needs to be defined in same translation unit to work.
if (m_decl) {
IsDefinitionFound = true;
} else {
// As a fallback look through method declarations in the interface.
// It's not very reliable (subclass might have redefined it)
// but it's better than nothing
IsDefinitionFound = false;
m_decl = receiver->lookupMethod(selector, IsInst);
}
}
// Fall back to the default method lookup method
if (!m_decl) {
m_decl = Node->getMethodDecl();
}
ObjCMessageExpr::ReceiverKind RK = Node->getReceiverKind();
bool HasNonDefaultReceiverKind = RK != ObjCMessageExpr::Instance;
ObjectScope Scope(
OF, 1 + IsDefinitionFound + (bool)m_decl + HasNonDefaultReceiverKind);
OF.emitTag("selector");
OF.emitString(selector.getAsString());
if (m_decl) {
OF.emitFlag("is_definition_found", IsDefinitionFound);
OF.emitTag("decl_pointer");
dumpPointer(m_decl);
}
if (HasNonDefaultReceiverKind) {
OF.emitTag("receiver_kind");
switch (RK) {
case ObjCMessageExpr::Class: {
VariantScope Scope(OF, "Class");
dumpQualType(Node->getClassReceiver());
} break;
case ObjCMessageExpr::SuperInstance:
OF.emitSimpleVariant("SuperInstance");
break;
case ObjCMessageExpr::SuperClass:
OF.emitSimpleVariant("SuperClass");
break;
case ObjCMessageExpr::Instance:
llvm_unreachable("unreachable");
break;
}
}
}