From: Douglas Gregor Date: Thu, 7 Jan 2010 00:17:44 +0000 (+0000) Subject: Whenever we emit a typo-correction diagnostic, also emit a note X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=67dd1d4df1b28973e12e0981129b2517d2033b66;p=clang Whenever we emit a typo-correction diagnostic, also emit a note pointing to the declaration that we found that has that name (if it is unique). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@92877 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaCXXScopeSpec.cpp b/lib/Sema/SemaCXXScopeSpec.cpp index 82d58eab1a..a8f118ebdd 100644 --- a/lib/Sema/SemaCXXScopeSpec.cpp +++ b/lib/Sema/SemaCXXScopeSpec.cpp @@ -446,6 +446,10 @@ Sema::CXXScopeTy *Sema::BuildCXXNestedNameSpecifier(Scope *S, << Name << Found.getLookupName() << CodeModificationHint::CreateReplacement(Found.getNameLoc(), Found.getLookupName().getAsString()); + + if (NamedDecl *ND = Found.getAsSingle()) + Diag(ND->getLocation(), diag::note_previous_decl) + << ND->getDeclName(); } else Found.clear(); } diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 9ed37f604f..69e9ff9e9c 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -281,6 +281,9 @@ bool Sema::DiagnoseUnknownTypeName(const IdentifierInfo &II, else llvm_unreachable("could not have corrected a typo here"); + Diag(Result->getLocation(), diag::note_previous_decl) + << Result->getDeclName(); + SuggestedType = getTypeName(*Result->getIdentifier(), IILoc, S, SS); return true; } @@ -580,6 +583,9 @@ ObjCInterfaceDecl *Sema::getObjCInterfaceDecl(IdentifierInfo *&Id, << Id << IDecl->getDeclName() << CodeModificationHint::CreateReplacement(RecoverLoc, IDecl->getNameAsString()); + Diag(IDecl->getLocation(), diag::note_previous_decl) + << IDecl->getDeclName(); + Id = IDecl->getIdentifier(); } } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 2e6f8bc687..7ae0440b40 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1072,6 +1072,8 @@ Sema::ActOnMemInitializer(DeclPtrTy ConstructorD, << MemberOrBase << true << R.getLookupName() << CodeModificationHint::CreateReplacement(R.getNameLoc(), R.getLookupName().getAsString()); + Diag(Member->getLocation(), diag::note_previous_decl) + << Member->getDeclName(); return BuildMemberInitializer(Member, (Expr**)Args, NumArgs, IdLoc, LParenLoc, RParenLoc); diff --git a/lib/Sema/SemaDeclObjC.cpp b/lib/Sema/SemaDeclObjC.cpp index e5526746d9..179255aedf 100644 --- a/lib/Sema/SemaDeclObjC.cpp +++ b/lib/Sema/SemaDeclObjC.cpp @@ -142,6 +142,8 @@ ActOnStartClassInterface(SourceLocation AtInterfaceLoc, (PrevDecl = R.getAsSingle())) { Diag(SuperLoc, diag::err_undef_superclass_suggest) << SuperName << ClassName << PrevDecl->getDeclName(); + Diag(PrevDecl->getLocation(), diag::note_previous_decl) + << PrevDecl->getDeclName(); } } @@ -335,6 +337,8 @@ Sema::FindProtocolDeclaration(bool WarnOnDeclarations, (PDecl = R.getAsSingle())) { Diag(ProtocolId[i].second, diag::err_undeclared_protocol_suggest) << ProtocolId[i].first << R.getLookupName(); + Diag(PDecl->getLocation(), diag::note_previous_decl) + << PDecl->getDeclName(); } } diff --git a/lib/Sema/SemaExpr.cpp b/lib/Sema/SemaExpr.cpp index 3d2ee74278..730375e5cd 100644 --- a/lib/Sema/SemaExpr.cpp +++ b/lib/Sema/SemaExpr.cpp @@ -943,7 +943,10 @@ bool Sema::DiagnoseEmptyLookup(Scope *S, const CXXScopeSpec &SS, << SS.getRange() << CodeModificationHint::CreateReplacement(R.getNameLoc(), R.getLookupName().getAsString()); - + if (NamedDecl *ND = R.getAsSingle()) + Diag(ND->getLocation(), diag::note_previous_decl) + << ND->getDeclName(); + // Tell the callee to try to recover. return false; } @@ -2400,6 +2403,9 @@ LookupMemberExprInRecord(Sema &SemaRef, LookupResult &R, << Name << DC << R.getLookupName() << SS.getRange() << CodeModificationHint::CreateReplacement(R.getNameLoc(), R.getLookupName().getAsString()); + if (NamedDecl *ND = R.getAsSingle()) + SemaRef.Diag(ND->getLocation(), diag::note_previous_decl) + << ND->getDeclName(); return false; } else { R.clear(); @@ -2881,6 +2887,8 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, << IDecl->getDeclName() << MemberName << IV->getDeclName() << CodeModificationHint::CreateReplacement(R.getNameLoc(), IV->getNameAsString()); + Diag(IV->getLocation(), diag::note_previous_decl) + << IV->getDeclName(); } } @@ -3060,6 +3068,10 @@ Sema::LookupMemberExpr(LookupResult &R, Expr *&BaseExpr, << MemberName << BaseType << Res.getLookupName() << CodeModificationHint::CreateReplacement(R.getNameLoc(), Res.getLookupName().getAsString()); + ObjCPropertyDecl *Property = Res.getAsSingle(); + Diag(Property->getLocation(), diag::note_previous_decl) + << Property->getDeclName(); + return LookupMemberExpr(Res, BaseExpr, IsArrow, OpLoc, SS, FirstQualifierInScope, ObjCImpDecl); } diff --git a/lib/Sema/SemaInit.cpp b/lib/Sema/SemaInit.cpp index 54d94f86ce..c2a62cbc52 100644 --- a/lib/Sema/SemaInit.cpp +++ b/lib/Sema/SemaInit.cpp @@ -1302,6 +1302,9 @@ InitListChecker::CheckDesignatedInitializer(InitListExpr *IList, << FieldName << CurrentObjectType << R.getLookupName() << CodeModificationHint::CreateReplacement(D->getFieldLoc(), R.getLookupName().getAsString()); + SemaRef.Diag(ReplacementField->getLocation(), + diag::note_previous_decl) + << ReplacementField->getDeclName(); } else { SemaRef.Diag(D->getFieldLoc(), diag::err_field_designator_unknown) << FieldName << CurrentObjectType; diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp index 8c6aa6a7d4..ecb89edcf7 100644 --- a/lib/Sema/SemaTemplate.cpp +++ b/lib/Sema/SemaTemplate.cpp @@ -219,6 +219,9 @@ void Sema::LookupTemplateName(LookupResult &Found, << Name << Found.getLookupName() << CodeModificationHint::CreateReplacement(Found.getNameLoc(), Found.getLookupName().getAsString()); + if (TemplateDecl *Template = Found.getAsSingle()) + Diag(Template->getLocation(), diag::note_previous_decl) + << Template->getDeclName(); } else Found.clear(); } else { diff --git a/test/FixIt/typo.c b/test/FixIt/typo.c index d36e769ed0..72e3d658e7 100644 --- a/test/FixIt/typo.c +++ b/test/FixIt/typo.c @@ -5,13 +5,14 @@ struct Point { }; struct Rectangle { - struct Point top_left, bottom_right; + struct Point top_left, // expected-note{{'top_left' declared here}} + bottom_right; }; enum Color { Red, Green, Blue }; struct Window { - struct Rectangle bounds; + struct Rectangle bounds; // expected-note{{'bounds' declared here}} enum Color color; }; diff --git a/test/FixIt/typo.cpp b/test/FixIt/typo.cpp index 041b86a7f2..ffeb18dde1 100644 --- a/test/FixIt/typo.cpp +++ b/test/FixIt/typo.cpp @@ -1,15 +1,15 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s // RUN: %clang_cc1 -fsyntax-only -fixit -o - %s | %clang_cc1 -fsyntax-only -pedantic -Werror -x c++ - namespace std { - template class basic_string { - int find(const char *substr); - static const int npos = -1; + template class basic_string { // expected-note 2{{'basic_string' declared here}} + int find(const char *substr); // expected-note{{'find' declared here}} + static const int npos = -1; // expected-note{{'npos' declared here}} }; - typedef basic_string string; + typedef basic_string string; // expected-note 2{{'string' declared here}} } -namespace otherstd { +namespace otherstd { // expected-note 2{{'otherstd' declared here}} using namespace std; } @@ -36,7 +36,7 @@ bool test_string(std::string s) { struct Base { }; struct Derived : public Base { - int member; + int member; // expected-note 3{{'member' declared here}} Derived() : base(), // expected-error{{initializer 'base' does not name a non-static data member or base class; did you mean the base class 'Base'?}} ember() { } // expected-error{{initializer 'ember' does not name a non-static data member or base class; did you mean the member 'member'?}} diff --git a/test/FixIt/typo.m b/test/FixIt/typo.m index cff5dd84ea..4c3ee5f60b 100644 --- a/test/FixIt/typo.m +++ b/test/FixIt/typo.m @@ -12,24 +12,24 @@ void test() { } @protocol P1 -@property int *sprop; +@property int *sprop; // expected-note{{'sprop' declared here}} @end @interface A { - int his_ivar; + int his_ivar; // expected-note 2{{'his_ivar' declared here}} float wibble; } -@property int his_prop; +@property int his_prop; // expected-note{{'his_prop' declared here}} @end @interface B : A { - int her_ivar; + int her_ivar; // expected-note 2{{'her_ivar' declared here}} } -@property int her_prop; +@property int her_prop; // expected-note{{'her_prop' declared here}} - (void)inst_method1:(int)a; + (void)class_method1; @end @@ -60,13 +60,13 @@ void test_message_send(B* b) { [NSstring method:17]; // expected-error{{use of undeclared identifier 'NSstring'; did you mean 'NSString'?}} } -@interface Collide +@interface Collide // expected-note{{'Collide' declared here}} { @public - int value; + int value; // expected-note{{'value' declared here}} } -@property int value; +@property int value; // expected-note{{'value' declared here}} @end @implementation Collide @@ -81,7 +81,7 @@ void test2(Collide *a) { @interface Derived : Collid // expected-error{{cannot find interface declaration for 'Collid', superclass of 'Derived'; did you mean 'Collide'?}} @end -@protocol NetworkSocket +@protocol NetworkSocket // expected-note{{'NetworkSocket' declared here}} - (int)send:(void*)buffer bytes:(int)bytes; @end diff --git a/test/Sema/var-redecl.c b/test/Sema/var-redecl.c index e67499bcc4..71d7ea1bae 100644 --- a/test/Sema/var-redecl.c +++ b/test/Sema/var-redecl.c @@ -50,7 +50,7 @@ void outer_shadowing_test() { } } -void g18(void) { +void g18(void) { // expected-note{{'g18' declared here}} extern int g19; } int *p=&g19; // expected-error{{use of undeclared identifier 'g19'}} \ diff --git a/test/SemaObjC/undef-class-messagin-error.m b/test/SemaObjC/undef-class-messagin-error.m index 2a6d240840..63e0b9dec3 100644 --- a/test/SemaObjC/undef-class-messagin-error.m +++ b/test/SemaObjC/undef-class-messagin-error.m @@ -1,6 +1,6 @@ // RUN: %clang_cc1 -fsyntax-only -verify %s -@interface _Child +@interface _Child // expected-note{{'_Child' declared here}} + (int) flashCache; @end