diff options
-rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 11 | ||||
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 7 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 22 | ||||
-rw-r--r-- | clang/lib/Sema/SemaTemplate.cpp | 7 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 8 | ||||
-rw-r--r-- | clang/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp | 4 | ||||
-rw-r--r-- | clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp | 6 | ||||
-rw-r--r-- | clang/test/CXX/drs/dr2xx.cpp | 6 | ||||
-rw-r--r-- | clang/test/CXX/drs/dr4xx.cpp | 2 | ||||
-rw-r--r-- | clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp | 2 | ||||
-rw-r--r-- | clang/test/CXX/temp/temp.spec/no-body.cpp | 2 | ||||
-rw-r--r-- | clang/test/SemaCXX/PR8755.cpp | 2 | ||||
-rw-r--r-- | clang/test/SemaCXX/using-decl-templates.cpp | 2 | ||||
-rw-r--r-- | clang/test/SemaTemplate/template-id-expr.cpp | 2 |
14 files changed, 53 insertions, 30 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 85f600db92e..90175dcb57b 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -4564,10 +4564,15 @@ def err_redefinition_different_typedef : Error< "%select{typedef|type alias|type alias template}0 " "redefinition with different types%diff{ ($ vs $)|}1,2">; def err_tag_reference_non_tag : Error< - "elaborated type refers to %select{a non-tag type|a typedef|a type alias|a template|a type alias template|a template template argument}0">; + "%select{non-struct type|non-class type|non-union type|non-enum " + "type|typedef|type alias|template|type alias template|template " + "template argument}1 %0 cannot be referenced with a " + "%select{struct|interface|union|class|enum}2 specifier">; def err_tag_reference_conflict : Error< - "implicit declaration introduced by elaborated type conflicts with " - "%select{a declaration|a typedef|a type alias|a template}0 of the same name">; + "implicit declaration introduced by elaborated type conflicts with a " + "%select{non-struct type|non-class type|non-union type|non-enum " + "type|typedef|type alias|template|type alias template|template " + "template argument}0 of the same name">; def err_dependent_tag_decl : Error< "%select{declaration|definition}0 of " "%select{struct|interface|union|class|enum}1 in a dependent scope">; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 0dfb0d922cf..b08c698d0b8 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -1976,7 +1976,10 @@ public: /// Common ways to introduce type names without a tag for use in diagnostics. /// Keep in sync with err_tag_reference_non_tag. enum NonTagKind { - NTK_Unknown, + NTK_NonStruct, + NTK_NonClass, + NTK_NonUnion, + NTK_NonEnum, NTK_Typedef, NTK_TypeAlias, NTK_Template, @@ -1986,7 +1989,7 @@ public: /// Given a non-tag type declaration, returns an enum useful for indicating /// what kind of non-tag type this is. - NonTagKind getNonTagTypeDeclKind(const Decl *D); + NonTagKind getNonTagTypeDeclKind(const Decl *D, TagTypeKind TTK); bool isAcceptableTagRedeclaration(const TagDecl *Previous, TagTypeKind NewTag, bool isDefinition, diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 9e764e3f5a7..f8d4dbe1ebe 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -12430,7 +12430,8 @@ static bool isClassCompatTagKind(TagTypeKind Tag) return Tag == TTK_Struct || Tag == TTK_Class || Tag == TTK_Interface; } -Sema::NonTagKind Sema::getNonTagTypeDeclKind(const Decl *PrevDecl) { +Sema::NonTagKind Sema::getNonTagTypeDeclKind(const Decl *PrevDecl, + TagTypeKind TTK) { if (isa<TypedefDecl>(PrevDecl)) return NTK_Typedef; else if (isa<TypeAliasDecl>(PrevDecl)) @@ -12441,7 +12442,17 @@ Sema::NonTagKind Sema::getNonTagTypeDeclKind(const Decl *PrevDecl) { return NTK_TypeAliasTemplate; else if (isa<TemplateTemplateParmDecl>(PrevDecl)) return NTK_TemplateTemplateArgument; - return NTK_Unknown; + switch (TTK) { + case TTK_Struct: + case TTK_Interface: + case TTK_Class: + return getLangOpts().CPlusPlus ? NTK_NonClass : NTK_NonStruct; + case TTK_Union: + return NTK_NonUnion; + case TTK_Enum: + return NTK_NonEnum; + } + llvm_unreachable("invalid TTK"); } /// \brief Determine whether a tag with a given kind is acceptable @@ -13224,8 +13235,9 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // (non-redeclaration) lookup. if ((TUK == TUK_Reference || TUK == TUK_Friend) && !Previous.isForRedeclaration()) { - NonTagKind NTK = getNonTagTypeDeclKind(PrevDecl); - Diag(NameLoc, diag::err_tag_reference_non_tag) << NTK; + NonTagKind NTK = getNonTagTypeDeclKind(PrevDecl, Kind); + Diag(NameLoc, diag::err_tag_reference_non_tag) << PrevDecl << NTK + << Kind; Diag(PrevDecl->getLocation(), diag::note_declared_at); Invalid = true; @@ -13236,7 +13248,7 @@ Decl *Sema::ActOnTag(Scope *S, unsigned TagSpec, TagUseKind TUK, // Diagnose implicit declarations introduced by elaborated types. } else if (TUK == TUK_Reference || TUK == TUK_Friend) { - NonTagKind NTK = getNonTagTypeDeclKind(PrevDecl); + NonTagKind NTK = getNonTagTypeDeclKind(PrevDecl, Kind); Diag(NameLoc, diag::err_tag_reference_conflict) << NTK; Diag(PrevDecl->getLocation(), diag::note_previous_decl) << PrevDecl; Invalid = true; diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 4846b25232a..65ae962c3bf 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -2489,7 +2489,8 @@ TypeResult Sema::ActOnTagTemplateIdType(TagUseKind TUK, // If the identifier resolves to a typedef-name or the simple-template-id // resolves to an alias template specialization, the // elaborated-type-specifier is ill-formed. - Diag(TemplateLoc, diag::err_tag_reference_non_tag) << NTK_TypeAliasTemplate; + Diag(TemplateLoc, diag::err_tag_reference_non_tag) + << TAT << NTK_TypeAliasTemplate << TagKind; Diag(TAT->getLocation(), diag::note_declared_at); } @@ -7508,8 +7509,8 @@ Sema::ActOnExplicitInstantiation(Scope *S, ClassTemplateDecl *ClassTemplate = dyn_cast<ClassTemplateDecl>(TD); if (!ClassTemplate) { - NonTagKind NTK = getNonTagTypeDeclKind(TD); - Diag(TemplateNameLoc, diag::err_tag_reference_non_tag) << NTK; + NonTagKind NTK = getNonTagTypeDeclKind(TD, Kind); + Diag(TemplateNameLoc, diag::err_tag_reference_non_tag) << TD << NTK << Kind; Diag(TD->getLocation(), diag::note_previous_use); return true; } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index dd857f49e30..1a07e719f12 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -1013,8 +1013,9 @@ public: case LookupResult::FoundOverloaded: case LookupResult::FoundUnresolvedValue: { NamedDecl *SomeDecl = Result.getRepresentativeDecl(); - Sema::NonTagKind NTK = SemaRef.getNonTagTypeDeclKind(SomeDecl); - SemaRef.Diag(IdLoc, diag::err_tag_reference_non_tag) << NTK; + Sema::NonTagKind NTK = SemaRef.getNonTagTypeDeclKind(SomeDecl, Kind); + SemaRef.Diag(IdLoc, diag::err_tag_reference_non_tag) << SomeDecl + << NTK << Kind; SemaRef.Diag(SomeDecl->getLocation(), diag::note_declared_at); break; } @@ -5706,7 +5707,8 @@ TreeTransform<Derived>::TransformElaboratedType(TypeLocBuilder &TLB, Template.getAsTemplateDecl())) { SemaRef.Diag(TL.getNamedTypeLoc().getBeginLoc(), diag::err_tag_reference_non_tag) - << Sema::NTK_TypeAliasTemplate; + << TAT << Sema::NTK_TypeAliasTemplate + << ElaboratedType::getTagTypeKindForKeyword(T->getKeyword()); SemaRef.Diag(TAT->getLocation(), diag::note_declared_at); } } diff --git a/clang/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp b/clang/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp index 004d1e491f1..ca17ba50ac2 100644 --- a/clang/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp +++ b/clang/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp @@ -9,7 +9,7 @@ namespace test0 { typedef int A; // expected-note {{declared here}} int test() { - struct A a; // expected-error {{elaborated type refers to a typedef}} + struct A a; // expected-error {{typedef 'A' cannot be referenced with a struct specifier}} return a.foo; } } @@ -18,7 +18,7 @@ namespace test0 { template <class> class A; // expected-note {{declared here}} int test() { - struct A a; // expected-error {{elaborated type refers to a template}} + struct A a; // expected-error {{template 'A' cannot be referenced with a struct specifier}} return a.foo; } } diff --git a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp index 027104151ac..f3e79c0aae4 100644 --- a/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp +++ b/clang/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp @@ -2,18 +2,18 @@ struct A { typedef int type; }; template<typename T> using X = A; // expected-note {{declared here}} -struct X<int>* p2; // expected-error {{elaborated type refers to a type alias template}} +struct X<int>* p2; // expected-error {{type alias template 'X' cannot be referenced with a struct specifier}} template<typename T> using Id = T; // expected-note {{declared here}} template<template<typename> class F> struct Y { - struct F<int> i; // expected-error {{elaborated type refers to a type alias template}} + struct F<int> i; // expected-error {{type alias template 'Id' cannot be referenced with a struct specifier}} typename F<A>::type j; // ok // FIXME: don't produce the diagnostic both for the definition and the instantiation. template<typename T> using U = F<char>; // expected-note 2{{declared here}} - struct Y<F>::template U<char> k; // expected-error 2{{elaborated type refers to a type alias template}} + struct Y<F>::template U<char> k; // expected-error 2{{type alias template 'U' cannot be referenced with a struct specifier}} typename Y<F>::template U<char> l; // ok }; template struct Y<Id>; // expected-note {{requested here}} diff --git a/clang/test/CXX/drs/dr2xx.cpp b/clang/test/CXX/drs/dr2xx.cpp index fa9d67762d8..a9f0c8fcc99 100644 --- a/clang/test/CXX/drs/dr2xx.cpp +++ b/clang/test/CXX/drs/dr2xx.cpp @@ -620,7 +620,7 @@ namespace dr254 { // dr254: yes template<typename T> struct A { typedef typename T::type type; // ok even if this is a typedef-name, because // it's not an elaborated-type-specifier - typedef struct T::type foo; // expected-error {{elaborated type refers to a typedef}} + typedef struct T::type foo; // expected-error {{typedef 'type' cannot be referenced with a struct specifier}} }; struct B { struct type {}; }; struct C { typedef struct {} type; }; // expected-note {{here}} @@ -1048,8 +1048,8 @@ namespace dr298 { // dr298: yes C::type i3; struct A a; - struct B b; // expected-error {{refers to a typedef}} - struct C c; // expected-error {{refers to a typedef}} + struct B b; // expected-error {{typedef 'B' cannot be referenced with a struct specifier}} + struct C c; // expected-error {{typedef 'C' cannot be referenced with a struct specifier}} B::B() {} // expected-error {{requires a type specifier}} B::A() {} // ok diff --git a/clang/test/CXX/drs/dr4xx.cpp b/clang/test/CXX/drs/dr4xx.cpp index 4be3a58a901..6046c4afefd 100644 --- a/clang/test/CXX/drs/dr4xx.cpp +++ b/clang/test/CXX/drs/dr4xx.cpp @@ -90,7 +90,7 @@ namespace dr407 { // dr407: 3.8 struct S *p; { typedef struct S S; // expected-note {{here}} - struct S *p; // expected-error {{refers to a typedef}} + struct S *p; // expected-error {{typedef 'S' cannot be referenced with a struct specifier}} } } struct S {}; diff --git a/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp b/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp index 640d03d4c96..f1f3f701624 100644 --- a/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.friend/p1.cpp @@ -174,7 +174,7 @@ namespace test7 { // This shouldn't crash. template <class T> class D { - friend class A; // expected-error {{elaborated type refers to a template}} + friend class A; // expected-error {{template 'A' cannot be referenced with a class specifier}} }; template class D<int>; } diff --git a/clang/test/CXX/temp/temp.spec/no-body.cpp b/clang/test/CXX/temp/temp.spec/no-body.cpp index 4ec18fdf820..6d1b82fe189 100644 --- a/clang/test/CXX/temp/temp.spec/no-body.cpp +++ b/clang/test/CXX/temp/temp.spec/no-body.cpp @@ -43,7 +43,7 @@ namespace good { // Only good in C++98/03 namespace unsupported { #ifndef FIXING - template struct y; // expected-error {{elaborated type refers to a template}} + template struct y; // expected-error {{template 'y' cannot be referenced with a struct specifier}} #endif } diff --git a/clang/test/SemaCXX/PR8755.cpp b/clang/test/SemaCXX/PR8755.cpp index 07778ddfc90..6818f3f0a82 100644 --- a/clang/test/SemaCXX/PR8755.cpp +++ b/clang/test/SemaCXX/PR8755.cpp @@ -7,7 +7,7 @@ struct A { template <typename T> void f() { - class A <T> ::iterator foo; // expected-error{{elaborated type refers to a typedef}} + class A <T> ::iterator foo; // expected-error{{typedef 'iterator' cannot be referenced with a class specifier}} } void g() { diff --git a/clang/test/SemaCXX/using-decl-templates.cpp b/clang/test/SemaCXX/using-decl-templates.cpp index 3b2b8e15c83..d5cc3a08eb7 100644 --- a/clang/test/SemaCXX/using-decl-templates.cpp +++ b/clang/test/SemaCXX/using-decl-templates.cpp @@ -90,7 +90,7 @@ namespace aliastemplateinst { template<typename T> struct A { }; template<typename T> using APtr = A<T*>; // expected-note{{previous use is here}} - template struct APtr<int>; // expected-error{{elaborated type refers to a type alias template}} + template struct APtr<int>; // expected-error{{type alias template 'APtr' cannot be referenced with a struct specifier}} } namespace DontDiagnoseInvalidTest { diff --git a/clang/test/SemaTemplate/template-id-expr.cpp b/clang/test/SemaTemplate/template-id-expr.cpp index 499d289ee67..e311b5832d0 100644 --- a/clang/test/SemaTemplate/template-id-expr.cpp +++ b/clang/test/SemaTemplate/template-id-expr.cpp @@ -100,5 +100,5 @@ template void f5<0>(); // expected-note {{in instantiation of function template class C {}; template <template <typename> class D> // expected-note{{previous use is here}} class E { - template class D<C>; // expected-error {{elaborated type refers to a template template argument}} + template class D<C>; // expected-error {{template template argument 'D' cannot be referenced with a class specifier}} }; |