From: Fariborz Jahanian Date: Tue, 19 Aug 2014 23:39:17 +0000 (+0000) Subject: Objective-C [qoi]. Provide fix-it hint when sending X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b9f1d9e8410df27472c13c9fca922762d4844250;p=clang Objective-C [qoi]. Provide fix-it hint when sending class method to an object receiver. rdar://16263395 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@216038 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 532e4d5bb8..5d427aada7 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -591,6 +591,8 @@ def note_class_declared : Note< "class is declared here">; def note_receiver_class_declared : Note< "receiver is instance of class declared here">; +def note_receiver_expr_here : Note< + "receiver expression is here">; def note_receiver_is_id : Note< "receiver is treated with 'id' type for purpose of method lookup">; def note_suppressed_class_declare : Note< diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index eb53a93c6a..a9f043d5bf 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -8045,6 +8045,7 @@ public: ObjCMethodDecl *Method, bool isClassMessage, bool isSuperMessage, SourceLocation lbrac, SourceLocation rbrac, + SourceRange RecRange, QualType &ReturnType, ExprValueKind &VK); /// \brief Determine the result of a message send expression based on diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 39598b5a19..582e1834d4 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -1325,6 +1325,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, ObjCMethodDecl *Method, bool isClassMessage, bool isSuperMessage, SourceLocation lbrac, SourceLocation rbrac, + SourceRange RecRange, QualType &ReturnType, ExprValueKind &VK) { SourceLocation SelLoc; if (!SelectorLocs.empty() && SelectorLocs.front().isValid()) @@ -1379,9 +1380,15 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType, SelectorLocs.back()); // Find the class to which we are sending this message. if (ReceiverType->isObjCObjectPointerType()) { - if (ObjCInterfaceDecl *Class = - ReceiverType->getAs()->getInterfaceDecl()) - Diag(Class->getLocation(), diag::note_receiver_class_declared); + if (ObjCInterfaceDecl *ThisClass = + ReceiverType->getAs()->getInterfaceDecl()) { + Diag(ThisClass->getLocation(), diag::note_receiver_class_declared); + if (!RecRange.isInvalid()) + if (ThisClass->lookupClassMethod(Sel)) + Diag(RecRange.getBegin(),diag::note_receiver_expr_here) + << FixItHint::CreateReplacement(RecRange, + ThisClass->getNameAsString()); + } } } @@ -2214,7 +2221,8 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo, if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs), Sel, SelectorLocs, Method, true, - SuperLoc.isValid(), LBracLoc, RBracLoc, + SuperLoc.isValid(), LBracLoc, RBracLoc, + SourceRange(), ReturnType, VK)) return ExprError(); @@ -2619,7 +2627,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver, if (CheckMessageArgumentTypes(ReceiverType, MultiExprArg(Args, NumArgs), Sel, SelectorLocs, Method, ClassMessage, SuperLoc.isValid(), - LBracLoc, RBracLoc, ReturnType, VK)) + LBracLoc, RBracLoc, RecRange, ReturnType, VK)) return ExprError(); if (Method && !Method->getReturnType()->isVoidType() && diff --git a/test/FixIt/fixit-class-method-messaging.m b/test/FixIt/fixit-class-method-messaging.m new file mode 100644 index 0000000000..e2592d0c87 --- /dev/null +++ b/test/FixIt/fixit-class-method-messaging.m @@ -0,0 +1,30 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fdiagnostics-parseable-fixits %s 2>&1 | FileCheck %s +// rdar://16263395 + +@interface NSObject @end + +@interface I : NSObject // expected-note 3 {{receiver is instance of class declared here}} ++ (id) ClassMeth; +- (I*) MethInstPI; +@end + +I* pi; + +I* foobar(); + +@implementation I +- (id) PrivInstMeth { + [ foobar() ClassMeth]; // expected-warning {{instance method '-ClassMeth' not found (return type defaults to 'id')}} \ + // expected-note {{receiver expression is here}} +// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:5-[[@LINE-2]]:13}:"I + [[self MethInstPI] ClassMeth]; // expected-warning {{instance method '-ClassMeth' not found (return type defaults to 'id')}} \ + // expected-note {{receiver expression is here}} +// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:4-[[@LINE-2]]:21}:"I + return [pi ClassMeth]; // expected-warning {{instance method '-ClassMeth' not found (return type defaults to 'id')}} \ + // expected-note {{receiver expression is here}} +// CHECK: fix-it:"{{.*}}":{[[@LINE-2]]:11-[[@LINE-2]]:13}:"I +} ++ (id) ClassMeth { return 0; } +- (I*) MethInstPI { return 0; } +@end