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".

llvm-svn: 101211
This commit is contained in:
Douglas Gregor 2010-04-14 02:46:37 +00:00
parent 5f40d34958
commit 8aa4ebf0bc
4 changed files with 65 additions and 3 deletions

View File

@ -2017,6 +2017,8 @@ def warn_bad_receiver_type : Warning<
"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<

View File

@ -3863,6 +3863,12 @@ public:
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.

View File

@ -486,6 +486,61 @@ ActOnClassPropertyRefExpr(IdentifierInfo &receiverName,
<< &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

View File

@ -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 -
@interface NSString
@interface NSString // expected-note{{'NSString' declared here}}
+ (int)method:(int)x;
@end
@ -57,8 +57,7 @@ void test() {
@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}}