aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaelyn Uhrain <rikka@google.com>2012-04-26 23:36:17 +0000
committerKaelyn Uhrain <rikka@google.com>2012-04-26 23:36:17 +0000
commitaec2ac67e7190bdb88abb1d427b82ae3284ea756 (patch)
treed835e2740d0381136393c75b45ebb3c8fab28ce1
parent65a7c685b78c18dc158399d2cc688a611d5e2553 (diff)
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
-rw-r--r--include/clang/Basic/DiagnosticCommonKinds.td2
-rw-r--r--lib/Parse/ParseDecl.cpp16
-rw-r--r--lib/Sema/SemaDecl.cpp8
-rw-r--r--test/FixIt/fixit.cpp2
-rw-r--r--test/Parser/cxx-using-declaration.cpp16
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<ModuleBuild>, 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