diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index f7d9e80c7bc6..b3761f36dac5 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -4551,6 +4551,9 @@ public: ObjCInterfaceDecl *CDecl); ObjCMethodDecl *LookupPrivateInstanceMethod(Selector Sel, ObjCInterfaceDecl *ClassDecl); + ObjCMethodDecl *LookupMethodInQualifiedType(Selector Sel, + const ObjCObjectPointerType *OPT, + bool IsInstance); ExprResult HandleExprPropertyRefExpr(const ObjCObjectPointerType *OPT, diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 3d8d42fa001e..5826f296c1fa 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -381,6 +381,23 @@ ObjCMethodDecl *Sema::LookupPrivateInstanceMethod(Selector Sel, return Method; } +/// LookupMethodInQualifiedType - Lookups up a method in protocol qualifier +/// list of a qualified objective pointer type. +ObjCMethodDecl *Sema::LookupMethodInQualifiedType(Selector Sel, + const ObjCObjectPointerType *OPT, + bool Instance) +{ + ObjCMethodDecl *MD = 0; + for (ObjCObjectPointerType::qual_iterator I = OPT->qual_begin(), + E = OPT->qual_end(); I != E; ++I) { + ObjCProtocolDecl *PROTO = (*I); + if ((MD = PROTO->lookupMethod(Sel, Instance))) { + return MD; + } + } + return 0; +} + /// HandleExprPropertyRefExpr - Handle foo.bar where foo is a pointer to an /// objective C interface. This is a property reference expression. ExprResult Sema:: diff --git a/clang/lib/Sema/SemaStmt.cpp b/clang/lib/Sema/SemaStmt.cpp index ca37df943890..dae6bce6266c 100644 --- a/clang/lib/Sema/SemaStmt.cpp +++ b/clang/lib/Sema/SemaStmt.cpp @@ -991,7 +991,8 @@ Sema::ActOnObjCForCollectionStmt(SourceLocation ForLoc, Selector CSelector = Context.Selectors.getSelector(3, &KeyIdents[0]); if (ObjCInterfaceDecl *IDecl = OPT->getInterfaceDecl()) { if (!IDecl->isForwardDecl() && - !IDecl->lookupInstanceMethod(CSelector)) { + !IDecl->lookupInstanceMethod(CSelector) && + !LookupMethodInQualifiedType(CSelector, OPT, true)) { // Must further look into private implementation methods. if (!LookupPrivateInstanceMethod(CSelector, IDecl)) Diag(ForLoc, diag::warn_collection_expr_type) diff --git a/clang/test/SemaObjC/foreach.m b/clang/test/SemaObjC/foreach.m index 0f7fd9eea992..c865374e61af 100644 --- a/clang/test/SemaObjC/foreach.m +++ b/clang/test/SemaObjC/foreach.m @@ -16,3 +16,33 @@ void f(NSArray *a) { for (id thisKey in keys); for (id thisKey in keys); } + +/* // rdar://9072298 */ +@protocol NSObject @end + +@interface NSObject { + Class isa; +} +@end + +typedef struct { + unsigned long state; + id *itemsPtr; + unsigned long *mutationsPtr; + unsigned long extra[5]; +} NSFastEnumerationState; + +@protocol NSFastEnumeration + +- (unsigned long)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id *)stackbuf count:(unsigned long)len; + +@end + +int main () +{ + NSObject* collection = ((void*)0); + for (id thing in collection) { } + + return 0; +} +