2009-07-30 07:40:14 +08:00
|
|
|
//===--- Analyzer.cpp - Analysis for indexing information -------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file implements the Analyzer interface.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "clang/Index/Analyzer.h"
|
|
|
|
#include "clang/Index/Entity.h"
|
|
|
|
#include "clang/Index/TranslationUnit.h"
|
|
|
|
#include "clang/Index/Handlers.h"
|
|
|
|
#include "clang/Index/ASTLocation.h"
|
2009-07-30 08:03:55 +08:00
|
|
|
#include "clang/Index/GlobalSelector.h"
|
2009-07-30 07:40:14 +08:00
|
|
|
#include "clang/Index/DeclReferenceMap.h"
|
2009-07-30 08:03:55 +08:00
|
|
|
#include "clang/Index/SelectorMap.h"
|
2009-07-30 07:40:14 +08:00
|
|
|
#include "clang/Index/IndexProvider.h"
|
2009-07-30 08:03:55 +08:00
|
|
|
#include "clang/AST/DeclObjC.h"
|
|
|
|
#include "clang/AST/ExprObjC.h"
|
|
|
|
#include "llvm/ADT/SmallSet.h"
|
2009-07-30 07:40:14 +08:00
|
|
|
using namespace clang;
|
|
|
|
using namespace idx;
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// DeclEntityAnalyzer Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-11-29 03:45:26 +08:00
|
|
|
class DeclEntityAnalyzer : public TranslationUnitHandler {
|
2009-07-30 07:40:14 +08:00
|
|
|
Entity Ent;
|
|
|
|
TULocationHandler &TULocHandler;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 07:40:14 +08:00
|
|
|
public:
|
|
|
|
DeclEntityAnalyzer(Entity ent, TULocationHandler &handler)
|
|
|
|
: Ent(ent), TULocHandler(handler) { }
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 07:40:14 +08:00
|
|
|
virtual void Handle(TranslationUnit *TU) {
|
|
|
|
assert(TU && "Passed null translation unit");
|
|
|
|
|
|
|
|
Decl *D = Ent.getDecl(TU->getASTContext());
|
|
|
|
assert(D && "Couldn't resolve Entity");
|
|
|
|
|
|
|
|
for (Decl::redecl_iterator I = D->redecls_begin(),
|
|
|
|
E = D->redecls_end(); I != E; ++I)
|
|
|
|
TULocHandler.Handle(TULocation(TU, ASTLocation(*I)));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// RefEntityAnalyzer Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-11-29 03:45:26 +08:00
|
|
|
class RefEntityAnalyzer : public TranslationUnitHandler {
|
2009-07-30 07:40:14 +08:00
|
|
|
Entity Ent;
|
|
|
|
TULocationHandler &TULocHandler;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 07:40:14 +08:00
|
|
|
public:
|
|
|
|
RefEntityAnalyzer(Entity ent, TULocationHandler &handler)
|
|
|
|
: Ent(ent), TULocHandler(handler) { }
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 07:40:14 +08:00
|
|
|
virtual void Handle(TranslationUnit *TU) {
|
|
|
|
assert(TU && "Passed null translation unit");
|
|
|
|
|
|
|
|
Decl *D = Ent.getDecl(TU->getASTContext());
|
|
|
|
assert(D && "Couldn't resolve Entity");
|
|
|
|
NamedDecl *ND = dyn_cast<NamedDecl>(D);
|
|
|
|
if (!ND)
|
|
|
|
return;
|
|
|
|
|
|
|
|
DeclReferenceMap &RefMap = TU->getDeclReferenceMap();
|
|
|
|
for (DeclReferenceMap::astlocation_iterator
|
|
|
|
I = RefMap.refs_begin(ND), E = RefMap.refs_end(ND); I != E; ++I)
|
2009-07-30 08:03:55 +08:00
|
|
|
TULocHandler.Handle(TULocation(TU, *I));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// RefSelectorAnalyzer Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// \brief Accepts an ObjC method and finds all message expressions that this
|
|
|
|
/// method may respond to.
|
2009-11-29 03:45:26 +08:00
|
|
|
class RefSelectorAnalyzer : public TranslationUnitHandler {
|
2009-07-30 08:03:55 +08:00
|
|
|
Program &Prog;
|
|
|
|
TULocationHandler &TULocHandler;
|
|
|
|
|
|
|
|
// The original ObjCInterface associated with the method.
|
|
|
|
Entity IFaceEnt;
|
|
|
|
GlobalSelector GlobSel;
|
|
|
|
bool IsInstanceMethod;
|
|
|
|
|
|
|
|
/// \brief Super classes of the ObjCInterface.
|
|
|
|
typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
|
|
|
|
EntitiesSetTy HierarchyEntities;
|
|
|
|
|
|
|
|
public:
|
|
|
|
RefSelectorAnalyzer(ObjCMethodDecl *MD,
|
|
|
|
Program &prog, TULocationHandler &handler)
|
|
|
|
: Prog(prog), TULocHandler(handler) {
|
|
|
|
assert(MD);
|
|
|
|
|
|
|
|
// FIXME: Protocol methods.
|
|
|
|
assert(!isa<ObjCProtocolDecl>(MD->getDeclContext()) &&
|
|
|
|
"Protocol methods not supported yet");
|
|
|
|
|
|
|
|
ObjCInterfaceDecl *IFD = MD->getClassInterface();
|
|
|
|
assert(IFD);
|
|
|
|
IFaceEnt = Entity::get(IFD, Prog);
|
|
|
|
GlobSel = GlobalSelector::get(MD->getSelector(), Prog);
|
|
|
|
IsInstanceMethod = MD->isInstanceMethod();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 08:03:55 +08:00
|
|
|
for (ObjCInterfaceDecl *Cls = IFD->getSuperClass();
|
|
|
|
Cls; Cls = Cls->getSuperClass())
|
|
|
|
HierarchyEntities.insert(Entity::get(Cls, Prog));
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 08:03:55 +08:00
|
|
|
virtual void Handle(TranslationUnit *TU) {
|
|
|
|
assert(TU && "Passed null translation unit");
|
|
|
|
|
|
|
|
ASTContext &Ctx = TU->getASTContext();
|
|
|
|
// Null means it doesn't exist in this translation unit.
|
|
|
|
ObjCInterfaceDecl *IFace =
|
|
|
|
cast_or_null<ObjCInterfaceDecl>(IFaceEnt.getDecl(Ctx));
|
|
|
|
Selector Sel = GlobSel.getSelector(Ctx);
|
|
|
|
|
|
|
|
SelectorMap &SelMap = TU->getSelectorMap();
|
|
|
|
for (SelectorMap::astlocation_iterator
|
|
|
|
I = SelMap.refs_begin(Sel), E = SelMap.refs_end(Sel); I != E; ++I) {
|
|
|
|
if (ValidReference(*I, IFace))
|
|
|
|
TULocHandler.Handle(TULocation(TU, *I));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Determines whether the given message expression is likely to end
|
|
|
|
/// up at the given interface decl.
|
|
|
|
///
|
|
|
|
/// It returns true "eagerly", meaning it will return false only if it can
|
|
|
|
/// "prove" statically that the interface cannot accept this message.
|
|
|
|
bool ValidReference(ASTLocation ASTLoc, ObjCInterfaceDecl *IFace) {
|
|
|
|
assert(ASTLoc.isStmt());
|
|
|
|
|
|
|
|
// FIXME: Finding @selector references should be through another Analyzer
|
|
|
|
// method, like FindSelectors.
|
2009-09-30 03:44:27 +08:00
|
|
|
if (isa<ObjCSelectorExpr>(ASTLoc.AsStmt()))
|
2009-09-09 23:08:12 +08:00
|
|
|
return false;
|
2009-07-30 08:03:55 +08:00
|
|
|
|
|
|
|
ObjCInterfaceDecl *MsgD = 0;
|
2009-09-30 03:44:27 +08:00
|
|
|
ObjCMessageExpr *Msg = cast<ObjCMessageExpr>(ASTLoc.AsStmt());
|
2009-07-30 08:03:55 +08:00
|
|
|
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
switch (Msg->getReceiverKind()) {
|
|
|
|
case ObjCMessageExpr::Instance: {
|
2009-07-30 08:03:55 +08:00
|
|
|
const ObjCObjectPointerType *OPT =
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
Msg->getInstanceReceiver()->getType()->getAsObjCInterfacePointerType();
|
2009-07-30 08:03:55 +08:00
|
|
|
|
|
|
|
// Can be anything! Accept it as a possibility..
|
|
|
|
if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// Expecting class method.
|
|
|
|
if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType())
|
|
|
|
return !IsInstanceMethod;
|
|
|
|
|
|
|
|
MsgD = OPT->getInterfaceDecl();
|
|
|
|
assert(MsgD);
|
|
|
|
|
|
|
|
// Should be an instance method.
|
|
|
|
if (!IsInstanceMethod)
|
|
|
|
return false;
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
break;
|
|
|
|
}
|
2009-07-30 08:03:55 +08:00
|
|
|
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
case ObjCMessageExpr::Class: {
|
2009-07-30 08:03:55 +08:00
|
|
|
// Expecting class method.
|
|
|
|
if (IsInstanceMethod)
|
|
|
|
return false;
|
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
MsgD = Msg->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
case ObjCMessageExpr::SuperClass:
|
|
|
|
// Expecting class method.
|
|
|
|
if (IsInstanceMethod)
|
|
|
|
return false;
|
|
|
|
|
2010-05-15 19:32:37 +08:00
|
|
|
MsgD = Msg->getSuperType()->getAs<ObjCObjectType>()->getInterface();
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
break;
|
|
|
|
|
|
|
|
case ObjCMessageExpr::SuperInstance:
|
|
|
|
// Expecting instance method.
|
|
|
|
if (!IsInstanceMethod)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>()
|
|
|
|
->getInterfaceDecl();
|
|
|
|
break;
|
2009-07-30 08:03:55 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
assert(MsgD);
|
|
|
|
|
|
|
|
// Same interface ? We have a winner!
|
|
|
|
if (MsgD == IFace)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// If the message interface is a superclass of the original interface,
|
|
|
|
// accept this message as a possibility.
|
|
|
|
if (HierarchyEntities.count(Entity::get(MsgD, Prog)))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
// If the message interface is a subclass of the original interface, accept
|
|
|
|
// the message unless there is a subclass in the hierarchy that will
|
|
|
|
// "steal" the message (thus the message "will go" to the subclass and not
|
|
|
|
/// the original interface).
|
|
|
|
if (IFace) {
|
|
|
|
Selector Sel = Msg->getSelector();
|
|
|
|
for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
|
|
|
|
if (Cls == IFace)
|
|
|
|
return true;
|
|
|
|
if (Cls->getMethod(Sel, IsInstanceMethod))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// The interfaces are unrelated, don't accept the message.
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// MessageAnalyzer Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
/// \brief Accepts an ObjC message expression and finds all methods that may
|
|
|
|
/// respond to it.
|
2009-11-29 03:45:26 +08:00
|
|
|
class MessageAnalyzer : public TranslationUnitHandler {
|
2009-07-30 08:03:55 +08:00
|
|
|
Program &Prog;
|
|
|
|
TULocationHandler &TULocHandler;
|
|
|
|
|
|
|
|
// The ObjCInterface associated with the message. Can be null/invalid.
|
|
|
|
Entity MsgIFaceEnt;
|
|
|
|
GlobalSelector GlobSel;
|
|
|
|
bool CanBeInstanceMethod;
|
|
|
|
bool CanBeClassMethod;
|
|
|
|
|
|
|
|
/// \brief Super classes of the ObjCInterface.
|
|
|
|
typedef llvm::SmallSet<Entity, 16> EntitiesSetTy;
|
|
|
|
EntitiesSetTy HierarchyEntities;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 08:03:55 +08:00
|
|
|
/// \brief The interface in the message interface hierarchy that "intercepts"
|
|
|
|
/// the selector.
|
|
|
|
Entity ReceiverIFaceEnt;
|
|
|
|
|
|
|
|
public:
|
|
|
|
MessageAnalyzer(ObjCMessageExpr *Msg,
|
|
|
|
Program &prog, TULocationHandler &handler)
|
|
|
|
: Prog(prog), TULocHandler(handler),
|
|
|
|
CanBeInstanceMethod(false),
|
|
|
|
CanBeClassMethod(false) {
|
|
|
|
|
|
|
|
assert(Msg);
|
|
|
|
|
|
|
|
ObjCInterfaceDecl *MsgD = 0;
|
|
|
|
|
|
|
|
while (true) {
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
switch (Msg->getReceiverKind()) {
|
|
|
|
case ObjCMessageExpr::Instance: {
|
|
|
|
const ObjCObjectPointerType *OPT =
|
|
|
|
Msg->getInstanceReceiver()->getType()
|
|
|
|
->getAsObjCInterfacePointerType();
|
|
|
|
|
|
|
|
if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()) {
|
|
|
|
CanBeInstanceMethod = CanBeClassMethod = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) {
|
|
|
|
CanBeClassMethod = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
MsgD = OPT->getInterfaceDecl();
|
|
|
|
assert(MsgD);
|
|
|
|
CanBeInstanceMethod = true;
|
2009-07-30 08:03:55 +08:00
|
|
|
break;
|
|
|
|
}
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
|
|
|
|
case ObjCMessageExpr::Class:
|
|
|
|
CanBeClassMethod = true;
|
2010-05-15 19:32:37 +08:00
|
|
|
MsgD = Msg->getClassReceiver()->getAs<ObjCObjectType>()->getInterface();
|
2009-07-30 08:03:55 +08:00
|
|
|
break;
|
|
|
|
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
case ObjCMessageExpr::SuperClass:
|
2009-07-30 08:03:55 +08:00
|
|
|
CanBeClassMethod = true;
|
2010-05-15 19:32:37 +08:00
|
|
|
MsgD = Msg->getSuperType()->getAs<ObjCObjectType>()->getInterface();
|
2009-07-30 08:03:55 +08:00
|
|
|
break;
|
|
|
|
|
Overhaul the AST representation of Objective-C message send
expressions, to improve source-location information, clarify the
actual receiver of the message, and pave the way for proper C++
support. The ObjCMessageExpr node represents four different kinds of
message sends in a single AST node:
1) Send to a object instance described by an expression (e.g., [x method:5])
2) Send to a class described by the class name (e.g., [NSString method:5])
3) Send to a superclass class (e.g, [super method:5] in class method)
4) Send to a superclass instance (e.g., [super method:5] in instance method)
Previously these four cases where tangled together. Now, they have
more distinct representations. Specific changes:
1) Unchanged; the object instance is represented by an Expr*.
2) Previously stored the ObjCInterfaceDecl* referring to the class
receiving the message. Now stores a TypeSourceInfo* so that we know
how the class was spelled. This both maintains typedef information
and opens the door for more complicated C++ types (e.g., dependent
types). There was an alternative, unused representation of these
sends by naming the class via an IdentifierInfo *. In practice, we
either had an ObjCInterfaceDecl *, from which we would get the
IdentifierInfo *, or we fell into the case below...
3) Previously represented by a class message whose IdentifierInfo *
referred to "super". Sema and CodeGen would use isStr("super") to
determine if they had a send to super. Now represented as a
"class super" send, where we have both the location of the "super"
keyword and the ObjCInterfaceDecl* of the superclass we're
targetting (statically).
4) Previously represented by an instance message whose receiver is a
an ObjCSuperExpr, which Sema and CodeGen would check for via
isa<ObjCSuperExpr>(). Now represented as an "instance super" send,
where we have both the location of the "super" keyword and the
ObjCInterfaceDecl* of the superclass we're targetting
(statically). Note that ObjCSuperExpr only has one remaining use in
the AST, which is for "super.prop" references.
The new representation of ObjCMessageExpr is 2 pointers smaller than
the old one, since it combines more storage. It also eliminates a leak
when we loaded message-send expressions from a precompiled header. The
representation also feels much cleaner to me; comments welcome!
This patch attempts to maintain the same semantics we previously had
with Objective-C message sends. In several places, there are massive
changes that boil down to simply replacing a nested-if structure such
as:
if (message has a receiver expression) {
// instance message
if (isa<ObjCSuperExpr>(...)) {
// send to super
} else {
// send to an object
}
} else {
// class message
if (name->isStr("super")) {
// class send to super
} else {
// send to class
}
}
with a switch
switch (E->getReceiverKind()) {
case ObjCMessageExpr::SuperInstance: ...
case ObjCMessageExpr::Instance: ...
case ObjCMessageExpr::SuperClass: ...
case ObjCMessageExpr::Class:...
}
There are quite a few places (particularly in the checkers) where
send-to-super is effectively ignored. I've placed FIXMEs in most of
them, and attempted to address send-to-super in a reasonable way. This
could use some review.
llvm-svn: 101972
2010-04-21 08:45:42 +08:00
|
|
|
case ObjCMessageExpr::SuperInstance:
|
|
|
|
CanBeInstanceMethod = true;
|
|
|
|
MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>()
|
|
|
|
->getInterfaceDecl();
|
|
|
|
break;
|
|
|
|
}
|
2009-07-30 08:03:55 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 08:03:55 +08:00
|
|
|
assert(CanBeInstanceMethod || CanBeClassMethod);
|
|
|
|
|
|
|
|
Selector sel = Msg->getSelector();
|
|
|
|
assert(!sel.isNull());
|
|
|
|
|
|
|
|
MsgIFaceEnt = Entity::get(MsgD, Prog);
|
|
|
|
GlobSel = GlobalSelector::get(sel, Prog);
|
|
|
|
|
|
|
|
if (MsgD) {
|
|
|
|
for (ObjCInterfaceDecl *Cls = MsgD->getSuperClass();
|
|
|
|
Cls; Cls = Cls->getSuperClass())
|
|
|
|
HierarchyEntities.insert(Entity::get(Cls, Prog));
|
|
|
|
|
|
|
|
// Find the interface in the hierarchy that "receives" the message.
|
|
|
|
for (ObjCInterfaceDecl *Cls = MsgD; Cls; Cls = Cls->getSuperClass()) {
|
|
|
|
bool isReceiver = false;
|
|
|
|
|
|
|
|
ObjCInterfaceDecl::lookup_const_iterator Meth, MethEnd;
|
|
|
|
for (llvm::tie(Meth, MethEnd) = Cls->lookup(sel);
|
|
|
|
Meth != MethEnd; ++Meth) {
|
|
|
|
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(*Meth))
|
|
|
|
if ((MD->isInstanceMethod() && CanBeInstanceMethod) ||
|
|
|
|
(MD->isClassMethod() && CanBeClassMethod)) {
|
|
|
|
isReceiver = true;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 08:03:55 +08:00
|
|
|
if (isReceiver) {
|
|
|
|
ReceiverIFaceEnt = Entity::get(Cls, Prog);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 08:03:55 +08:00
|
|
|
virtual void Handle(TranslationUnit *TU) {
|
|
|
|
assert(TU && "Passed null translation unit");
|
|
|
|
ASTContext &Ctx = TU->getASTContext();
|
|
|
|
|
|
|
|
// Null means it doesn't exist in this translation unit or there was no
|
|
|
|
// interface that was determined to receive the original message.
|
|
|
|
ObjCInterfaceDecl *ReceiverIFace =
|
|
|
|
cast_or_null<ObjCInterfaceDecl>(ReceiverIFaceEnt.getDecl(Ctx));
|
|
|
|
|
|
|
|
// No subclass for the original receiver interface, so it remains the
|
|
|
|
// receiver.
|
|
|
|
if (ReceiverIFaceEnt.isValid() && ReceiverIFace == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
// Null means it doesn't exist in this translation unit or there was no
|
|
|
|
// interface associated with the message in the first place.
|
|
|
|
ObjCInterfaceDecl *MsgIFace =
|
|
|
|
cast_or_null<ObjCInterfaceDecl>(MsgIFaceEnt.getDecl(Ctx));
|
|
|
|
|
|
|
|
Selector Sel = GlobSel.getSelector(Ctx);
|
|
|
|
SelectorMap &SelMap = TU->getSelectorMap();
|
|
|
|
for (SelectorMap::method_iterator
|
|
|
|
I = SelMap.methods_begin(Sel), E = SelMap.methods_end(Sel);
|
|
|
|
I != E; ++I) {
|
|
|
|
ObjCMethodDecl *D = *I;
|
|
|
|
if (ValidMethod(D, MsgIFace, ReceiverIFace)) {
|
|
|
|
for (ObjCMethodDecl::redecl_iterator
|
|
|
|
RI = D->redecls_begin(), RE = D->redecls_end(); RI != RE; ++RI)
|
|
|
|
TULocHandler.Handle(TULocation(TU, ASTLocation(*RI)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// \brief Determines whether the given method is likely to accept the
|
|
|
|
/// original message.
|
|
|
|
///
|
|
|
|
/// It returns true "eagerly", meaning it will return false only if it can
|
|
|
|
/// "prove" statically that the method cannot accept the original message.
|
|
|
|
bool ValidMethod(ObjCMethodDecl *D, ObjCInterfaceDecl *MsgIFace,
|
|
|
|
ObjCInterfaceDecl *ReceiverIFace) {
|
|
|
|
assert(D);
|
|
|
|
|
|
|
|
// FIXME: Protocol methods ?
|
|
|
|
if (isa<ObjCProtocolDecl>(D->getDeclContext()))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
// No specific interface associated with the message. Can be anything.
|
|
|
|
if (MsgIFaceEnt.isInvalid())
|
|
|
|
return true;
|
|
|
|
|
2009-07-30 08:11:31 +08:00
|
|
|
if ((!CanBeInstanceMethod && D->isInstanceMethod()) ||
|
|
|
|
(!CanBeClassMethod && D->isClassMethod()))
|
2009-07-30 08:03:55 +08:00
|
|
|
return false;
|
|
|
|
|
|
|
|
ObjCInterfaceDecl *IFace = D->getClassInterface();
|
|
|
|
assert(IFace);
|
|
|
|
|
|
|
|
// If the original message interface is the same or a superclass of the
|
|
|
|
// given interface, accept the method as a possibility.
|
|
|
|
if (MsgIFace && MsgIFace->isSuperClassOf(IFace))
|
|
|
|
return true;
|
|
|
|
|
|
|
|
if (ReceiverIFace) {
|
|
|
|
// The given interface, "overrides" the receiver.
|
|
|
|
if (ReceiverIFace->isSuperClassOf(IFace))
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
// No receiver was found for the original message.
|
|
|
|
assert(ReceiverIFaceEnt.isInvalid());
|
|
|
|
|
|
|
|
// If the original message interface is a subclass of the given interface,
|
|
|
|
// accept the message.
|
|
|
|
if (HierarchyEntities.count(Entity::get(IFace, Prog)))
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The interfaces are unrelated, or the receiver interface wasn't
|
|
|
|
// "overriden".
|
|
|
|
return false;
|
2009-07-30 07:40:14 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
// Analyzer Implementation
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
void Analyzer::FindDeclarations(Decl *D, TULocationHandler &Handler) {
|
|
|
|
assert(D && "Passed null declaration");
|
|
|
|
Entity Ent = Entity::get(D, Prog);
|
|
|
|
if (Ent.isInvalid())
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 07:40:14 +08:00
|
|
|
DeclEntityAnalyzer DEA(Ent, Handler);
|
|
|
|
Idxer.GetTranslationUnitsFor(Ent, DEA);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Analyzer::FindReferences(Decl *D, TULocationHandler &Handler) {
|
|
|
|
assert(D && "Passed null declaration");
|
2009-07-30 08:03:55 +08:00
|
|
|
if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
|
|
|
|
RefSelectorAnalyzer RSA(MD, Prog, Handler);
|
|
|
|
GlobalSelector Sel = GlobalSelector::get(MD->getSelector(), Prog);
|
|
|
|
Idxer.GetTranslationUnitsFor(Sel, RSA);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2009-07-30 07:40:14 +08:00
|
|
|
Entity Ent = Entity::get(D, Prog);
|
|
|
|
if (Ent.isInvalid())
|
|
|
|
return;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-30 07:40:14 +08:00
|
|
|
RefEntityAnalyzer REA(Ent, Handler);
|
|
|
|
Idxer.GetTranslationUnitsFor(Ent, REA);
|
|
|
|
}
|
2009-07-30 08:03:55 +08:00
|
|
|
|
|
|
|
/// \brief Find methods that may respond to the given message and pass them
|
|
|
|
/// to Handler.
|
|
|
|
void Analyzer::FindObjCMethods(ObjCMessageExpr *Msg,
|
|
|
|
TULocationHandler &Handler) {
|
|
|
|
assert(Msg);
|
|
|
|
MessageAnalyzer MsgAnalyz(Msg, Prog, Handler);
|
|
|
|
GlobalSelector GlobSel = GlobalSelector::get(Msg->getSelector(), Prog);
|
|
|
|
Idxer.GetTranslationUnitsFor(GlobSel, MsgAnalyz);
|
|
|
|
}
|