From: Douglas Gregor Date: Fri, 1 Jan 2010 00:15:04 +0000 (+0000) Subject: When typo correction for an id-expression finds a type (or Objective-C X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d203a162966cfc2157857f5fdfb0e30a4f669281;p=clang When typo correction for an id-expression finds a type (or Objective-C class), provide a suggestion for the type or class found. However, since we can't recover properly in this case, don't provide a fix-it hint. Example: test/FixIt/typo.m:8:3: error: use of undeclared identifier 'NSstring'; did you mean 'NSString'? NSstring *str = @"A string"; ... ^ 1 diagnostic generated. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92379 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 6bb6ea3e51..7bf04d88cd 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -931,21 +931,41 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, const CXXScopeSpec &SS, } // We didn't find anything, so try to correct for a typo. - if (S && CorrectTypo(R, S, &SS) && - (isa(*R.begin()) || isa(*R.begin()))) { - if (SS.isEmpty()) - Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName() - << CodeModificationHint::CreateReplacement(R.getNameLoc(), + if (S && CorrectTypo(R, S, &SS)) { + if (isa(*R.begin()) || isa(*R.begin())) { + if (SS.isEmpty()) + Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName() + << CodeModificationHint::CreateReplacement(R.getNameLoc(), R.getLookupName().getAsString()); - else - Diag(R.getNameLoc(), diag::err_no_member_suggest) - << Name << computeDeclContext(SS, false) << R.getLookupName() - << SS.getRange() - << CodeModificationHint::CreateReplacement(R.getNameLoc(), + else + Diag(R.getNameLoc(), diag::err_no_member_suggest) + << Name << computeDeclContext(SS, false) << R.getLookupName() + << SS.getRange() + << CodeModificationHint::CreateReplacement(R.getNameLoc(), R.getLookupName().getAsString()); - // Tell the callee to try to recover. - return false; + // Tell the callee to try to recover. + return false; + } + + if (isa(*R.begin()) || isa(*R.begin())) { + // FIXME: If we ended up with a typo for a type name or + // Objective-C class name, we're in trouble because the parser + // is in the wrong place to recover. Suggest the typo + // correction, but don't make it a fix-it since we're not going + // to recover well anyway. + if (SS.isEmpty()) + Diag(R.getNameLoc(), diagnostic_suggest) << Name << R.getLookupName(); + else + Diag(R.getNameLoc(), diag::err_no_member_suggest) + << Name << computeDeclContext(SS, false) << R.getLookupName() + << SS.getRange(); + + // Don't try to recover; it won't work. + return true; + } + + R.clear(); } // Emit a special diagnostic for failed member lookups. diff --git a/test/FixIt/typo.m b/test/FixIt/typo.m new file mode 100644 index 0000000000..251684949e --- /dev/null +++ b/test/FixIt/typo.m @@ -0,0 +1,9 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s +// RUN: %clang_cc1 -fsyntax-only -fixit -o - | %clang_cc1 -fsyntax-only -pedantic -Werror -x objective-c - + +@interface NSString +@end + +void test() { + NSstring *str = @"A string"; // expected-error{{use of undeclared identifier 'NSstring'; did you mean 'NSString'?}} +}