aboutsummaryrefslogtreecommitdiff
path: root/lib/Index/Analyzer.cpp
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2010-04-21 00:45:42 +0000
committerDouglas Gregor <dgregor@apple.com>2010-04-21 00:45:42 +0000
commit04badcf84c8d504d8491c7c7e29b58f52cb16640 (patch)
tree99dc6c7a506db47b8d998c0fa9807f10f770db34 /lib/Index/Analyzer.cpp
parent10dc0f8c355c6a726f206aefcb249cb2fafbce17 (diff)
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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101972 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Index/Analyzer.cpp')
-rw-r--r--lib/Index/Analyzer.cpp79
1 files changed, 56 insertions, 23 deletions
diff --git a/lib/Index/Analyzer.cpp b/lib/Index/Analyzer.cpp
index 7b414f2a9f..1354fe6be0 100644
--- a/lib/Index/Analyzer.cpp
+++ b/lib/Index/Analyzer.cpp
@@ -153,9 +153,10 @@ public:
ObjCInterfaceDecl *MsgD = 0;
ObjCMessageExpr *Msg = cast<ObjCMessageExpr>(ASTLoc.AsStmt());
- if (Msg->getReceiver()) {
+ switch (Msg->getReceiverKind()) {
+ case ObjCMessageExpr::Instance: {
const ObjCObjectPointerType *OPT =
- Msg->getReceiver()->getType()->getAsObjCInterfacePointerType();
+ Msg->getInstanceReceiver()->getType()->getAsObjCInterfacePointerType();
// Can be anything! Accept it as a possibility..
if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType())
@@ -171,15 +172,34 @@ public:
// Should be an instance method.
if (!IsInstanceMethod)
return false;
+ break;
+ }
- } else {
+ case ObjCMessageExpr::Class: {
+ // Expecting class method.
+ if (IsInstanceMethod)
+ return false;
+
+ MsgD = Msg->getClassReceiver()->getAs<ObjCInterfaceType>()->getDecl();
+ break;
+ }
+
+ case ObjCMessageExpr::SuperClass:
// Expecting class method.
if (IsInstanceMethod)
return false;
- MsgD = Msg->getClassInfo().Decl;
- // FIXME: Case when we only have an identifier.
- assert(MsgD && "Identifier only");
+ MsgD = Msg->getSuperType()->getAs<ObjCInterfaceType>()->getDecl();
+ break;
+
+ case ObjCMessageExpr::SuperInstance:
+ // Expecting instance method.
+ if (!IsInstanceMethod)
+ return false;
+
+ MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>()
+ ->getInterfaceDecl();
+ break;
}
assert(MsgD);
@@ -248,31 +268,44 @@ public:
ObjCInterfaceDecl *MsgD = 0;
while (true) {
- if (Msg->getReceiver() == 0) {
- CanBeClassMethod = true;
- MsgD = Msg->getClassInfo().Decl;
- // FIXME: Case when we only have an identifier.
- assert(MsgD && "Identifier only");
- break;
- }
+ switch (Msg->getReceiverKind()) {
+ case ObjCMessageExpr::Instance: {
+ const ObjCObjectPointerType *OPT =
+ Msg->getInstanceReceiver()->getType()
+ ->getAsObjCInterfacePointerType();
+
+ if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()) {
+ CanBeInstanceMethod = CanBeClassMethod = true;
+ break;
+ }
- const ObjCObjectPointerType *OPT =
- Msg->getReceiver()->getType()->getAsObjCInterfacePointerType();
+ if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) {
+ CanBeClassMethod = true;
+ break;
+ }
- if (!OPT || OPT->isObjCIdType() || OPT->isObjCQualifiedIdType()) {
- CanBeInstanceMethod = CanBeClassMethod = true;
+ MsgD = OPT->getInterfaceDecl();
+ assert(MsgD);
+ CanBeInstanceMethod = true;
break;
}
+
+ case ObjCMessageExpr::Class:
+ CanBeClassMethod = true;
+ MsgD = Msg->getClassReceiver()->getAs<ObjCInterfaceType>()->getDecl();
+ break;
- if (OPT->isObjCClassType() || OPT->isObjCQualifiedClassType()) {
+ case ObjCMessageExpr::SuperClass:
CanBeClassMethod = true;
+ MsgD = Msg->getSuperType()->getAs<ObjCInterfaceType>()->getDecl();
break;
- }
- MsgD = OPT->getInterfaceDecl();
- assert(MsgD);
- CanBeInstanceMethod = true;
- break;
+ case ObjCMessageExpr::SuperInstance:
+ CanBeInstanceMethod = true;
+ MsgD = Msg->getSuperType()->getAs<ObjCObjectPointerType>()
+ ->getInterfaceDecl();
+ break;
+ }
}
assert(CanBeInstanceMethod || CanBeClassMethod);