]> granicus.if.org Git - clang/commitdiff
Point diagnostics that complain about a use of a selector in an objc message, to...
authorArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 1 May 2013 00:24:09 +0000 (00:24 +0000)
committerArgyrios Kyrtzidis <akyrtzi@gmail.com>
Wed, 1 May 2013 00:24:09 +0000 (00:24 +0000)
Previously it would point to the left bracket or the receiver, which can be particularly
problematic if the receiver is a block literal and we end up point the diagnostic far away
for the selector that is complaining about.

rdar://13620447

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@180833 91177308-0d34-0410-b5e6-96231b3b80d8

lib/ARCMigrate/TransAPIUses.cpp
lib/ARCMigrate/TransRetainReleaseDealloc.cpp
lib/Sema/SemaExprObjC.cpp
test/ARCMT/check-with-serialized-diag.m
test/ARCMT/migrate-plist-output.m
test/SemaObjC/message.m
test/SemaObjC/warn-missing-super.m

index 2305b6defd9c25e3a9f3665eb1eefb951f68f4a0..a0994a6b459ac8177725ecd24a442cf3998613c9 100644 (file)
@@ -91,12 +91,12 @@ public:
         E->getSelector() == zoneSel &&
         Pass.TA.hasDiagnostic(diag::err_unavailable,
                               diag::err_unavailable_message,
-                              E->getInstanceReceiver()->getExprLoc())) {
+                              E->getSelectorLoc(0))) {
       // Calling -zone is meaningless in ARC, change it to nil.
       Transaction Trans(Pass.TA);
       Pass.TA.clearDiagnostic(diag::err_unavailable,
                               diag::err_unavailable_message,
-                              E->getInstanceReceiver()->getExprLoc());
+                              E->getSelectorLoc(0));
       Pass.TA.replace(E->getSourceRange(), getNilString(Pass.Ctx));
     }
     return true;
