atch for implementation of objective-c's -Wselector
warning flag in clang. Little more to do
for a PCH issue. Radar 6507158.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@109129 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp
index 21aeb59..5f2f37e 100644
--- a/lib/Sema/SemaDeclObjC.cpp
+++ b/lib/Sema/SemaDeclObjC.cpp
@@ -32,10 +32,10 @@
 
   // Allow the rest of sema to find private method decl implementations.
   if (MDecl->isInstanceMethod())
-    AddInstanceMethodToGlobalPool(MDecl);
+    AddInstanceMethodToGlobalPool(MDecl, true);
   else
-    AddFactoryMethodToGlobalPool(MDecl);
-
+    AddFactoryMethodToGlobalPool(MDecl, true);
+  
   // Allow all of Sema to see that we are entering a method definition.
   PushDeclContext(FnBodyScope, MDecl);
   PushFunctionScope();
@@ -1130,7 +1130,7 @@
   return FactoryMethodPool.insert(std::make_pair(Sel, Methods.second)).first;
 }
 
-void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method) {
+void Sema::AddInstanceMethodToGlobalPool(ObjCMethodDecl *Method, bool impl) {
   llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos
     = InstanceMethodPool.find(Method->getSelector());
   if (Pos == InstanceMethodPool.end()) {
@@ -1140,7 +1140,7 @@
       Pos = InstanceMethodPool.insert(std::make_pair(Method->getSelector(),
                                                      ObjCMethodList())).first;
   }
-
+  Method->setDefined(impl);
   ObjCMethodList &Entry = Pos->second;
   if (Entry.Method == 0) {
     // Haven't seen a method with this selector name yet - add it.
@@ -1152,8 +1152,10 @@
   // We've seen a method with this name, see if we have already seen this type
   // signature.
   for (ObjCMethodList *List = &Entry; List; List = List->Next)
-    if (MatchTwoMethodDeclarations(Method, List->Method))
+    if (MatchTwoMethodDeclarations(Method, List->Method)) {
+      List->Method->setDefined(impl);
       return;
+    }
 
   // We have a new signature for an existing method - add it.
   // This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
@@ -1194,7 +1196,7 @@
   return MethList.Method;
 }
 
-void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method) {
+void Sema::AddFactoryMethodToGlobalPool(ObjCMethodDecl *Method, bool impl) {
   llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos
     = FactoryMethodPool.find(Method->getSelector());
   if (Pos == FactoryMethodPool.end()) {
@@ -1204,32 +1206,31 @@
       Pos = FactoryMethodPool.insert(std::make_pair(Method->getSelector(),
                                                     ObjCMethodList())).first;
   }
-
-  ObjCMethodList &FirstMethod = Pos->second;
-  if (!FirstMethod.Method) {
+  Method->setDefined(impl);
+  ObjCMethodList &Entry = Pos->second;
+  if (!Entry.Method) {
     // Haven't seen a method with this selector name yet - add it.
-    FirstMethod.Method = Method;
-    FirstMethod.Next = 0;
-  } else {
-    // We've seen a method with this name, now check the type signature(s).
-    bool match = MatchTwoMethodDeclarations(Method, FirstMethod.Method);
-
-    for (ObjCMethodList *Next = FirstMethod.Next; !match && Next;
-         Next = Next->Next)
-      match = MatchTwoMethodDeclarations(Method, Next->Method);
-
-    if (!match) {
-      // We have a new signature for an existing method - add it.
-      // This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
-      ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>();
-      ObjCMethodList *OMI = new (Mem) ObjCMethodList(Method, FirstMethod.Next);
-      FirstMethod.Next = OMI;
+    Entry.Method = Method;
+    Entry.Next = 0;
+    return;
+  } 
+  // We've seen a method with this name, see if we have already seen this type
+  // signature.
+  for (ObjCMethodList *List = &Entry; List; List = List->Next)
+    if (MatchTwoMethodDeclarations(Method, List->Method)) {
+      List->Method->setDefined(impl);
+      return;
     }
-  }
+  
+  // We have a new signature for an existing method - add it.
+  // This is extremely rare. Only 1% of Cocoa selectors are "overloaded".
+  ObjCMethodList *Mem = BumpAlloc.Allocate<ObjCMethodList>();
+  Entry.Next = new (Mem) ObjCMethodList(Method, Entry.Next);
 }
 
 ObjCMethodDecl *Sema::LookupFactoryMethodInGlobalPool(Selector Sel,
-                                                      SourceRange R) {
+                                                      SourceRange R,
+                                                      bool warn) {
   llvm::DenseMap<Selector, ObjCMethodList>::iterator Pos
     = FactoryMethodPool.find(Sel);
   if (Pos == FactoryMethodPool.end()) {
@@ -1246,7 +1247,7 @@
     for (ObjCMethodList *Next = MethList.Next; Next; Next = Next->Next)
       // This checks if the methods differ by size & alignment.
       if (!MatchTwoMethodDeclarations(MethList.Method, Next->Method, true))
-        issueWarning = true;
+        issueWarning = warn;
   }
   if (issueWarning && (MethList.Method && MethList.Next)) {
     Diag(R.getBegin(), diag::warn_multiple_method_decl) << Sel << R;
@@ -1259,6 +1260,18 @@
   return MethList.Method;
 }
 
+ObjCMethodDecl *Sema::LookupImplementedMethodInGlobalPool(Selector Sel) {
+  SourceRange SR;
+  ObjCMethodDecl *Method = LookupInstanceMethodInGlobalPool(Sel,
+                                                            SR, false);
+  if (Method && Method->isDefined())
+    return Method;
+  Method = LookupFactoryMethodInGlobalPool(Sel, SR, false);
+  if (Method && Method->isDefined())
+    return Method;
+  return 0;
+}
+
 /// CompareMethodParamsInBaseAndSuper - This routine compares methods with
 /// identical selector names in current and its super classes and issues
 /// a warning if any of their argument types are incompatible.
@@ -1540,7 +1553,7 @@
                            ResultTInfo,
                            cast<DeclContext>(ClassDecl),
                            MethodType == tok::minus, isVariadic,
-                           false,
+                           false, false,
                            MethodDeclKind == tok::objc_optional ?
                            ObjCMethodDecl::Optional :
                            ObjCMethodDecl::Required);
@@ -1849,3 +1862,15 @@
   }
 }
 
+void Sema::DiagnoseUseOfUnimplementedSelectors() {
+  if (ReferencedSelectors.empty())
+    return;
+  for (llvm::DenseMap<Selector, SourceLocation>::iterator S = 
+        ReferencedSelectors.begin(),
+       E = ReferencedSelectors.end(); S != E; ++S) {
+    Selector Sel = (*S).first;
+    if (!LookupImplementedMethodInGlobalPool(Sel))
+      Diag((*S).second, diag::warn_unimplemented_selector) << Sel;
+  }
+  return;
+}