r268594 - Fix implementation of C++'s restrictions on using-declarations referring to enumerators:

Reid Kleckner via cfe-commits cfe-commits at lists.llvm.org
Thu May 5 10:40:53 PDT 2016


FYI, this change broke bionic, which has this exact pattern:
https://android.googlesource.com/platform/bionic/+/master/tools/relocation_packer/src/debug.h#84

struct A {
  enum E {
    X = 3
  };
};
typedef A::E T;
using T::X;

I expect users are going to have lots of issues with this, and it probably
warrants a release note.

On Wed, May 4, 2016 at 7:13 PM, Richard Smith via cfe-commits <
cfe-commits at lists.llvm.org> wrote:

> Author: rsmith
> Date: Wed May  4 21:13:49 2016
> New Revision: 268594
>
> URL: http://llvm.org/viewvc/llvm-project?rev=268594&view=rev
> Log:
> Fix implementation of C++'s restrictions on using-declarations referring
> to enumerators:
>
>  * an unscoped enumerator whose enumeration is a class member is itself a
> class
>    member, so can only be the subject of a class-scope using-declaration.
>
>  * a scoped enumerator cannot be the subject of a class-scope
> using-declaration.
>
> Added:
>     cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp
>       - copied, changed from r268583,
> cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp
>     cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx11.cpp
>       - copied, changed from r268583,
> cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp
> Removed:
>     cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp
>     cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp
> Modified:
>     cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
>     cfe/trunk/lib/Sema/SemaDeclCXX.cpp
>     cfe/trunk/test/CXX/drs/dr4xx.cpp
>     cfe/trunk/test/SemaCXX/enum-scoped.cpp
>
> Modified: cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td?rev=268594&r1=268593&r2=268594&view=diff
>
> ==============================================================================
> --- cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td (original)
> +++ cfe/trunk/include/clang/Basic/DiagnosticSemaKinds.td Wed May  4
> 21:13:49 2016
> @@ -396,7 +396,9 @@ def note_using_decl_class_member_workaro
>    "use %select{an alias declaration|a typedef declaration|a reference}0 "
>    "instead">;
>  def err_using_decl_can_not_refer_to_namespace : Error<
> -  "using declaration cannot refer to namespace">;
> +  "using declaration cannot refer to a namespace">;
> +def err_using_decl_can_not_refer_to_scoped_enum : Error<
> +  "using declaration cannot refer to a scoped enumerator">;
>  def err_using_decl_constructor : Error<
>    "using declaration cannot refer to a constructor">;
>  def warn_cxx98_compat_using_decl_constructor : Warning<
>
> Modified: cfe/trunk/lib/Sema/SemaDeclCXX.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDeclCXX.cpp?rev=268594&r1=268593&r2=268594&view=diff
>
> ==============================================================================
> --- cfe/trunk/lib/Sema/SemaDeclCXX.cpp (original)
> +++ cfe/trunk/lib/Sema/SemaDeclCXX.cpp Wed May  4 21:13:49 2016
> @@ -7738,7 +7738,7 @@ bool Sema::CheckUsingShadowDecl(UsingDec
>    // function will silently decide not to build a shadow decl, which
>    // will pre-empt further diagnostics.
>    //
> -  // We don't need to do this in C++0x because we do the check once on
> +  // We don't need to do this in C++11 because we do the check once on
>    // the qualifier.
>    //
>    // FIXME: diagnose the following if we care enough:
> @@ -8227,7 +8227,7 @@ NamedDecl *Sema::BuildUsingDeclaration(S
>      }
>    }
>
> -  // C++0x N2914 [namespace.udecl]p6:
> +  // C++14 [namespace.udecl]p6:
>    // A using-declaration shall not name a namespace.
>    if (R.getAsSingle<NamespaceDecl>()) {
>      Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_namespace)
> @@ -8235,6 +8235,16 @@ NamedDecl *Sema::BuildUsingDeclaration(S
>      return BuildInvalid();
>    }
>
> +  // C++14 [namespace.udecl]p7:
> +  // A using-declaration shall not name a scoped enumerator.
> +  if (auto *ED = R.getAsSingle<EnumConstantDecl>()) {
> +    if (cast<EnumDecl>(ED->getDeclContext())->isScoped()) {
> +      Diag(IdentLoc, diag::err_using_decl_can_not_refer_to_scoped_enum)
> +        << SS.getRange();
> +      return BuildInvalid();
> +    }
> +  }
> +
>    UsingDecl *UD = BuildValid();
>
>    // The normal rules do not apply to inheriting constructor declarations.
> @@ -8359,8 +8369,10 @@ bool Sema::CheckUsingDeclQualifier(Sourc
>
>      // If we weren't able to compute a valid scope, it must be a
>      // dependent class scope.
> -    if (!NamedContext || NamedContext->isRecord()) {
> -      auto *RD = dyn_cast_or_null<CXXRecordDecl>(NamedContext);
> +    if (!NamedContext || NamedContext->getRedeclContext()->isRecord()) {
> +      auto *RD = NamedContext
> +                     ?
> cast<CXXRecordDecl>(NamedContext->getRedeclContext())
> +                     : nullptr;
>        if (RD && RequireCompleteDeclContext(const_cast<CXXScopeSpec&>(SS),
> RD))
>          RD = nullptr;
>
> @@ -8444,7 +8456,7 @@ bool Sema::CheckUsingDeclQualifier(Sourc
>      return true;
>
>    if (getLangOpts().CPlusPlus11) {
> -    // C++0x [namespace.udecl]p3:
> +    // C++11 [namespace.udecl]p3:
>      //   In a using-declaration used as a member-declaration, the
>      //   nested-name-specifier shall name a base class of the class
>      //   being defined.
>
> Removed:
> cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp?rev=268593&view=auto
>
> ==============================================================================
> ---
> cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp
> (original)
> +++
> cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp
> (removed)
> @@ -1,46 +0,0 @@
> -// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
> -// C++0x N2914.
> -
> -struct B {
> -  void f(char);
> -  void g(char);
> -  enum E { e };
> -  union { int x; };
> -};
> -
> -class C {
> -  int g();
> -};
> -
> -class D2 : public B {
> -  using B::f;
> -  using B::e;
> -  using B::x;
> -  using C::g; // expected-error{{using declaration refers into 'C::',
> which is not a base class of 'D2'}}
> -};
> -
> -namespace test1 {
> -  struct Base {
> -    int foo();
> -  };
> -
> -  struct Unrelated {
> -    int foo();
> -  };
> -
> -  struct Subclass : Base {
> -  };
> -
> -  namespace InnerNS {
> -    int foo();
> -  }
> -
> -  // We should be able to diagnose these without instantiation.
> -  template <class T> struct C : Base {
> -    using InnerNS::foo; // expected-error {{not a class}}
> -    using Base::bar; // expected-error {{no member named 'bar'}}
> -    using Unrelated::foo; // expected-error {{not a base class}}
> -    using C::foo; // expected-error {{refers to its own class}}
> -    using Subclass::foo; // expected-error {{not a base class}}
> -  };
> -}
>
> Copied: cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp
> (from r268583,
> cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp)
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp?p2=cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp&p1=cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp&r1=268583&r2=268594&rev=268594&view=diff
>
> ==============================================================================
> ---
> cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3-cxx0x.cpp
> (original)
> +++ cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p3.cpp Wed
> May  4 21:13:49 2016
> @@ -1,22 +1,48 @@
> +// RUN: %clang_cc1 -std=c++98 -fsyntax-only -verify %s
>  // RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
> -// C++0x N2914.
> +// RUN: %clang_cc1 -fsyntax-only -verify %s
>
>  struct B {
>    void f(char);
>    void g(char);
>    enum E { e };
>    union { int x; };
> +
> +  enum class EC { ec }; // expected-warning 0-1 {{C++11}}
> +
> +  void f2(char);
> +  void g2(char);
> +  enum E2 { e2 };
> +  union { int x2; };
>  };
>
>  class C {
>    int g();
>  };
>
> +struct D : B {};
> +
>  class D2 : public B {
>    using B::f;
> +  using B::E;
>    using B::e;
>    using B::x;
>    using C::g; // expected-error{{using declaration refers into 'C::',
> which is not a base class of 'D2'}}
> +
> +  // These are valid in C++98 but not in C++11.
> +  using D::f2;
> +  using D::E2;
> +  using D::e2;
> +  using D::x2;
> +#if __cplusplus >= 201103L
> +  // expected-error at -5 {{using declaration refers into 'D::', which is
> not a base class of 'D2'}}
> +  // expected-error at -5 {{using declaration refers into 'D::', which is
> not a base class of 'D2'}}
> +  // expected-error at -5 {{using declaration refers into 'D::', which is
> not a base class of 'D2'}}
> +  // expected-error at -5 {{using declaration refers into 'D::', which is
> not a base class of 'D2'}}
> +#endif
> +
> +  using B::EC;
> +  using B::EC::ec; // expected-error {{not a class}} expected-warning 0-1
> {{C++11}}
>  };
>
>  namespace test1 {
> @@ -35,12 +61,22 @@ namespace test1 {
>      int foo();
>    }
>
> +  struct B : Base {
> +  };
> +
>    // We should be able to diagnose these without instantiation.
>    template <class T> struct C : Base {
>      using InnerNS::foo; // expected-error {{not a class}}
>      using Base::bar; // expected-error {{no member named 'bar'}}
>      using Unrelated::foo; // expected-error {{not a base class}}
> -    using C::foo; // expected-error {{refers to its own class}}
> -    using Subclass::foo; // expected-error {{not a base class}}
> +
> +    // In C++98, it's hard to see that these are invalid, because indirect
> +    // references to base class members are permitted.
> +    using C::foo;
> +    using Subclass::foo;
> +#if __cplusplus >= 201103L
> +    // expected-error at -3 {{refers to its own class}}
> +    // expected-error at -3 {{not a base class}}
> +#endif
>    };
>  }
>
> Removed:
> cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp?rev=268593&view=auto
>
> ==============================================================================
> ---
> cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp
> (original)
> +++
> cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp
> (removed)
> @@ -1,8 +0,0 @@
> -// RUN: %clang_cc1 -fsyntax-only -verify %s
> -// C++0x N2914.
> -
> -namespace A {
> -  namespace B { }
> -}
> -
> -using A::B; // expected-error{{using declaration cannot refer to
> namespace}}
>
> Copied:
> cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx11.cpp
> (from r268583,
> cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp)
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx11.cpp?p2=cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx11.cpp&p1=cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp&r1=268583&r2=268594&rev=268594&view=diff
>
> ==============================================================================
> ---
> cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx0x.cpp
> (original)
> +++
> cfe/trunk/test/CXX/dcl.dcl/basic.namespace/namespace.udecl/p6-cxx11.cpp Wed
> May  4 21:13:49 2016
> @@ -1,8 +1,7 @@
>  // RUN: %clang_cc1 -fsyntax-only -verify %s
> -// C++0x N2914.
>
>  namespace A {
>    namespace B { }
>  }
>
> -using A::B; // expected-error{{using declaration cannot refer to
> namespace}}
> +using A::B; // expected-error{{using declaration cannot refer to a
> namespace}}
>
> Modified: cfe/trunk/test/CXX/drs/dr4xx.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/drs/dr4xx.cpp?rev=268594&r1=268593&r2=268594&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/CXX/drs/dr4xx.cpp (original)
> +++ cfe/trunk/test/CXX/drs/dr4xx.cpp Wed May  4 21:13:49 2016
> @@ -702,8 +702,8 @@ namespace dr460 { // dr460: yes
>    namespace X { namespace Q { int n; } }
>    namespace Y {
>      using X; // expected-error {{requires a qualified name}}
> -    using dr460::X; // expected-error {{cannot refer to namespace}}
> -    using X::Q; // expected-error {{cannot refer to namespace}}
> +    using dr460::X; // expected-error {{cannot refer to a namespace}}
> +    using X::Q; // expected-error {{cannot refer to a namespace}}
>    }
>  }
>
>
> Modified: cfe/trunk/test/SemaCXX/enum-scoped.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/enum-scoped.cpp?rev=268594&r1=268593&r2=268594&view=diff
>
> ==============================================================================
> --- cfe/trunk/test/SemaCXX/enum-scoped.cpp (original)
> +++ cfe/trunk/test/SemaCXX/enum-scoped.cpp Wed May  4 21:13:49 2016
> @@ -298,8 +298,8 @@ namespace PR18044 {
>    int E::*p; // expected-error {{does not point into a class}}
>    using E::f; // expected-error {{no member named 'f'}}
>
> -  using E::a; // ok!
> -  E b = a;
> +  using E::a; // expected-error {{using declaration cannot refer to a
> scoped enumerator}}
> +  E b = a; // expected-error {{undeclared}}
>  }
>
>  namespace test11 {
>
>
> _______________________________________________
> 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/20160505/b9e4f91b/attachment-0001.html>


More information about the cfe-commits mailing list