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<T>'

llvm-svn: 100060
This commit is contained in:
Douglas Gregor 2010-03-31 23:17:41 +00:00
parent 7f89a0ac88
commit f5af3584ca
8 changed files with 15 additions and 13 deletions

View File

@ -2182,7 +2182,7 @@ def err_invalid_declarator_global_scope : Error<
def err_invalid_declarator_in_function : Error< def err_invalid_declarator_in_function : Error<
"definition or redeclaration of %0 not allowed inside a function">; "definition or redeclaration of %0 not allowed inside a function">;
def err_not_tag_in_scope : Error< 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< def err_cannot_form_pointer_to_member_of_reference_type : Error<
"cannot form a pointer-to-member to member %0 of reference type %1">; "cannot form a pointer-to-member to member %0 of reference type %1">;

View File

@ -4786,7 +4786,8 @@ Sema::DeclPtrTy Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK,
} }
// A tag 'foo::bar' must already exist. // 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; Name = 0;
Invalid = true; Invalid = true;
goto CreateNewDecl; goto CreateNewDecl;

View File

@ -693,7 +693,8 @@ Decl *TemplateDeclInstantiator::VisitClassTemplateDecl(ClassTemplateDecl *D) {
if (!PrevClassTemplate && Qualifier) { if (!PrevClassTemplate && Qualifier) {
SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope) SemaRef.Diag(Pattern->getLocation(), diag::err_not_tag_in_scope)
<< Pattern->getDeclName() << Pattern->getQualifierRange(); << D->getTemplatedDecl()->getTagKind() << Pattern->getDeclName() << DC
<< Pattern->getQualifierRange();
return 0; return 0;
} }

View File

@ -618,9 +618,9 @@ public:
} }
if (!Tag) { 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) SemaRef.Diag(SR.getEnd(), diag::err_not_tag_in_scope)
<< Id << SR; << Kind << Id << DC;
return QualType(); return QualType();
} }

View File

@ -40,10 +40,10 @@ void c2(class B<float>::Member);
void c3(union B<float>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}} void c3(union B<float>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}}
void c4(enum B<float>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}} void c4(enum B<float>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}}
void d1(struct B<int>::Member); // expected-error {{'Member' does not name a tag member in the specified scope}} void d1(struct B<int>::Member); // expected-error {{no struct named 'Member' in 'B<int>'}}
void d2(class B<int>::Member); // expected-error {{'Member' does not name a tag member in the specified scope}} void d2(class B<int>::Member); // expected-error {{no class named 'Member' in 'B<int>'}}
void d3(union B<int>::Member); // expected-error {{'Member' does not name a tag member in the specified scope}} void d3(union B<int>::Member); // expected-error {{no union named 'Member' in 'B<int>'}}
void d4(enum B<int>::Member); // expected-error {{'Member' does not name a tag member in the specified scope}} void d4(enum B<int>::Member); // expected-error {{no enum named 'Member' in 'B<int>'}}
void e1(struct B<A>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}} void e1(struct B<A>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}}
void e2(class B<A>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}} void e2(class B<A>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}}
@ -51,7 +51,7 @@ void e3(union B<A>::Member);
void e4(enum B<A>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}} void e4(enum B<A>::Member); // expected-error {{use of 'Member' with tag type that does not match previous declaration}}
template <class T> struct C { template <class T> struct C {
void foo(class B<T>::Member); // expected-error{{'Member' does not name a tag member in the specified scope}} \ void foo(class B<T>::Member); // expected-error{{no class named 'Member' in 'B<int>'}} \
// expected-error{{use of 'Member' with tag type that does not match previous declaration}} // expected-error{{use of 'Member' with tag type that does not match previous declaration}}
}; };

View File

@ -64,7 +64,7 @@ void f2() {
A::C c1; A::C c1;
struct A::C c2; struct A::C c2;
struct S : public A::C {}; 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 { namespace A2 {
typedef int INT; typedef int INT;

View File

@ -55,7 +55,7 @@ namespace PR6031 {
template<typename T> template<typename T>
struct NoDepBase { struct NoDepBase {
int foo() { 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<T>'}}
typedef typename NoDepBase::template MemberTemplate<T>::type type; // expected-error{{'MemberTemplate' following the 'template' keyword does not refer to a template}} \ typedef typename NoDepBase::template MemberTemplate<T>::type type; // expected-error{{'MemberTemplate' following the 'template' keyword does not refer to a template}} \
// FIXME: expected-error{{unqualified-id}} // FIXME: expected-error{{unqualified-id}}
return NoDepBase::a; // expected-error{{no member named 'a' in 'NoDepBase<T>'}} return NoDepBase::a; // expected-error{{no member named 'a' in 'NoDepBase<T>'}}

View File

@ -36,7 +36,7 @@ namespace N {
typedef int INT; typedef int INT;
template struct N::Outer::Inner::InnerTemplate<INT>::VeryInner; template struct N::Outer::Inner::InnerTemplate<INT>::VeryInner;
template struct N::Outer::Inner::InnerTemplate<INT>::UeberInner; // expected-error{{'UeberInner' does not name a tag member}} template struct N::Outer::Inner::InnerTemplate<INT>::UeberInner; // expected-error{{no struct named 'UeberInner' in 'N::Outer::Inner::InnerTemplate<int>'}}
namespace N2 { namespace N2 {
struct Outer2 { struct Outer2 {