forked from OSchip/llvm-project
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:
parent
5f40d34958
commit
8aa4ebf0bc
|
@ -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<
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}}
|
||||
|
|
Loading…
Reference in New Issue