in glean/lang/clang/ast.cpp [2227:2259]
bool VisitObjCMessageExpr(const clang::ObjCMessageExpr *expr) {
if (!expr->isImplicit()) {
if (const auto *decl = expr->getMethodDecl()) {
folly::Optional<Cxx::XRefTarget> target;
if (auto r = objcMethodDecls(decl)) {
target = Cxx::XRefTarget::declaration(
Cxx::Declaration::objcMethod(r->decl));
}
const auto sel = expr->getSelector();
const auto nsels = expr->getNumSelectorLocs();
for (unsigned int i = 0; i < nsels; ++i) {
const auto start = expr->getSelectorLoc(i);
if (start.isValid()) {
// NOTE: Arguments don't necessarily have names, e.g.
// foo:(float)x :(float)y :(float)z
// which would then be called as
// [o foo:1 :2 :3]
//
// There will be at least one word (the method name) so we'll
// definitely get at least one xref.
if (auto ident = sel.getIdentifierInfoForSlot(i)) {
const auto end = start.getLocWithOffset(
ident->getLength()-1);
xrefTarget(
clang::SourceRange(start,end),
XRef::to(decl, target));
}
}
}
}
}
return true;
}