From aec2ac67e7190bdb88abb1d427b82ae3284ea756 Mon Sep 17 00:00:00 2001 From: Kaelyn Uhrain Date: Thu, 26 Apr 2012 23:36:17 +0000 Subject: [PATCH] Add note to help explain why a tag such as 'struct' is needed to refer to a given type, when the reason is that there is a non-type decl with the same name. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155677 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticCommonKinds.td | 2 ++ lib/Parse/ParseDecl.cpp | 16 ++++++++++++++-- lib/Sema/SemaDecl.cpp | 8 ++++++++ test/FixIt/fixit.cpp | 2 +- test/Parser/cxx-using-declaration.cpp | 16 ++++++++++++++++ 5 files changed, 41 insertions(+), 3 deletions(-) diff --git a/include/clang/Basic/DiagnosticCommonKinds.td b/include/clang/Basic/DiagnosticCommonKinds.td index 103fc00b40..c1c933198d 100644 --- a/include/clang/Basic/DiagnosticCommonKinds.td +++ b/include/clang/Basic/DiagnosticCommonKinds.td @@ -74,6 +74,8 @@ def err_module_cycle : Error<"cyclic dependency in module '%0': %1">, def warn_module_build : Warning<"building module '%0' from source">, InGroup, DefaultIgnore; def note_pragma_entered_here : Note<"#pragma entered here">; +def note_decl_shadowing_tag_type : Note< + "non-type %0 shadowing %1 %0 declared here">; // Sema && Lex def ext_longlong : Extension< diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 4775798d62..134bc97a1b 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -14,6 +14,7 @@ #include "clang/Parse/Parser.h" #include "clang/Parse/ParseDiagnostic.h" #include "clang/Basic/OpenCL.h" +#include "clang/Sema/Lookup.h" #include "clang/Sema/Scope.h" #include "clang/Sema/ParsedTemplate.h" #include "clang/Sema/PrettyDeclStackTrace.h" @@ -1671,9 +1672,20 @@ bool Parser::ParseImplicitInt(DeclSpec &DS, CXXScopeSpec *SS, } if (TagName) { + IdentifierInfo *TokenName = Tok.getIdentifierInfo(); + LookupResult R(Actions, TokenName, SourceLocation(), + Sema::LookupOrdinaryName); + Diag(Loc, diag::err_use_of_tag_name_without_tag) - << Tok.getIdentifierInfo() << TagName << getLangOpts().CPlusPlus - << FixItHint::CreateInsertion(Tok.getLocation(),FixitTagName); + << TokenName << TagName << getLangOpts().CPlusPlus + << FixItHint::CreateInsertion(Tok.getLocation(), FixitTagName); + + if (Actions.LookupParsedName(R, getCurScope(), SS)) { + for (LookupResult::iterator I = R.begin(), IEnd = R.end(); + I != IEnd; ++I) + Diag((*I)->getLocation(), diag::note_decl_shadowing_tag_type) + << TokenName << TagName; + } // Parse this as a tag as if the missing tag were present. if (TagKind == tok::kw_enum) diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 38bb852fa2..ec950d1842 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -564,6 +564,14 @@ Corrected: Diag(NameLoc, diag::err_use_of_tag_name_without_tag) << Name << TagName << getLangOpts().CPlusPlus << FixItHint::CreateInsertion(NameLoc, FixItTagName); + + LookupResult R(*this, Name, NameLoc, LookupOrdinaryName); + if (LookupParsedName(R, S, &SS)) { + for (LookupResult::iterator I = R.begin(), IEnd = R.end(); + I != IEnd; ++I) + Diag((*I)->getLocation(), diag::note_decl_shadowing_tag_type) + << Name << TagName; + } break; } diff --git a/test/FixIt/fixit.cpp b/test/FixIt/fixit.cpp index e6609d8a6c..9a2acd33e0 100644 --- a/test/FixIt/fixit.cpp +++ b/test/FixIt/fixit.cpp @@ -211,7 +211,7 @@ class Foo { public: enum Bar { X, Y }; void SetBar(Bar bar); - Bar Bar(); + Bar Bar(); // expected-note 2 {{non-type 'Bar' shadowing enum 'Bar' declared here}} private: Bar bar_; // expected-error {{must use 'enum' tag to refer to type 'Bar' in this scope}} }; diff --git a/test/Parser/cxx-using-declaration.cpp b/test/Parser/cxx-using-declaration.cpp index 2b2a69d1a4..8c60b9b7a2 100644 --- a/test/Parser/cxx-using-declaration.cpp +++ b/test/Parser/cxx-using-declaration.cpp @@ -43,3 +43,19 @@ using F::X; // Should have some errors here. Waiting for implementation. void X(int); struct X *x; + + +namespace ShadowedTagNotes { + +namespace foo { + class Bar {}; +} + +void Bar(int); // expected-note{{non-type 'Bar' shadowing class 'Bar' declared here}} +using foo::Bar; + +void ambiguity() { + const Bar *x; // expected-error{{must use 'class' tag to refer to type 'Bar' in this scope}} +} + +} // namespace ShadowedTagNotes -- 2.40.0