]> granicus.if.org Git - clang/commitdiff
Objective-C [qoi]: privide typo correction for selectors
authorFariborz Jahanian <fjahanian@apple.com>
Tue, 18 Jun 2013 15:31:36 +0000 (15:31 +0000)
committerFariborz Jahanian <fjahanian@apple.com>
Tue, 18 Jun 2013 15:31:36 +0000 (15:31 +0000)
in addition of receiver having static type, but also when
receiver has dynamic type (of 'id' variety) as well as when
receiver is of 'Class' type vareity. // rdar://7853549

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@184195 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDeclObjC.cpp
lib/Sema/SemaExprObjC.cpp
test/FixIt/selector-fixit.m
test/SemaObjC/arc.m
test/SemaObjC/call-super-2.m
test/SemaObjC/protocol-id-test-1.m
test/SemaObjC/protocol-id-test-2.m

index 7be10c8e70683e2531ffd383e5628c7a8c521ee7..84f98a95d0f16efa7cca61dfcb7f77beb77682e8 100644 (file)
@@ -4601,9 +4601,15 @@ def warn_instance_method_on_class_found : Warning<
 def warn_inst_method_not_found : Warning<
   "instance method %objcinstance0 not found (return type defaults to 'id')">,
   InGroup<MethodAccess>;
-def warn_method_not_found_with_typo : Warning<
-  "%select{instance|class}0 method %1 not found (return type defaults to 'id')"
-  "; did you mean %2?">, InGroup<MethodAccess>;
+def warn_instance_method_not_found_with_typo : Warning<
+  "instance method %objcinstance0 not found (return type defaults to 'id')"
+  "; did you mean %objcinstance2?">, InGroup<MethodAccess>;
+def warn_class_method_not_found_with_typo : Warning<
+  "class method %objcclass0 not found (return type defaults to 'id')"
+  "; did you mean %objcclass2?">, InGroup<MethodAccess>;
+def error_method_not_found_with_typo : Error<
+  "%select{instance|class}1 method %0 not found "
+  "; did you mean %2?">;
 def error_no_super_class_message : Error<
   "no @interface declaration found in class messaging of %0">;
 def error_root_class_cannot_use_super : Error<
index b3102efe475829d6523b11c6ddde5f397cf95191..b62487bee72955e19532551ff766b5b43fc64237 100644 (file)
@@ -2309,21 +2309,45 @@ Sema::SelectorsForTypoCorrection(Selector Sel,
                                  QualType ObjectType) {
   unsigned NumArgs = Sel.getNumArgs();
   SmallVector<const ObjCMethodDecl *, 8> Methods;
+  bool ObjectIsId = true, ObjectIsClass = true;
+  if (ObjectType.isNull())
+    ObjectIsId = ObjectIsClass = false;
+  else if (!ObjectType->isObjCObjectPointerType())
+    return 0;
+  else if (const ObjCObjectPointerType *ObjCPtr =
+           ObjectType->getAsObjCInterfacePointerType()) {
+    ObjectType = QualType(ObjCPtr->getInterfaceType(), 0);
+    ObjectIsId = ObjectIsClass = false;
+  }
+  else if (ObjectType->isObjCIdType() || ObjectType->isObjCQualifiedIdType())
+    ObjectIsClass = false;
+  else if (ObjectType->isObjCClassType() || ObjectType->isObjCQualifiedClassType())
+    ObjectIsId = false;
+  else
+    return 0;
   
   for (GlobalMethodPool::iterator b = MethodPool.begin(),
        e = MethodPool.end(); b != e; b++) {
     // instance methods
     for (ObjCMethodList *M = &b->second.first; M; M=M->getNext())
       if (M->Method &&
-          (M->Method->getSelector().getNumArgs() == NumArgs) &&
-          HelperIsMethodInObjCType(*this, M->Method->getSelector(), ObjectType))
-        Methods.push_back(M->Method);
+          (M->Method->getSelector().getNumArgs() == NumArgs)) {
+        if (ObjectIsId)
+          Methods.push_back(M->Method);
+        else if (!ObjectIsClass &&
+                 HelperIsMethodInObjCType(*this, M->Method->getSelector(), ObjectType))
+          Methods.push_back(M->Method);
+      }
     // class methods
     for (ObjCMethodList *M = &b->second.second; M; M=M->getNext())
       if (M->Method &&
-          (M->Method->getSelector().getNumArgs() == NumArgs) &&
-          HelperIsMethodInObjCType(*this, M->Method->getSelector(), ObjectType))
-        Methods.push_back(M->Method);
+          (M->Method->getSelector().getNumArgs() == NumArgs)) {
+        if (ObjectIsClass)
+          Methods.push_back(M->Method);
+        else if (!ObjectIsId &&
+                 HelperIsMethodInObjCType(*this, M->Method->getSelector(), ObjectType))
+          Methods.push_back(M->Method);
+      }
   }
   
   SmallVector<const ObjCMethodDecl *, 8> SelectedMethods;