index 0c8d15544610e4abddd5a8a08450fa352c697749..446a284a286f0becce2c6e5eacb9c714439f2b4d 100644 (file)
@@ -118,7 +118,7 @@ public:
       return true;
     case ObjCMessageExpr::SuperInstance: {
       Transaction Trans(Pass.TA);
-      clearDiagnostics(E->getSuperLoc());
+      clearDiagnostics(E->getSelectorLoc(0));
       if (tryRemoving(E))
         return true;
       Pass.TA.replace(E->getSourceRange(), "self");
@@ -132,7 +132,7 @@ public:
     if (!rec) return true;
 
     Transaction Trans(Pass.TA);
-    clearDiagnostics(rec->getExprLoc());
+    clearDiagnostics(E->getSelectorLoc(0));
 
     ObjCMessageExpr *Msg = E;
     Expr *RecContainer = Msg;
index e7b5ec9b0168889c2218746d7debba91c136f2c8..fed86eed5176cfd3ed457f179da5dd29b2f178cc 100644 (file)
@@ -1191,6 +1191,12 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
                                      bool isClassMessage, bool isSuperMessage,
                                      SourceLocation lbrac, SourceLocation rbrac,
                                      QualType &ReturnType, ExprValueKind &VK) {
+  SourceLocation SelLoc;
+  if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
+    SelLoc = SelectorLocs.front();
+  else
+    SelLoc = lbrac;
+
   if (!Method) {
     // Apply default argument promotion as for (C99 6.5.2.2p6).
     for (unsigned i = 0; i != NumArgs; i++) {
@@ -1200,7 +1206,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
       ExprResult result;
       if (getLangOpts().DebuggerSupport) {
         QualType paramTy; // ignored
-        result = checkUnknownAnyArg(lbrac, Args[i], paramTy);
+        result = checkUnknownAnyArg(SelLoc, Args[i], paramTy);
       } else {
         result = DefaultArgumentPromotion(Args[i]);
       }
@@ -1216,7 +1222,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
       DiagID = isClassMessage ? diag::warn_class_method_not_found
                               : diag::warn_inst_method_not_found;
     if (!getLangOpts().DebuggerSupport)
-      Diag(lbrac, DiagID)
+      Diag(SelLoc, DiagID)
         << Sel << isClassMessage << SourceRange(SelectorLocs.front(), 
                                                 SelectorLocs.back());
 
@@ -1242,7 +1248,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
     NumNamedArgs = Method->param_size();
   // FIXME. This need be cleaned up.
   if (NumArgs < NumNamedArgs) {
-    Diag(lbrac, diag::err_typecheck_call_too_few_args)
+    Diag(SelLoc, diag::err_typecheck_call_too_few_args)
       << 2 << NumNamedArgs << NumArgs;
     return false;
   }
@@ -1268,7 +1274,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
     // from the argument.
     if (param->getType() == Context.UnknownAnyTy) {
       QualType paramType;
-      ExprResult argE = checkUnknownAnyArg(lbrac, argExpr, paramType);
+      ExprResult argE = checkUnknownAnyArg(SelLoc, argExpr, paramType);
       if (argE.isInvalid()) {
         IsError = true;
       } else {
@@ -1287,7 +1293,7 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
 
     InitializedEntity Entity = InitializedEntity::InitializeParameter(Context,
                                                                       param);
-    ExprResult ArgE = PerformCopyInitialization(Entity, lbrac, Owned(argExpr));
+    ExprResult ArgE = PerformCopyInitialization(Entity, SelLoc, Owned(argExpr));
     if (ArgE.isInvalid())
       IsError = true;
     else
@@ -1317,10 +1323,10 @@ bool Sema::CheckMessageArgumentTypes(QualType ReceiverType,
     }
   }
 
-  DiagnoseSentinelCalls(Method, lbrac, Args, NumArgs);
+  DiagnoseSentinelCalls(Method, SelLoc, Args, NumArgs);
 
   // Do additional checkings on method.
-  IsError |= CheckObjCMethodCall(Method, lbrac, Args, NumArgs);
+  IsError |= CheckObjCMethodCall(Method, SelLoc, Args, NumArgs);
 
   return IsError;
 }
@@ -1993,7 +1999,12 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
       << FixItHint::CreateInsertion(Loc, "[");
     LBracLoc = Loc;
   }
-  
+  SourceLocation SelLoc;
+  if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
+    SelLoc = SelectorLocs.front();
+  else
+    SelLoc = Loc;
+
   if (ReceiverType->isDependentType()) {
     // If the receiver type is dependent, we can't type-check anything
     // at this point. Build a dependent expression.
@@ -2018,7 +2029,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
   assert(Class && "We don't know which class we're messaging?");
   // objc++ diagnoses during typename annotation.
   if (!getLangOpts().CPlusPlus)
-    (void)DiagnoseUseOfDecl(Class, Loc);
+    (void)DiagnoseUseOfDecl(Class, SelLoc);
   // Find the method we are messaging.
   if (!Method) {
     SourceRange TypeRange 
@@ -2043,7 +2054,7 @@ ExprResult Sema::BuildClassMessage(TypeSourceInfo *ReceiverTypeInfo,
     if (!Method)
       Method = Class->lookupPrivateClassMethod(Sel);
 
-    if (Method && DiagnoseUseOfDecl(Method, Loc))
+    if (Method && DiagnoseUseOfDecl(Method, SelLoc))
       return ExprError();
   }
 
@@ -2159,7 +2170,14 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
                                       bool isImplicit) {
   // The location of the receiver.
   SourceLocation Loc = SuperLoc.isValid()? SuperLoc : Receiver->getLocStart();
-  
+  SourceRange RecRange =
+      SuperLoc.isValid()? SuperLoc : Receiver->getSourceRange();
+  SourceLocation SelLoc;
+  if (!SelectorLocs.empty() && SelectorLocs.front().isValid())
+    SelLoc = SelectorLocs.front();
+  else
+    SelLoc = Loc;
+
   if (LBracLoc.isInvalid()) {
     Diag(Loc, diag::err_missing_open_square_message_send)
       << FixItHint::CreateInsertion(Loc, "[");
@@ -2264,7 +2282,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
           Method = LookupMethodInQualifiedType(Sel, QClassTy, true);
           // warn if instance method found for a Class message.
           if (Method) {
-            Diag(Loc, diag::warn_instance_method_on_class_found)
+            Diag(SelLoc, diag::warn_instance_method_on_class_found)
               << Method->getSelector() << Sel;
             Diag(Method->getLocation(), diag::note_method_declared_at)
               << Method->getDeclName();
@@ -2279,7 +2297,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
             if (!Method)
               Method = ClassDecl->lookupPrivateClassMethod(Sel);
           }
-          if (Method && DiagnoseUseOfDecl(Method, Loc))
+          if (Method && DiagnoseUseOfDecl(Method, SelLoc))
             return ExprError();
         }
         if (!Method) {
@@ -2298,7 +2316,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
                   if (const ObjCInterfaceDecl *ID =
                       dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext())) {
                     if (ID->getSuperClass())
-                      Diag(Loc, diag::warn_root_inst_method_not_found)
+                      Diag(SelLoc, diag::warn_root_inst_method_not_found)
                       << Sel << SourceRange(LBracLoc, RBracLoc);
                   }
             }
@@ -2317,7 +2335,7 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
         Method = LookupMethodInQualifiedType(Sel, QIdTy, true);
         if (!Method)
           Method = LookupMethodInQualifiedType(Sel, QIdTy, false);
-        if (Method && DiagnoseUseOfDecl(Method, Loc))
+        if (Method && DiagnoseUseOfDecl(Method, SelLoc))
           return ExprError();
       } else if (const ObjCObjectPointerType *OCIType
                    = ReceiverType->getAsObjCInterfacePointerType()) {
@@ -2353,8 +2371,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
           Method = ClassDecl->lookupPrivateMethod(Sel);
 
           if (!Method && getLangOpts().ObjCAutoRefCount) {
-            Diag(Loc, diag::err_arc_may_not_respond)
-              << OCIType->getPointeeType() << Sel 
+            Diag(SelLoc, diag::err_arc_may_not_respond)
+              << OCIType->getPointeeType() << Sel << RecRange
               << SourceRange(SelectorLocs.front(), SelectorLocs.back());
             return ExprError();
           }
@@ -2367,12 +2385,13 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
               Method = LookupInstanceMethodInGlobalPool(Sel,
                                               SourceRange(LBracLoc, RBracLoc));
               if (Method && !forwardClass)
-                Diag(Loc, diag::warn_maynot_respond)
-                  << OCIType->getInterfaceDecl()->getIdentifier() << Sel;
+                Diag(SelLoc, diag::warn_maynot_respond)
+                  << OCIType->getInterfaceDecl()->getIdentifier()
+                  << Sel << RecRange;
             }
           }
         }
