From: Fariborz Jahanian Date: Fri, 7 Dec 2007 21:21:21 +0000 (+0000) Subject: Implemented when static typing is combined with protocols and use as receiver X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7dd82836dca87cf828ce994f161b53a34f6cdb7e;p=clang Implemented when static typing is combined with protocols and use as receiver type. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@44685 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/AST/Decl.cpp b/AST/Decl.cpp index cebd29525d..188f3255de 100644 --- a/AST/Decl.cpp +++ b/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/Driver/RewriteTest.cpp b/Driver/RewriteTest.cpp index 9c845a4473..2a189ad85b 100644 --- a/Driver/RewriteTest.cpp +++ b/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/Sema/SemaExpr.cpp b/Sema/SemaExpr.cpp index e7102aa0a2..8c5ef43f4c 100644 --- a/Sema/SemaExpr.cpp +++ b/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/include/clang/AST/DeclObjC.h b/include/clang/AST/DeclObjC.h index 5432a4c2a4..4a4bcf10db 100644 --- a/include/clang/AST/DeclObjC.h +++ b/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; }