On Sun, Apr 17, 2016 at 2:01 PM, Patrick Palka <patr...@parcs.ath.cx> wrote: > When an in-class unscoped enumeration is defined out-of-line its > enumerators currently don't inherit the access of the enumeration. This > patch makes the access of the enumerations defined out-of-line match the > access of the enumerator. > > Also, we currently don't check that redeclarations of in-class > enumerations have the same access, which this patch fixes as well. > > Bootstrapped + regtested on x86_64-pc-linux-gnu, does this look OK to > commit? > > gcc/cp/ChangeLog: > > PR c++/70241 > * decl.c (build_enumerator): Set current_access_specifier when > declaring an enumerator belonging to an in-class enumeration. > * parser.c (cp_parser_check_access_in_redecleration): Also > consider in-class enumerations. > > gcc/testsite/ChangeLog: > > PR c++/70241 > * g++.dg/cpp0x/enum32.C: New test. > * g++.dg/cpp0x/enum33.C: New test. > --- > gcc/cp/decl.c | 28 ++++++++++++++++++++++++---- > gcc/cp/parser.c | 8 +++++--- > gcc/testsuite/g++.dg/cpp0x/enum32.C | 25 +++++++++++++++++++++++++ > gcc/testsuite/g++.dg/cpp0x/enum33.C | 11 +++++++++++ > 4 files changed, 65 insertions(+), 7 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp0x/enum32.C > create mode 100644 gcc/testsuite/g++.dg/cpp0x/enum33.C > > diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c > index f9f12a7..0f217a5 100644 > --- a/gcc/cp/decl.c > +++ b/gcc/cp/decl.c > @@ -13694,10 +13694,30 @@ incremented enumerator value is too large for > %<long%>"); > cplus_decl_attributes (&decl, attributes, 0); > > if (context && context == current_class_type && !SCOPED_ENUM_P (enumtype)) > - /* In something like `struct S { enum E { i = 7 }; };' we put `i' > - on the TYPE_FIELDS list for `S'. (That's so that you can say > - things like `S::i' later.) */ > - finish_member_declaration (decl); > + { > + /* In something like `struct S { enum E { i = 7 }; };' we put `i' > + on the TYPE_FIELDS list for `S'. (That's so that you can say > + things like `S::i' later.) */ > + > + /* The enumerator may be getting declared outside of its enclosing > + class, like so: > + > + class S { public: enum E : int; }; enum S::E : int { i = 7; }; > + > + For which case we need to make sure that the access of `S::i' > + matches the access of `S::E'. */ > + tree saved_cas = current_access_specifier; > + if (TREE_PRIVATE (TYPE_NAME (enumtype))) > + current_access_specifier = access_private_node; > + else if (TREE_PROTECTED (TYPE_NAME (enumtype))) > + current_access_specifier = access_protected_node; > + else > + current_access_specifier = access_public_node; > + > + finish_member_declaration (decl); > + > + current_access_specifier = saved_cas; > + } > else > pushdecl (decl); > > diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c > index 5486129..f782d70 100644 > --- a/gcc/cp/parser.c > +++ b/gcc/cp/parser.c > @@ -27228,13 +27228,15 @@ cp_parser_check_class_key (enum tag_types > class_key, tree type) > > /* Issue an error message if DECL is redeclared with different > access than its original declaration [class.access.spec/3]. > - This applies to nested classes and nested class templates. > - [class.mem/1]. */ > + This applies to nested classes, nested class templates and > + enumerations [class.mem/1]. */ > > static void > cp_parser_check_access_in_redeclaration (tree decl, location_t location) > { > - if (!decl || !CLASS_TYPE_P (TREE_TYPE (decl))) > + if (!decl > + || (!CLASS_TYPE_P (TREE_TYPE (decl)) > + && TREE_CODE (TREE_TYPE (decl)) != ENUMERAL_TYPE)) > return; > > if ((TREE_PRIVATE (decl) > diff --git a/gcc/testsuite/g++.dg/cpp0x/enum32.C > b/gcc/testsuite/g++.dg/cpp0x/enum32.C > new file mode 100644 > index 0000000..9d7a7b5 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp0x/enum32.C > @@ -0,0 +1,25 @@ > +// PR c++/70241 > +// { dg-do compile { target c++11 } } > + > +class A { > +public: > + enum B : int; > +}; > + > +enum A::B : int { > + x > +}; > + > +struct C { > +private: > + enum D : int; > +}; > + > +enum C::D : int { > + y > +}; > + > +int main() { > + A::x; > + C::y; // { dg-error "private" } > +} > diff --git a/gcc/testsuite/g++.dg/cpp0x/enum33.C > b/gcc/testsuite/g++.dg/cpp0x/enum33.C > new file mode 100644 > index 0000000..ac39741 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp0x/enum33.C > @@ -0,0 +1,11 @@ > +// PR c++/70241 > +// { dg-do compile { target c++11 } } > + > +class A { > +public: > + enum B : int; > + enum class C : int; > +private: > + enum B : int { }; // { dg-error "different access" } > + enum class C : int { }; // { dg-error "different access" } > +}; > -- > 2.8.1.231.g95ac767 >
Ping.