diff options
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 3 | ||||
| -rw-r--r-- | clang/include/clang/Sema/Sema.h | 3 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 18 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 18 | ||||
| -rw-r--r-- | clang/test/FixIt/selector-fixit.m | 10 | ||||
| -rw-r--r-- | clang/test/SemaObjC/call-super-2.m | 2 | ||||
| -rw-r--r-- | clang/test/SemaObjC/protocol-id-test-1.m | 2 |
7 files changed, 48 insertions, 8 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index eddf1e2e950..cb207a6c6dc 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4601,6 +4601,9 @@ 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 error_no_super_class_message : Error< "no @interface declaration found in class messaging of %0">; def error_root_class_cannot_use_super : Error< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 03952feea35..ca20c04fa60 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -2672,7 +2672,8 @@ public: warn, /*instance*/false); } - const ObjCMethodDecl *SelectorsForTypoCorrection(Selector Sel); + const ObjCMethodDecl *SelectorsForTypoCorrection(Selector Sel, + QualType ObjectType=QualType()); /// DiagnoseMismatchedMethodsInGlobalPool - This routine goes through list of /// methods in global pool and issues diagnostic on identical selectors which diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index 07282935c8a..b3102efe475 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -2295,8 +2295,18 @@ HelperSelectorsForTypoCorrection( } } +static bool HelperIsMethodInObjCType(Sema &S, Selector Sel, + QualType ObjectType) { + if (ObjectType.isNull()) + return true; + if (S.LookupMethodInObjectType(Sel, ObjectType, true/*Instance method*/)) + return true; + return S.LookupMethodInObjectType(Sel, ObjectType, false/*Class method*/) != 0; +} + const ObjCMethodDecl * -Sema::SelectorsForTypoCorrection(Selector Sel) { +Sema::SelectorsForTypoCorrection(Selector Sel, + QualType ObjectType) { unsigned NumArgs = Sel.getNumArgs(); SmallVector<const ObjCMethodDecl *, 8> Methods; @@ -2305,12 +2315,14 @@ Sema::SelectorsForTypoCorrection(Selector Sel) { // instance methods for (ObjCMethodList *M = &b->second.first; M; M=M->getNext()) if (M->Method && - (M->Method->getSelector().getNumArgs() == NumArgs)) + (M->Method->getSelector().getNumArgs() == NumArgs) && + 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)) + (M->Method->getSelector().getNumArgs() == NumArgs) && + HelperIsMethodInObjCType(*this, M->Method->getSelector(), ObjectType)) Methods.push_back(M->Method); } diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index b21f8e70f5d..5b994cbe784 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/lib/Sema/SemaExprObjC.cpp @@ -1232,8 +1232,22 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, DiagID = isClassMessage ? diag::warn_class_method_not_found : diag::warn_inst_method_not_found; if (!getLangOpts().DebuggerSupport) { - Diag(SelLoc, DiagID) - << Sel << isClassMessage << SourceRange(SelectorLocs.front(), + const ObjCMethodDecl *OMD = 0; + if (const ObjCObjectPointerType *ObjCPtr = + ReceiverType->getAsObjCInterfacePointerType()) { + QualType ObjectType = QualType(ObjCPtr->getInterfaceType(), 0); + OMD = SelectorsForTypoCorrection(Sel, ObjectType); + } + if (OMD) { + Selector MatchedSel = OMD->getSelector(); + SourceRange SelectorRange(SelectorLocs.front(), SelectorLocs.back()); + Diag(SelLoc, diag::warn_method_not_found_with_typo) + << isClassMessage << Sel << MatchedSel + << FixItHint::CreateReplacement(SelectorRange, MatchedSel.getAsString()); + } + else + Diag(SelLoc, DiagID) + << Sel << isClassMessage << SourceRange(SelectorLocs.front(), SelectorLocs.back()); // Find the class to which we are sending this message. if (ReceiverType->isObjCObjectPointerType()) { diff --git a/clang/test/FixIt/selector-fixit.m b/clang/test/FixIt/selector-fixit.m index a8b38c6b9ef..ed7c7186ffe 100644 --- a/clang/test/FixIt/selector-fixit.m +++ b/clang/test/FixIt/selector-fixit.m @@ -28,3 +28,13 @@ } @end + +// rdar://7853549 +@interface rdar7853549 : NSObject +- (int) bounds; +@end + +@implementation rdar7853549 +- (int) bounds { return 0; } +- (void)PrivateMeth { int bounds = [self bonds]; } +@end diff --git a/clang/test/SemaObjC/call-super-2.m b/clang/test/SemaObjC/call-super-2.m index 25cfbdd0879..071f9fdfd81 100644 --- a/clang/test/SemaObjC/call-super-2.m +++ b/clang/test/SemaObjC/call-super-2.m @@ -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')}} + int i = (size_t)[self instance_func0]; // expected-warning {{instance method 'instance_func0' not found (return type defaults to 'id'); did you mean 'instance_func3'?}} return i + (size_t)[super instance_func0]; // expected-warning {{'Object' may not respond to 'instance_func0'}} } - (int) instance_func2 diff --git a/clang/test/SemaObjC/protocol-id-test-1.m b/clang/test/SemaObjC/protocol-id-test-1.m index 36e23ed9f29..6583b3c7ea4 100644 --- a/clang/test/SemaObjC/protocol-id-test-1.m +++ b/clang/test/SemaObjC/protocol-id-test-1.m @@ -12,5 +12,5 @@ @end @implementation INTF -- (void)IMeth {INTF<P> *pi; [pi Meth]; } // expected-warning {{method '-Meth' not found (return type defaults to 'id')}} +- (void)IMeth {INTF<P> *pi; [pi Meth]; } // expected-warning {{instance method 'Meth' not found (return type defaults to 'id'); did you mean 'IMeth'?}} @end |

