From 419245e0719e1785e4eb3954ddaee122e921c738 Mon Sep 17 00:00:00 2001 From: Fariborz Jahanian Date: Tue, 18 Jun 2013 15:31:36 +0000 Subject: [PATCH] Objective-C [qoi]: privide typo correction for selectors 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 | 12 ++++++-- lib/Sema/SemaDeclObjC.cpp | 36 ++++++++++++++++++---- lib/Sema/SemaExprObjC.cpp | 18 +++++------ test/FixIt/selector-fixit.m | 1 + test/SemaObjC/arc.m | 2 +- test/SemaObjC/call-super-2.m | 4 +-- test/SemaObjC/protocol-id-test-1.m | 2 +- test/SemaObjC/protocol-id-test-2.m | 2 +- 8 files changed, 54 insertions(+), 23 deletions(-) diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 7be10c8e70..84f98a95d0 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -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; -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; +def warn_instance_method_not_found_with_typo : Warning< + "instance method %objcinstance0 not found (return type defaults to 'id')" + "; did you mean %objcinstance2?">, InGroup; +def warn_class_method_not_found_with_typo : Warning< + "class method %objcclass0 not found (return type defaults to 'id')" + "; did you mean %objcclass2?">, InGroup; +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< diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index b3102efe47..b62487bee7 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -2309,21 +2309,45 @@ Sema::SelectorsForTypoCorrection(Selector Sel, QualType ObjectType) { unsigned NumArgs = Sel.getNumArgs(); SmallVector 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 SelectedMethods; diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 5b994cbe78..678a1291ae 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -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 diff --git a/test/FixIt/selector-fixit.m b/test/FixIt/selector-fixit.m index ed7c7186ff..e9d2f19df1 100644 --- a/test/FixIt/selector-fixit.m +++ b/test/FixIt/selector-fixit.m @@ -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 diff --git a/test/SemaObjC/arc.m b/test/SemaObjC/arc.m index 1d4e42de64..2646adce94 100644 --- a/test/SemaObjC/arc.m +++ b/test/SemaObjC/arc.m @@ -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; diff --git a/test/SemaObjC/call-super-2.m b/test/SemaObjC/call-super-2.m index 0a07c01407..8927f3b528 100644 --- a/test/SemaObjC/call-super-2.m +++ b/test/SemaObjC/call-super-2.m @@ -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 diff --git a/test/SemaObjC/protocol-id-test-1.m b/test/SemaObjC/protocol-id-test-1.m index 6583b3c7ea..2366f73265 100644 --- a/test/SemaObjC/protocol-id-test-1.m +++ b/test/SemaObjC/protocol-id-test-1.m @@ -12,5 +12,5 @@ @end @implementation INTF -- (void)IMeth {INTF

*pi; [pi Meth]; } // expected-warning {{instance method 'Meth' not found (return type defaults to 'id'); did you mean 'IMeth'?}} +- (void)IMeth {INTF

*pi; [pi Meth]; } // expected-warning {{instance method '-Meth' not found (return type defaults to 'id'); did you mean '-IMeth'?}} @end diff --git a/test/SemaObjC/protocol-id-test-2.m b/test/SemaObjC/protocol-id-test-2.m index 6bd2feeeaf..4c1befb97f 100644 --- a/test/SemaObjC/protocol-id-test-2.m +++ b/test/SemaObjC/protocol-id-test-2.m @@ -8,5 +8,5 @@ @end @implementation INTF -- (void)IMeth { [(id

)self Meth]; } // expected-warning {{method '-Meth' not found (return type defaults to 'id')}} +- (void)IMeth { [(id

)self Meth]; } // expected-warning {{instance method '-Meth' not found (return type defaults to 'id'); did you mean '-IMeth'?}} @end -- 2.40.0