index 5b994cbe784247a2d08c07a69a5ef3e35aaec534..678a1291ae186b9c0e357f8f8afccadfaff5098c 100644 (file)
@@ -1232,17 +1232,17 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
       DiagID = isClassMessage ? diag::warn_class_method_not_found
                               : diag::warn_inst_method_not_found;
     if (!getLangOpts().DebuggerSupport) {
-      const ObjCMethodDecl *OMD = 0;
-      if (const ObjCObjectPointerType *ObjCPtr =
-          ReceiverType->getAsObjCInterfacePointerType()) {
-        QualType ObjectType = QualType(ObjCPtr->getInterfaceType(), 0);
-        OMD = SelectorsForTypoCorrection(Sel, ObjectType);
-      }
-      if (OMD) {
+      const ObjCMethodDecl *OMD = SelectorsForTypoCorrection(Sel, ReceiverType);
+      if (OMD && !OMD->isInvalidDecl() && OMD->getSelector() != Sel) {
+        if (getLangOpts().ObjCAutoRefCount)
+          DiagID = diag::error_method_not_found_with_typo;
+        else
+          DiagID = isClassMessage ? diag::warn_class_method_not_found_with_typo
+                                  : diag::warn_instance_method_not_found_with_typo;
         Selector MatchedSel = OMD->getSelector();
         SourceRange SelectorRange(SelectorLocs.front(), SelectorLocs.back());
-        Diag(SelLoc, diag::warn_method_not_found_with_typo)
-          << isClassMessage << Sel << MatchedSel
+        Diag(SelLoc, DiagID)
+          << Sel<< isClassMessage << MatchedSel
           << FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString());
       }
       else
index ed7c7186ffe0920e3e4d3f7eada45c51ed7af3f2..e9d2f19df1a1bdfacfdf0018d8d1c347f8238c3c 100644 (file)
@@ -37,4 +37,5 @@
 @implementation rdar7853549
 - (int) bounds { return 0; }
 - (void)PrivateMeth { int bounds = [self bonds]; }
+- (void)OtherPrivateMeth : (id) p { int bounds = [p bonds]; }
 @end
index 1d4e42de649da1077c464b579e84badc453928c4..2646adce94f95150b2e2aeac110f8f2d89cee9e2 100644 (file)
@@ -411,7 +411,7 @@ void test17(void) {
 
 void test18(void) {
   id x;
-  [x test18]; // expected-error {{no known instance method for selector 'test18'}}
+  [x test18]; // expected-error {{instance method 'test18' not found ; did you mean 'test17'?}}
 }
 
 extern struct Test19 *test19a;
index 0a07c0140746fd9113bddb95bcd8a9ae27d48fd3..8927f3b528648fa794edcae55e2b038dc27d675f 100644 (file)
@@ -35,7 +35,7 @@ id objc_getClass(const char *s);
 @implementation Derived
 + (int) class_func1
 {
-   int i = (size_t)[self class_func0];       // expected-warning {{class method '+class_func0' not found (return type defaults to 'id')}}
+   int i = (size_t)[self class_func0];       // expected-warning {{class method '+class_func0' not found (return type defaults to 'id'); did you mean '+class_func}}
    return i + (size_t)[super class_func0];   // expected-warning {{class method '+class_func0' not found (return type defaults to 'id')}}
 }
 + (int) class_func2
@@ -68,7 +68,7 @@ id objc_getClass(const char *s);
 }
 - (int) instance_func1
 {
-   int i = (size_t)[self instance_func0];     // expected-warning {{instance method 'instance_func0' not found (return type defaults to 'id'); did you mean}}
+   int i = (size_t)[self instance_func0];     // expected-warning {{instance method '-instance_func0' not found (return type defaults to 'id'); did you mean}}
    return i + (size_t)[super instance_func0]; // expected-warning {{'Object' may not respond to 'instance_func0'}}
 }
 - (int) instance_func2
index 6583b3c7ea4cbcc82386fbef2c2b9bc8e7d1b490..2366f7326550a65f690e81c224d5887aa868a97f 100644 (file)
@@ -12,5 +12,5 @@
 @end
 
 @implementation INTF
-- (void)IMeth {INTF<P> *pi;  [pi Meth]; } // expected-warning {{instance method 'Meth' not found (return type defaults to 'id'); did you mean 'IMeth'?}}
+- (void)IMeth {INTF<P> *pi;  [pi Meth]; } // expected-warning {{instance method '-Meth' not found (return type defaults to 'id'); did you mean '-IMeth'?}}
 @end
index 6bd2feeeaf1fd4a3fb6403eb427b2c2a78eca2fe..4c1befb97f62af013405cc6662eced493be2d78e 100644 (file)
@@ -8,5 +8,5 @@
 @end
 
 @implementation INTF
-- (void)IMeth { [(id<P>)self Meth]; }  // expected-warning {{method '-Meth' not found (return type defaults to 'id')}}
+- (void)IMeth { [(id<P>)self Meth]; }  // expected-warning {{instance method '-Meth' not found (return type defaults to 'id'); did you mean '-IMeth'?}}
 @end