diff options
author | Fariborz Jahanian <fjahanian@apple.com> | 2013-06-18 15:31:36 +0000 |
---|---|---|
committer | Fariborz Jahanian <fjahanian@apple.com> | 2013-06-18 15:31:36 +0000 |
commit | 4cc5552b9b9468b392a2cbb4bed72f1d3f2b67f5 (patch) | |
tree | 69dd574d541a15699aaf666f25e09d39d637a6ec | |
parent | 62c013db6ce8dabac58a313c5e4ca05e75e45881 (diff) | |
download | bcm5719-llvm-4cc5552b9b9468b392a2cbb4bed72f1d3f2b67f5.tar.gz bcm5719-llvm-4cc5552b9b9468b392a2cbb4bed72f1d3f2b67f5.zip |
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
llvm-svn: 184195
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 12 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclObjC.cpp | 36 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 18 | ||||
-rw-r--r-- | clang/test/FixIt/selector-fixit.m | 1 | ||||
-rw-r--r-- | clang/test/SemaObjC/arc.m | 2 | ||||
-rw-r--r-- | clang/test/SemaObjC/call-super-2.m | 4 | ||||
-rw-r--r-- | clang/test/SemaObjC/protocol-id-test-1.m | 2 | ||||
-rw-r--r-- | clang/test/SemaObjC/protocol-id-test-2.m | 2 |
8 files changed, 54 insertions, 23 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 7be10c8e706..84f98a95d0f 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/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<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< diff --git a/clang/lib/Sema/SemaDeclObjC.cpp b/clang/lib/Sema/SemaDeclObjC.cpp index b3102efe475..b62487bee72 100644 --- a/clang/lib/Sema/SemaDeclObjC.cpp +++ b/clang/lib/Sema/SemaDeclObjC.cpp @@ -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; diff --git a/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 5b994cbe784..678a1291ae1 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/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/clang/test/FixIt/selector-fixit.m b/clang/test/FixIt/selector-fixit.m index ed7c7186ffe..e9d2f19df1a 100644 --- a/clang/test/FixIt/selector-fixit.m +++ b/clang/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/clang/test/SemaObjC/arc.m b/clang/test/SemaObjC/arc.m index 1d4e42de649..2646adce94f 100644 --- a/clang/test/SemaObjC/arc.m +++ b/clang/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/clang/test/SemaObjC/call-super-2.m b/clang/test/SemaObjC/call-super-2.m index 0a07c014074..8927f3b5286 100644 --- a/clang/test/SemaObjC/call-super-2.m +++ b/clang/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/clang/test/SemaObjC/protocol-id-test-1.m b/clang/test/SemaObjC/protocol-id-test-1.m index 6583b3c7ea4..2366f732655 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 {{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 diff --git a/clang/test/SemaObjC/protocol-id-test-2.m b/clang/test/SemaObjC/protocol-id-test-2.m index 6bd2feeeaf1..4c1befb97f6 100644 --- a/clang/test/SemaObjC/protocol-id-test-2.m +++ b/clang/test/SemaObjC/protocol-id-test-2.m @@ -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 |