r289259 - Improve error message when referencing a non-tag type with a tag

Nico Weber via cfe-commits cfe-commits at lists.llvm.org
Fri Dec 9 12:01:07 PST 2016


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 at 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 at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20161209/8f51687c/attachment-0001.html>


More information about the cfe-commits mailing list