I never heard "class specifier" outside of compilerese either… On Fri, Dec 9, 2016 at 2:47 PM, Reid Kleckner via cfe-commits < cfe-commits@lists.llvm.org> wrote:
> Author: rnk > Date: Fri Dec 9 13:47:58 2016 > New Revision: 289259 > > URL: http://llvm.org/viewvc/llvm-project?rev=289259&view=rev > Log: > Improve error message when referencing a non-tag type with a tag > > Other compilers accept invalid code here that we reject, and we need a > better error message to try to convince users that the code is really > incorrect. Consider: > class Foo { > typedef MyIterHelper<Foo> iterator; > friend class iterator; > }; > > Previously our wording was "elaborated type refers to a typedef". > "elaborated type" isn't widely known terminology, so the new diagnostic > says "typedef 'iterator' cannot be referenced with class specifier". > > Reviewers: rsmith > > Differential Revision: https://reviews.llvm.org/D25216 > > Modified: > cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > cfe/trunk/include/clang/Sema/Sema.h > cfe/trunk/lib/Sema/SemaDecl.cpp > cfe/trunk/lib/Sema/SemaTemplate.cpp > cfe/trunk/lib/Sema/TreeTransform.h > cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp > cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp > cfe/trunk/test/CXX/drs/dr2xx.cpp > cfe/trunk/test/CXX/drs/dr4xx.cpp > cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp > cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp > cfe/trunk/test/SemaCXX/PR8755.cpp > cfe/trunk/test/SemaCXX/using-decl-templates.cpp > cfe/trunk/test/SemaTemplate/template-id-expr.cpp > > Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/ > DiagnosticSemaKinds.td?rev=289259&r1=289258&r2=289259&view=diff > ============================================================ > ================== > --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original) > +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Fri Dec 9 > 13:47:58 2016 > @@ -4564,10 +4564,15 @@ def err_redefinition_different_typedef : > "%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">; > > Modified: cfe/trunk/include/clang/Sema/Sema.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/ > clang/Sema/Sema.h?rev=289259&r1=289258&r2=289259&view=diff > ============================================================ > ================== > --- cfe/trunk/include/clang/Sema/Sema.h (original) > +++ cfe/trunk/include/clang/Sema/Sema.h Fri Dec 9 13:47:58 2016 > @@ -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, > > Modified: cfe/trunk/lib/Sema/SemaDecl.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/ > SemaDecl.cpp?rev=289259&r1=289258&r2=289259&view=diff > ============================================================ > ================== > --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) > +++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Dec 9 13:47:58 2016 > @@ -12430,7 +12430,8 @@ static bool isClassCompatTagKind(TagType > 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::getNonTagTypeDecl > 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 > // (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 > > // 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; > > Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/ > SemaTemplate.cpp?rev=289259&r1=289258&r2=289259&view=diff > ============================================================ > ================== > --- cfe/trunk/lib/Sema/SemaTemplate.cpp (original) > +++ cfe/trunk/lib/Sema/SemaTemplate.cpp Fri Dec 9 13:47:58 2016 > @@ -2489,7 +2489,8 @@ TypeResult Sema::ActOnTagTemplateIdType( > // 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 * > 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; > } > > Modified: cfe/trunk/lib/Sema/TreeTransform.h > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/ > TreeTransform.h?rev=289259&r1=289258&r2=289259&view=diff > ============================================================ > ================== > --- cfe/trunk/lib/Sema/TreeTransform.h (original) > +++ cfe/trunk/lib/Sema/TreeTransform.h Fri Dec 9 13:47:58 2016 > @@ -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>::TransformElabora > 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); > } > } > > Modified: cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/ > basic/basic.lookup/basic.lookup.elab/p2.cpp?rev=289259& > r1=289258&r2=289259&view=diff > ============================================================ > ================== > --- cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp > (original) > +++ cfe/trunk/test/CXX/basic/basic.lookup/basic.lookup.elab/p2.cpp Fri > Dec 9 13:47:58 2016 > @@ -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; > } > } > > Modified: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type. > elab/p2-0x.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/ > dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp?rev= > 289259&r1=289258&r2=289259&view=diff > ============================================================ > ================== > --- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp > (original) > +++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p2-0x.cpp > Fri Dec 9 13:47:58 2016 > @@ -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}} > > Modified: cfe/trunk/test/CXX/drs/dr2xx.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/ > drs/dr2xx.cpp?rev=289259&r1=289258&r2=289259&view=diff > ============================================================ > ================== > --- cfe/trunk/test/CXX/drs/dr2xx.cpp (original) > +++ cfe/trunk/test/CXX/drs/dr2xx.cpp Fri Dec 9 13:47:58 2016 > @@ -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 > > Modified: cfe/trunk/test/CXX/drs/dr4xx.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/ > drs/dr4xx.cpp?rev=289259&r1=289258&r2=289259&view=diff > ============================================================ > ================== > --- cfe/trunk/test/CXX/drs/dr4xx.cpp (original) > +++ cfe/trunk/test/CXX/drs/dr4xx.cpp Fri Dec 9 13:47:58 2016 > @@ -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 {}; > > Modified: cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/ > temp/temp.decls/temp.friend/p1.cpp?rev=289259&r1=289258& > r2=289259&view=diff > ============================================================ > ================== > --- cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp (original) > +++ cfe/trunk/test/CXX/temp/temp.decls/temp.friend/p1.cpp Fri Dec 9 > 13:47:58 2016 > @@ -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>; > } > > Modified: cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/ > temp/temp.spec/no-body.cpp?rev=289259&r1=289258&r2=289259&view=diff > ============================================================ > ================== > --- cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp (original) > +++ cfe/trunk/test/CXX/temp/temp.spec/no-body.cpp Fri Dec 9 13:47:58 2016 > @@ -43,7 +43,7 @@ namespace good { // Only good in C++98/0 > > 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 > } > > > Modified: cfe/trunk/test/SemaCXX/PR8755.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ > SemaCXX/PR8755.cpp?rev=289259&r1=289258&r2=289259&view=diff > ============================================================ > ================== > --- cfe/trunk/test/SemaCXX/PR8755.cpp (original) > +++ cfe/trunk/test/SemaCXX/PR8755.cpp Fri Dec 9 13:47:58 2016 > @@ -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() { > > Modified: cfe/trunk/test/SemaCXX/using-decl-templates.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ > SemaCXX/using-decl-templates.cpp?rev=289259&r1=289258&r2=289259&view=diff > ============================================================ > ================== > --- cfe/trunk/test/SemaCXX/using-decl-templates.cpp (original) > +++ cfe/trunk/test/SemaCXX/using-decl-templates.cpp Fri Dec 9 13:47:58 > 2016 > @@ -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 { > > Modified: cfe/trunk/test/SemaTemplate/template-id-expr.cpp > URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/ > SemaTemplate/template-id-expr.cpp?rev=289259&r1=289258&r2=289259&view=diff > ============================================================ > ================== > --- cfe/trunk/test/SemaTemplate/template-id-expr.cpp (original) > +++ cfe/trunk/test/SemaTemplate/template-id-expr.cpp Fri Dec 9 13:47:58 > 2016 > @@ -100,5 +100,5 @@ template void f5<0>(); // expected-note > 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}} > }; > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits