From f5af3584cab155ba4da7957a018098b3765b4641 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Wed, 31 Mar 2010 23:17:41 +0000 Subject: [PATCH] Improve diagnostics when an elaborated-type-specifer containing a nested-name-specifier (e.g., "class T::foo") fails to find a tag member in the scope nominated by the nested-name-specifier. Previously, we gave a bland error: 'Nested' does not name a tag member in the specified scope which didn't actually say where we were looking, which was rather horrible when the nested-name-specifier was instantiated. Now, we give something a bit better: error: no class named 'Nested' in 'NoDepBase' llvm-svn: 100060 --- clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/lib/Sema/SemaDecl.cpp | 3 ++- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp | 3 ++- clang/lib/Sema/TreeTransform.h | 4 ++-- .../CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp | 10 +++++----- clang/test/SemaCXX/nested-name-spec.cpp | 2 +- clang/test/SemaTemplate/dependent-base-classes.cpp | 2 +- clang/test/SemaTemplate/instantiate-declref.cpp | 2 +- 8 files changed, 15 insertions(+), 13 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 24391649d13b..4e177fbb1813 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -2182,7 +2182,7 @@ def err_invalid_declarator_global_scope : Error< def err_invalid_declarator_in_function : Error< "definition or redeclaration of %0 not allowed inside a function">; def err_not_tag_in_scope : Error< - "%0 does not name a tag member in the specified scope">; + "no %select{struct|union|class|enum}0 named %1 in %2">; def err_cannot_form_pointer_to_member_of_reference_type : Error< "cannot form a pointer-to-member to member %0 of reference type %1">; diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index eef73d8d7f5b..f3d0dcff20c7 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -4786,7 +4786,8 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, } // A tag 'foo::bar' must already exist. - Diag(NameLoc, diag::err_not_tag_in_scope) << Name << SS.getRange(); + Diag(NameLoc, diag::err_not_tag_in_scope) + << Kind << Name << DC << SS.getRange(); Name = 0; Invalid = true; goto CreateNewDecl; diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 9777569b3187..3375ccc0ebcd 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -693,7 +693,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) { if (!PrevClassTemplate && Qualifier) { SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope) - << Pattern->getDeclName() << Pattern->getQualifierRange(); + << D->getTemplatedDecl()->getTagKind() << Pattern->getDeclName() << DC + << Pattern->getQualifierRange(); return 0; } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index b08447e4805f..f9ffd3f41aa5 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -618,9 +618,9 @@ public: } if (!Tag) { - // FIXME: Crummy diagnostic + // FIXME: Would be nice to highlight just the source range. SemaRef.Diag(SR.getEnd(), diag::err_not_tag_in_scope) - << Id << SR; + << Kind << Id << DC; return QualType(); } diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp index bfb4780cde8e..c53031177323 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p3.cpp @@ -40,10 +40,10 @@ void c2(class B::Member); void c3(union B::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}} void c4(enum B::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}} -void d1(struct B::Member); // expected-error {{'Member' does not name a tag member in the specified scope}} -void d2(class B::Member); // expected-error {{'Member' does not name a tag member in the specified scope}} -void d3(union B::Member); // expected-error {{'Member' does not name a tag member in the specified scope}} -void d4(enum B::Member); // expected-error {{'Member' does not name a tag member in the specified scope}} +void d1(struct B::Member); // expected-error {{no struct named 'Member' in 'B'}} +void d2(class B::Member); // expected-error {{no class named 'Member' in 'B'}} +void d3(union B::Member); // expected-error {{no union named 'Member' in 'B'}} +void d4(enum B::Member); // expected-error {{no enum named 'Member' in 'B'}} void e1(struct B::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}} void e2(class B::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}} @@ -51,7 +51,7 @@ void e3(union B::Member); void e4(enum B::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}} template struct C { - void foo(class B::Member); // expected-error{{'Member' does not name a tag member in the specified scope}} \ + void foo(class B::Member); // expected-error{{no class named 'Member' in 'B'}} \ // expected-error{{use of 'Member' with tag type that does not match previous declaration}} }; diff --git a/clang/test/SemaCXX/nested-name-spec.cpp b/clang/test/SemaCXX/nested-name-spec.cpp index 8657c0dca0ae..9a611c38ad6d 100644 --- a/clang/test/SemaCXX/nested-name-spec.cpp +++ b/clang/test/SemaCXX/nested-name-spec.cpp @@ -64,7 +64,7 @@ void f2() { A::C c1; struct A::C c2; struct S : public A::C {}; -struct A::undef; // expected-error {{'undef' does not name a tag member in the specified scope}} +struct A::undef; // expected-error {{no struct named 'undef' in namespace 'A'}} namespace A2 { typedef int INT; diff --git a/clang/test/SemaTemplate/dependent-base-classes.cpp b/clang/test/SemaTemplate/dependent-base-classes.cpp index 600115b56530..d0dd9c98fa71 100644 --- a/clang/test/SemaTemplate/dependent-base-classes.cpp +++ b/clang/test/SemaTemplate/dependent-base-classes.cpp @@ -55,7 +55,7 @@ namespace PR6031 { template struct NoDepBase { int foo() { - class NoDepBase::Nested nested; // expected-error{{'Nested' does not name a tag member in the specified scope}} + class NoDepBase::Nested nested; // expected-error{{no class named 'Nested' in 'NoDepBase'}} typedef typename NoDepBase::template MemberTemplate::type type; // expected-error{{'MemberTemplate' following the 'template' keyword does not refer to a template}} \ // FIXME: expected-error{{unqualified-id}} return NoDepBase::a; // expected-error{{no member named 'a' in 'NoDepBase'}} diff --git a/clang/test/SemaTemplate/instantiate-declref.cpp b/clang/test/SemaTemplate/instantiate-declref.cpp index f883b9361b66..2d27075bd41f 100644 --- a/clang/test/SemaTemplate/instantiate-declref.cpp +++ b/clang/test/SemaTemplate/instantiate-declref.cpp @@ -36,7 +36,7 @@ namespace N { typedef int INT; template struct N::Outer::Inner::InnerTemplate::VeryInner; -template struct N::Outer::Inner::InnerTemplate::UeberInner; // expected-error{{'UeberInner' does not name a tag member}} +template struct N::Outer::Inner::InnerTemplate::UeberInner; // expected-error{{no struct named 'UeberInner' in 'N::Outer::Inner::InnerTemplate'}} namespace N2 { struct Outer2 {