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

Richard Smith via cfe-commits cfe-commits at lists.llvm.org
Thu May 5 11:15:47 PDT 2016


On Thu, May 5, 2016 at 10:40 AM, Reid Kleckner <rnk at google.com> wrote:

> 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.
>

Given that GCC rejects this code (and has done for as long as it's accepted
the Enum::Member syntax), I don't expect the problems to be too widespread.
If they are, we could trivially accept this as an extension; it seems like
a pointless restriction.


> 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/9b4e3191/attachment-0001.html>


More information about the cfe-commits mailing list