Lookup selector in protocol list of qualified objc type
to avoid a bogus warning. // rdar:// 9072298



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127355 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h
index f7d9e80..b3761f3 100644
--- a/include/clang/Sema/Sema.h
+++ b/include/clang/Sema/Sema.h
@@ -4551,6 +4551,9 @@
                                            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/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp
index 3d8d42f..5826f29 100644
--- a/lib/Sema/SemaExprObjC.cpp
+++ b/lib/Sema/SemaExprObjC.cpp
@@ -381,6 +381,23 @@
   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/lib/Sema/SemaStmt.cpp b/lib/Sema/SemaStmt.cpp
index ca37df9..dae6bce 100644
--- a/lib/Sema/SemaStmt.cpp
+++ b/lib/Sema/SemaStmt.cpp
@@ -991,7 +991,8 @@
       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/test/SemaObjC/foreach.m b/test/SemaObjC/foreach.m
index 0f7fd9e..c865374 100644
--- a/test/SemaObjC/foreach.m
+++ b/test/SemaObjC/foreach.m
@@ -16,3 +16,33 @@
   for (id thisKey in keys);
   for (id thisKey in keys);
 }
+
+/* // rdar://9072298 */
+@protocol NSObject @end
+
+@interface NSObject <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<NSFastEnumeration>* collection = ((void*)0);
+ for (id thing in collection) { }
+
+ return 0;
+}
+