diff options
author | Douglas Gregor <dgregor@apple.com> | 2010-04-14 02:46:37 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2010-04-14 02:46:37 +0000 |
commit | 47bd54392a4fd0f10e04de6a0420fd4838caaa0e (patch) | |
tree | a70cfcbd611a1a518bc3bee7617695e13984cb96 /lib/Sema/SemaExprObjC.cpp | |
parent | 1dbca6ea983231b4cab1a8f1edda8f6e13c21f12 (diff) |
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".
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@101211 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaExprObjC.cpp')
-rw-r--r-- | lib/Sema/SemaExprObjC.cpp | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/lib/Sema/SemaExprObjC.cpp b/lib/Sema/SemaExprObjC.cpp index 26d115667c..cbb49114fe 100644 --- a/lib/Sema/SemaExprObjC.cpp +++ b/lib/Sema/SemaExprObjC.cpp @@ -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 |