diff --git a/clang/AST/Decl.cpp b/clang/AST/Decl.cpp index cebd29525d52..188f3255dee0 100644 --- a/clang/AST/Decl.cpp +++ b/clang/AST/Decl.cpp @@ -543,3 +543,45 @@ ObjcMethodDecl *ObjcCategoryImplDecl::lookupClassMethod(Selector &Sel) { } return NULL; } + +// lookupInstanceMethod - Lookup a instance method in the protocol and protocols +// it inherited. +ObjcMethodDecl *ObjcProtocolDecl::lookupInstanceMethod(Selector &Sel) { + ObjcMethodDecl *const*methods = getInstanceMethods(); + int methodCount = getNumInstanceMethods(); + for (int i = 0; i < methodCount; ++i) { + if (methods[i]->getSelector() == Sel) { + return methods[i]; + } + } + if (getNumReferencedProtocols() > 0) { + ObjcProtocolDecl **RefPDecl = getReferencedProtocols(); + + for (int i = 0; i < getNumReferencedProtocols(); i++) { + if (ObjcMethodDecl *Method = RefPDecl[i]->lookupInstanceMethod(Sel)) + return Method; + } + } + return NULL; +} + +// lookupInstanceMethod - Lookup a class method in the protocol and protocols +// it inherited. +ObjcMethodDecl *ObjcProtocolDecl::lookupClassMethod(Selector &Sel) { + ObjcMethodDecl *const*methods = getClassMethods(); + int methodCount = getNumClassMethods(); + for (int i = 0; i < methodCount; ++i) { + if (methods[i]->getSelector() == Sel) { + return methods[i]; + } + } + if (getNumReferencedProtocols() > 0) { + ObjcProtocolDecl **RefPDecl = getReferencedProtocols(); + + for (int i = 0; i < getNumReferencedProtocols(); i++) { + if (ObjcMethodDecl *Method = RefPDecl[i]->lookupClassMethod(Sel)) + return Method; + } + } + return NULL; +} diff --git a/clang/Driver/RewriteTest.cpp b/clang/Driver/RewriteTest.cpp index 9c845a447336..2a189ad85b34 100644 --- a/clang/Driver/RewriteTest.cpp +++ b/clang/Driver/RewriteTest.cpp @@ -1446,6 +1446,10 @@ Stmt *RewriteTest::RewriteMessageExpr(ObjCMessageExpr *Exp) { SourceLocation()); MsgExprs.push_back(Unop); } else { + // Remove all type-casts because it may contain objc-style types; e.g. + // Foo *. + while (CastExpr *CE = dyn_cast(recExpr)) + recExpr = CE->getSubExpr(); recExpr = new CastExpr(Context->getObjcIdType(), recExpr, SourceLocation()); MsgExprs.push_back(recExpr); } diff --git a/clang/Sema/SemaExpr.cpp b/clang/Sema/SemaExpr.cpp index e7102aa0a261..8c5ef43f4c56 100644 --- a/clang/Sema/SemaExpr.cpp +++ b/clang/Sema/SemaExpr.cpp @@ -2232,14 +2232,32 @@ Sema::ExprResult Sema::ActOnInstanceMessage( static_cast(receiverType.getTypePtr()); receiverType = pointerType->getPointeeType(); } - assert(ObjcInterfaceType::classof(receiverType.getTypePtr()) && - "bad receiver type"); - ObjcInterfaceDecl* ClassDecl = static_cast( - receiverType.getTypePtr())->getDecl(); - // FIXME: consider using InstanceMethodPool, since it will be faster - // than the following method (which can do *many* linear searches). The - // idea is to add class info to InstanceMethodPool... - Method = ClassDecl->lookupInstanceMethod(Sel); + ObjcInterfaceDecl* ClassDecl; + if (ObjcQualifiedInterfaceType *QIT = + dyn_cast(receiverType)) { + ObjcInterfaceType * OITypePtr = QIT->getInterfaceType(); + + ClassDecl = OITypePtr->getDecl(); + Method = ClassDecl->lookupInstanceMethod(Sel); + if (!Method) { + // search protocols + for (unsigned i = 0; i < QIT->getNumProtocols(); i++) { + ObjcProtocolDecl *PDecl = QIT->getProtocols(i); + if (PDecl && (Method = PDecl->lookupInstanceMethod(Sel))) + break; + } + } + } + else { + assert(ObjcInterfaceType::classof(receiverType.getTypePtr()) && + "bad receiver type"); + ClassDecl = static_cast( + receiverType.getTypePtr())->getDecl(); + // FIXME: consider using InstanceMethodPool, since it will be faster + // than the following method (which can do *many* linear searches). The + // idea is to add class info to InstanceMethodPool... + Method = ClassDecl->lookupInstanceMethod(Sel); + } if (!Method) { // If we have an implementation in scope, check "private" methods. if (ObjcImplementationDecl *ImpDecl = diff --git a/clang/include/clang/AST/DeclObjC.h b/clang/include/clang/AST/DeclObjC.h index 5432a4c2a46a..4a4bcf10db7e 100644 --- a/clang/include/clang/AST/DeclObjC.h +++ b/clang/include/clang/AST/DeclObjC.h @@ -283,6 +283,9 @@ public: ObjcMethodDecl** getClassMethods() const { return ClassMethods; } int getNumClassMethods() const { return NumClassMethods; } + ObjcMethodDecl *lookupInstanceMethod(Selector &Sel); + ObjcMethodDecl *lookupClassMethod(Selector &Sel); + bool isForwardDecl() const { return isForwardProtoDecl; } void setForwardDecl(bool val) { isForwardProtoDecl = val; }