-        if (Method && DiagnoseUseOfDecl(Method, Loc, forwardClass))
+        if (Method && DiagnoseUseOfDecl(Method, SelLoc, forwardClass))
           return ExprError();
       } else {
         // Reject other random receiver types (e.g. structs).
@@ -2401,8 +2420,6 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
                           diag::err_illegal_message_expr_incomplete_type))
     return ExprError();
 
-  SourceLocation SelLoc = SelectorLocs.front();
-
   // In ARC, forbid the user from sending messages to 
   // retain/release/autorelease/dealloc/retainCount explicitly.
   if (getLangOpts().ObjCAutoRefCount) {
@@ -2427,8 +2444,8 @@ ExprResult Sema::BuildInstanceMessage(Expr *Receiver,
     case OMF_release:
     case OMF_autorelease:
     case OMF_retainCount:
-      Diag(Loc, diag::err_arc_illegal_explicit_message)
-        << Sel << SelLoc;
+      Diag(SelLoc, diag::err_arc_illegal_explicit_message)
+        << Sel << RecRange;
       break;
     
     case OMF_performSelector:
index d8073d04693176569d6c40cae9e39119cff62d7b..77bad96dcc3a8d7032be672b9aa43b3494481896 100644 (file)
@@ -43,13 +43,13 @@ void test1(A *a, struct UnsafeS *unsafeS) {
 // CHECK-NEXT: Number FIXITs = 0
 // CHECK-NEXT: {{.*}}check-with-serialized-diag.m:34:4: error: [rewriter] it is not safe to remove 'retain' message on a global variable
 // CHECK-NEXT: Number FIXITs = 0
-// CHECK-NEXT: {{.*}}check-with-serialized-diag.m:32:4: error: ARC forbids explicit message send of 'retain'
-// CHECK-NEXT: Range: {{.*}}check-with-serialized-diag.m:32:23 {{.*}}check-with-serialized-diag.m:32:29
+// CHECK-NEXT: {{.*}}check-with-serialized-diag.m:32:23: error: ARC forbids explicit message send of 'retain'
+// CHECK-NEXT: Range: {{.*}}check-with-serialized-diag.m:32:4 {{.*}}check-with-serialized-diag.m:32:22
 // CHECK-NEXT: Number FIXITs = 0
-// CHECK-NEXT: {{.*}}check-with-serialized-diag.m:34:4: error: ARC forbids explicit message send of 'retain'
-// CHECK-NEXT: Range: {{.*}}check-with-serialized-diag.m:34:15 {{.*}}check-with-serialized-diag.m:34:21
+// CHECK-NEXT: {{.*}}check-with-serialized-diag.m:34:15: error: ARC forbids explicit message send of 'retain'
+// CHECK-NEXT: Range: {{.*}}check-with-serialized-diag.m:34:4 {{.*}}check-with-serialized-diag.m:34:14
 // CHECK-NEXT: Number FIXITs = 0
-// CHECK-NEXT: {{.*}}check-with-serialized-diag.m:35:4: error: ARC forbids explicit message send of 'retainCount'
-// CHECK-NEXT: Range: {{.*}}check-with-serialized-diag.m:35:6 {{.*}}check-with-serialized-diag.m:35:17
+// CHECK-NEXT: {{.*}}check-with-serialized-diag.m:35:6: error: ARC forbids explicit message send of 'retainCount'
+// CHECK-NEXT: Range: {{.*}}check-with-serialized-diag.m:35:4 {{.*}}check-with-serialized-diag.m:35:5
 // CHECK-NEXT: Number FIXITs = 0
 
index 12efa93f07526d66c5e946c88599a8d41c6440c4..377dce30cafc8ba5bcb798c87a7866d566476600 100644 (file)
@@ -26,7 +26,7 @@ void test(id p) {
 // CHECK:   <key>location</key>
 // CHECK:   <dict>
 // CHECK:    <key>line</key><integer>10</integer>
-// CHECK:    <key>col</key><integer>4</integer>
+// CHECK:    <key>col</key><integer>6</integer>
 // CHECK:    <key>file</key><integer>0</integer>
 // CHECK:   </dict>
 // CHECK:    <key>ranges</key>
@@ -34,12 +34,12 @@ void test(id p) {
 // CHECK:     <array>
 // CHECK:      <dict>
 // CHECK:       <key>line</key><integer>10</integer>
-// CHECK:       <key>col</key><integer>6</integer>
+// CHECK:       <key>col</key><integer>4</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
 // CHECK:      <dict>
 // CHECK:       <key>line</key><integer>10</integer>
-// CHECK:       <key>col</key><integer>12</integer>
+// CHECK:       <key>col</key><integer>4</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
 // CHECK:     </array>
index f43bdf98852d23820294d1b31032f86fb322731e..40fa102f35d2a1bd77ad41b7a7df27d8edb7a9a7 100644 (file)
@@ -106,3 +106,15 @@ void foo5(id p) {
                  // expected-note {{to match this '['}} \
                  // expected-warning {{instance method '-bar' not found}}
 }
+
+@interface I1
+-(void)unavail_meth  __attribute__((unavailable)); // expected-note {{marked unavailable here}}
+@end
+
+// rdar://13620447
+void foo6(I1 *p) {
+  [p
+    bar]; // expected-warning {{instance method '-bar' not found}}
+  [p
+    unavail_meth]; // expected-error {{unavailable}}
+}
index 02b81651d7a21d0d9f8cdbdedaa90e251913b426..e9769a9db176d1c1e7987c3f12e666b99c050453 100644 (file)
@@ -54,5 +54,5 @@ __attribute__((objc_root_class))
 // CHECK-GC-ONLY: 1 warning generated.
 
 // RUN: %clang_cc1 -fsyntax-only -triple x86_64-apple-darwin10 -fobjc-arc %s 2>&1 | FileCheck --check-prefix=CHECK-ARC %s
-// CHECK-ARC: warn-missing-super.m:36:4: error: ARC forbids explicit message send of 'dealloc'
+// CHECK-ARC: warn-missing-super.m:36:10: error: ARC forbids explicit message send of 'dealloc'
 // CHECK-ARC: 1 error generated.