[cfe-commits] r101211 - in /cfe/trunk: include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaExprObjC.cpp test/FixIt/typo.m

Douglas Gregor dgregor at apple.com
Tue Apr 13 19:46:38 PDT 2010


Author: dgregor
Date: Tue Apr 13 21:46:37 2010
New Revision: 101211

URL: http://llvm.org/viewvc/llvm-project?rev=101211&view=rev
Log:
Implement typo correction for Objective-C message sends when the
receiver is a mis-typed class name. Previously, we would give a non-specific
typo-correction diagnostic from the expression-parsing code, but there
was no fix-it because it was too late to recover. Now, we give a nice
diagnostic

honk.m:6:4: error: unknown receiver 'Hnk'; did you mean 'Honk'?
  [Hnk method];
   ^~~
   Honk
honk.m:1:1: note: 'Honk' declared here
@interface Honk
^

which includes a fix-it.

We still need to recover better from mis-typing "super".

Modified:
    cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
    cfe/trunk/lib/Sema/Sema.h
    cfe/trunk/lib/Sema/SemaExprObjC.cpp
    cfe/trunk/test/FixIt/typo.m

Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=101211&r1=101210&r2=101211&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Tue Apr 13 21:46:37 2010
@@ -2017,6 +2017,8 @@
   "receiver type %0 is not 'id' or interface pointer, consider "
   "casting it to 'id'">;
 def err_bad_receiver_type : Error<"bad receiver type %0">;
+def err_unknown_receiver_suggest : Error<
+  "unknown receiver %0; did you mean %1?">;
 def error_objc_throw_expects_object : Error<
   "@throw requires an Objective-C object type (%0 invalid)">;
 def error_objc_synchronized_expects_object : Error<

Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=101211&r1=101210&r2=101211&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Tue Apr 13 21:46:37 2010
@@ -3863,6 +3863,12 @@
                             SourceLocation receiverNameLoc,
                             SourceLocation propertyNameLoc);
 
+  virtual ObjCMessageKind getObjCMessageKind(Scope *S,
+                                             IdentifierInfo *&Name,
+                                             SourceLocation NameLoc,
+                                             bool IsSuper,
+                                             bool HasTrailingDot);
+
   // ActOnClassMessage - used for both unary and keyword messages.
   // ArgExprs is optional - if it is present, the number of expressions
   // is obtained from NumArgs.

Modified: cfe/trunk/lib/Sema/SemaExprObjC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprObjC.cpp?rev=101211&r1=101210&r2=101211&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExprObjC.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExprObjC.cpp Tue Apr 13 21:46:37 2010
@@ -486,6 +486,61 @@
                      << &propertyName << Context.getObjCInterfaceType(IFace));
 }
 
+Sema::ObjCMessageKind Sema::getObjCMessageKind(Scope *S,
+                                               IdentifierInfo *&Name,
+                                               SourceLocation NameLoc,
+                                               bool IsSuper,
+                                               bool HasTrailingDot) {
+  // If the identifier is "super" and there is no trailing dot, we're
+  // messaging super.
+  if (IsSuper && !HasTrailingDot && S->isInObjcMethodScope())
+    return ObjCSuperMessage;
+  
+  LookupResult Result(*this, Name, NameLoc, LookupOrdinaryName);
+  LookupName(Result, S);
+  
+  switch (Result.getResultKind()) {
+  case LookupResult::NotFound:
+    // Break out; we'll perform typo correction below.
+    break;
+
+  case LookupResult::NotFoundInCurrentInstantiation:
+  case LookupResult::FoundOverloaded:
+  case LookupResult::FoundUnresolvedValue:
+  case LookupResult::Ambiguous:
+    Result.suppressDiagnostics();
+    return ObjCInstanceMessage;
+
+  case LookupResult::Found: {
+    // We found something. If it's a type, then we have a class
+    // message. Otherwise, it's an instance message.
+    NamedDecl *ND = Result.getFoundDecl();
+    if (isa<ObjCInterfaceDecl>(ND) || isa<TypeDecl>(ND) || 
+        isa<UnresolvedUsingTypenameDecl>(ND))
+      return ObjCClassMessage;
+
+    return ObjCInstanceMessage;
+  }
+  }
+
+  if (CorrectTypo(Result, S, 0) && Result.isSingleResult()) {
+    NamedDecl *ND = Result.getFoundDecl();
+    if (isa<ObjCInterfaceDecl>(ND)) {
+      Diag(NameLoc, diag::err_unknown_receiver_suggest)
+        << Name << Result.getLookupName()
+        << FixItHint::CreateReplacement(SourceRange(NameLoc),
+                                        ND->getNameAsString());
+      Diag(ND->getLocation(), diag::note_previous_decl)
+        << ND->getDeclName();
+
+      Name = ND->getIdentifier();
+      return ObjCClassMessage;
+    }
+  }
+  
+  // Fall back: let the parser try to parse it as an instance message.
+  return ObjCInstanceMessage;
+}
 
 // ActOnClassMessage - used for both unary and keyword messages.
 // ArgExprs is optional - if it is present, the number of expressions

Modified: cfe/trunk/test/FixIt/typo.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/typo.m?rev=101211&r1=101210&r2=101211&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/typo.m (original)
+++ cfe/trunk/test/FixIt/typo.m Tue Apr 13 21:46:37 2010
@@ -2,7 +2,7 @@
 // FIXME: the test below isn't testing quite what we want...
 // RUN: %clang_cc1 -fsyntax-only -fixit -o - %s | %clang_cc1 -fsyntax-only -pedantic -Werror -x objective-c -
 
- at interface NSString
+ at interface NSString // expected-note{{'NSString' declared here}}
 + (int)method:(int)x;
 @end
 
@@ -57,8 +57,7 @@
 @end
 
 void test_message_send(B* b) {
-  // FIXME: Not providing fix-its
-  [NSstring method:17]; // expected-error{{use of undeclared identifier 'NSstring'; did you mean 'NSString'?}}
+  [NSstring method:17]; // expected-error{{unknown receiver 'NSstring'; did you mean 'NSString'?}}
 }
 
 @interface Collide // expected-note{{'Collide' declared here}}





More information about the cfe-commits mailing list