[cfe-commits] r92341 - in /cfe/trunk: include/clang/Basic/Diagnostic.h include/clang/Basic/DiagnosticSemaKinds.td lib/Sema/Sema.h lib/Sema/SemaExpr.cpp lib/Sema/SemaLookup.cpp lib/Sema/SemaOverload.cpp test/FixIt/typo.cpp test/Sema/var-redecl.c
Douglas Gregor
dgregor at apple.com
Wed Dec 30 21:20:15 PST 2009
Author: dgregor
Date: Wed Dec 30 23:20:13 2009
New Revision: 92341
URL: http://llvm.org/viewvc/llvm-project?rev=92341&view=rev
Log:
Implement typo correction for id-expressions, e.g.,
typo.cpp:22:10: error: use of undeclared identifier 'radious'; did
you mean 'radius'?
return radious * pi;
^~~~~~~
radius
This was super-easy, since we already had decent recovery by looking
for names in dependent base classes.
Modified:
cfe/trunk/include/clang/Basic/Diagnostic.h
cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
cfe/trunk/lib/Sema/Sema.h
cfe/trunk/lib/Sema/SemaExpr.cpp
cfe/trunk/lib/Sema/SemaLookup.cpp
cfe/trunk/lib/Sema/SemaOverload.cpp
cfe/trunk/test/FixIt/typo.cpp
cfe/trunk/test/Sema/var-redecl.c
Modified: cfe/trunk/include/clang/Basic/Diagnostic.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Diagnostic.h?rev=92341&r1=92340&r2=92341&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/Diagnostic.h (original)
+++ cfe/trunk/include/clang/Basic/Diagnostic.h Wed Dec 30 23:20:13 2009
@@ -45,7 +45,7 @@
DIAG_START_PARSE = DIAG_START_LEX + 300,
DIAG_START_AST = DIAG_START_PARSE + 300,
DIAG_START_SEMA = DIAG_START_AST + 100,
- DIAG_START_ANALYSIS = DIAG_START_SEMA + 1100,
+ DIAG_START_ANALYSIS = DIAG_START_SEMA + 1500,
DIAG_UPPER_LIMIT = DIAG_START_ANALYSIS + 100
};
Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=92341&r1=92340&r2=92341&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
+++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed Dec 30 23:20:13 2009
@@ -2552,6 +2552,11 @@
"unknown type name %0; did you mean %1?">;
def err_unknown_nested_typename_suggest : Error<
"no type named %0 in %1; did you mean %2?">;
+def err_no_member_suggest : Error<"no member named %0 in %1; did you mean %2?">;
+def err_undeclared_use_suggest : Error<
+ "use of undeclared %0; did you mean %1?">;
+def err_undeclared_var_use_suggest : Error<
+ "use of undeclared identifier %0; did you mean %1?">;
}
Modified: cfe/trunk/lib/Sema/Sema.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/Sema.h?rev=92341&r1=92340&r2=92341&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/Sema.h (original)
+++ cfe/trunk/lib/Sema/Sema.h Wed Dec 30 23:20:13 2009
@@ -1209,8 +1209,7 @@
VisibleDeclConsumer &Consumer);
bool CorrectTypo(LookupResult &R, Scope *S, const CXXScopeSpec *SS,
- bool AllowBuiltinCreation = false,
- bool EnteringContext = false);
+ bool EnteringContext = false);
void FindAssociatedClassesAndNamespaces(Expr **Args, unsigned NumArgs,
AssociatedNamespaceSet &AssociatedNamespaces,
@@ -1458,7 +1457,7 @@
bool HasTrailingLParen,
bool IsAddressOfOperand);
- bool DiagnoseEmptyLookup(const CXXScopeSpec &SS, LookupResult &R);
+ bool DiagnoseEmptyLookup(Scope *S, const CXXScopeSpec &SS, LookupResult &R);
OwningExprResult LookupInObjCMethod(LookupResult &R,
Scope *S,
Modified: cfe/trunk/lib/Sema/SemaExpr.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExpr.cpp?rev=92341&r1=92340&r2=92341&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaExpr.cpp (original)
+++ cfe/trunk/lib/Sema/SemaExpr.cpp Wed Dec 30 23:20:13 2009
@@ -879,28 +879,25 @@
/// Diagnose an empty lookup.
///
/// \return false if new lookup candidates were found
-bool Sema::DiagnoseEmptyLookup(const CXXScopeSpec &SS,
+bool Sema::DiagnoseEmptyLookup(Scope *S, const CXXScopeSpec &SS,
LookupResult &R) {
DeclarationName Name = R.getLookupName();
- // We don't know how to recover from bad qualified lookups.
- if (!SS.isEmpty()) {
- Diag(R.getNameLoc(), diag::err_no_member)
- << Name << computeDeclContext(SS, false)
- << SS.getRange();
- return true;
- }
-
unsigned diagnostic = diag::err_undeclared_var_use;
+ unsigned diagnostic_suggest = diag::err_undeclared_var_use_suggest;
if (Name.getNameKind() == DeclarationName::CXXOperatorName ||
Name.getNameKind() == DeclarationName::CXXLiteralOperatorName ||
- Name.getNameKind() == DeclarationName::CXXConversionFunctionName)
+ Name.getNameKind() == DeclarationName::CXXConversionFunctionName) {
diagnostic = diag::err_undeclared_use;
+ diagnostic_suggest = diag::err_undeclared_use_suggest;
+ }
- // Fake an unqualified lookup. This is useful when (for example)
- // the original lookup would not have found something because it was
- // a dependent name.
- for (DeclContext *DC = CurContext; DC; DC = DC->getParent()) {
+ // If the original lookup was an unqualified lookup, fake an
+ // unqualified lookup. This is useful when (for example) the
+ // original lookup would not have found something because it was a
+ // dependent name.
+ for (DeclContext *DC = SS.isEmpty()? CurContext : 0;
+ DC; DC = DC->getParent()) {
if (isa<CXXRecordDecl>(DC)) {
LookupQualifiedName(R, DC);
@@ -933,6 +930,33 @@
}
}
+ // We didn't find anything, so try to correct for a typo.
+ if (S && CorrectTypo(R, S, &SS) &&
+ (isa<ValueDecl>(*R.begin()) || isa<TemplateDecl>(*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(),
+ R.getLookupName().getAsString());
+
+ // Tell the callee to try to recover.
+ return false;
+ }
+
+ // Emit a special diagnostic for failed member lookups.
+ // FIXME: computing the declaration context might fail here (?)
+ if (!SS.isEmpty()) {
+ Diag(R.getNameLoc(), diag::err_no_member)
+ << Name << computeDeclContext(SS, false)
+ << SS.getRange();
+ return true;
+ }
+
// Give up, we can't recover.
Diag(R.getNameLoc(), diagnostic) << Name;
return true;
@@ -1010,7 +1034,7 @@
// If this name wasn't predeclared and if this is not a function
// call, diagnose the problem.
if (R.empty()) {
- if (DiagnoseEmptyLookup(SS, R))
+ if (DiagnoseEmptyLookup(S, SS, R))
return ExprError();
assert(!R.empty() &&
Modified: cfe/trunk/lib/Sema/SemaLookup.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=92341&r1=92340&r2=92341&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaLookup.cpp (original)
+++ cfe/trunk/lib/Sema/SemaLookup.cpp Wed Dec 30 23:20:13 2009
@@ -2134,11 +2134,14 @@
/// \param SS the nested-name-specifier that precedes the name we're
/// looking for, if present.
///
+/// \param EnteringContext whether we're entering the context described by
+/// the nested-name-specifier SS.
+///
/// \returns true if the typo was corrected, in which case the \p Res
/// structure will contain the results of name lookup for the
/// corrected name. Otherwise, returns false.
bool Sema::CorrectTypo(LookupResult &Res, Scope *S, const CXXScopeSpec *SS,
- bool AllowBuiltinCreation, bool EnteringContext) {
+ bool EnteringContext) {
// We only attempt to correct typos for identifiers.
IdentifierInfo *Typo = Res.getLookupName().getAsIdentifierInfo();
if (!Typo)
@@ -2190,6 +2193,12 @@
// success if we found something that was not ambiguous.
Res.clear();
Res.setLookupName(BestName);
- LookupParsedName(Res, S, SS, AllowBuiltinCreation, EnteringContext);
- return Res.getResultKind() != LookupResult::NotFound && !Res.isAmbiguous();
+ LookupParsedName(Res, S, SS, /*AllowBuiltinCreation=*/false, EnteringContext);
+
+ if (Res.isAmbiguous()) {
+ Res.suppressDiagnostics();
+ return false;
+ }
+
+ return Res.getResultKind() != LookupResult::NotFound;
}
Modified: cfe/trunk/lib/Sema/SemaOverload.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaOverload.cpp?rev=92341&r1=92340&r2=92341&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaOverload.cpp (original)
+++ cfe/trunk/lib/Sema/SemaOverload.cpp Wed Dec 30 23:20:13 2009
@@ -4822,7 +4822,7 @@
LookupResult R(SemaRef, ULE->getName(), ULE->getNameLoc(),
Sema::LookupOrdinaryName);
- if (SemaRef.DiagnoseEmptyLookup(SS, R))
+ if (SemaRef.DiagnoseEmptyLookup(/*Scope=*/0, SS, R))
return Destroy(SemaRef, Fn, Args, NumArgs);
assert(!R.empty() && "lookup results empty despite recovery");
Modified: cfe/trunk/test/FixIt/typo.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/FixIt/typo.cpp?rev=92341&r1=92340&r2=92341&view=diff
==============================================================================
--- cfe/trunk/test/FixIt/typo.cpp (original)
+++ cfe/trunk/test/FixIt/typo.cpp Wed Dec 30 23:20:13 2009
@@ -1,7 +1,11 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
// RUN: %clang_cc1 -fsyntax-only -fixit -o - | %clang_cc1 -fsyntax-only -pedantic -Werror -x c++ -
namespace std {
- template<typename T> class basic_string { };
+ template<typename T> class basic_string {
+ int find(const char *substr);
+ static const int npos = -1;
+ };
+
typedef basic_string<char> string;
}
@@ -13,3 +17,11 @@
otherstd::strng str1; // expected-error{{no type named 'strng' in namespace 'otherstd'; did you mean 'string'?}}
tring str2; // expected-error{{unknown type name 'tring'; did you mean 'string'?}}
+
+float area(float radius, float pi) {
+ return radious * pi; // expected-error{{use of undeclared identifier 'radious'; did you mean 'radius'?}}
+}
+
+bool test_string(std::string s) {
+ return s.find("hello") == std::string::pos; // expected-error{{no member named 'pos' in 'class std::basic_string<char>'; did you mean 'npos'?}}
+}
Modified: cfe/trunk/test/Sema/var-redecl.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/var-redecl.c?rev=92341&r1=92340&r2=92341&view=diff
==============================================================================
--- cfe/trunk/test/Sema/var-redecl.c (original)
+++ cfe/trunk/test/Sema/var-redecl.c Wed Dec 30 23:20:13 2009
@@ -53,7 +53,8 @@
void g18(void) {
extern int g19;
}
-int *p=&g19; // expected-error{{use of undeclared identifier 'g19'}}
+int *p=&g19; // expected-error{{use of undeclared identifier 'g19'}} \
+ // expected-warning{{incompatible pointer types}}
// PR3645
static int a;
More information about the cfe-commits
mailing list