diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 | ||||
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 1 | ||||
-rw-r--r-- | clang/lib/Sema/SemaExprObjC.cpp | 18 | ||||
-rw-r--r-- | clang/test/FixIt/fixit-class-method-messaging.m | 30 |
4 files changed, 46 insertions, 5 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 532e4d5bb84..5d427aada7b 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/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/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index eb53a93c6a2..a9f043d5bfd 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/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/clang/lib/Sema/SemaExprObjC.cpp b/clang/lib/Sema/SemaExprObjC.cpp index 39598b5a19a..582e1834d48 100644 --- a/clang/lib/Sema/SemaExprObjC.cpp +++ b/clang/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<ObjCObjectPointerType>()->getInterfaceDecl()) - Diag(Class->getLocation(), diag::note_receiver_class_declared); + if (ObjCInterfaceDecl *ThisClass = + ReceiverType->getAs<ObjCObjectPointerType>()->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/clang/test/FixIt/fixit-class-method-messaging.m b/clang/test/FixIt/fixit-class-method-messaging.m new file mode 100644 index 00000000000..e2592d0c87f --- /dev/null +++ b/clang/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 |