Commit 19c2e2fa authored by Fariborz Jahanian's avatar Fariborz Jahanian
Browse files

Objective-C [qoi]. Provide fix-it hint when sending

class method to an object receiver. rdar://16263395

llvm-svn: 216038
parent 57d5bc88
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -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<
+1 −0
Original line number Diff line number Diff line
@@ -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
+13 −5
Original line number Diff line number Diff line
@@ -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());
        }
      }
    }

@@ -2215,6 +2222,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
                                Sel, SelectorLocs,
                                Method, true,
                                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() &&
+30 −0
Original line number Diff line number Diff line
// 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