aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AST/Decl.cpp42
-rw-r--r--Driver/RewriteTest.cpp4
-rw-r--r--Sema/SemaExpr.cpp34
-rw-r--r--include/clang/AST/DeclObjC.h3
4 files changed, 75 insertions, 8 deletions
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<Proto> *.
+ while (CastExpr *CE = dyn_cast<CastExpr>(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<PointerType*>(receiverType.getTypePtr());
receiverType = pointerType->getPointeeType();
}
- assert(ObjcInterfaceType::classof(receiverType.getTypePtr()) &&
- "bad receiver type");
- ObjcInterfaceDecl* ClassDecl = static_cast<ObjcInterfaceType*>(
- 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<ObjcQualifiedInterfaceType>(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<ObjcInterfaceType*>(
+ 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; }