]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fix PR c++/70241 (inconsistent access with in-class enumeration)
authorPatrick Palka <ppalka@gcc.gnu.org>
Tue, 26 Apr 2016 22:24:43 +0000 (22:24 +0000)
committerPatrick Palka <ppalka@gcc.gnu.org>
Tue, 26 Apr 2016 22:24:43 +0000 (22:24 +0000)
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.

From-SVN: r235456

gcc/cp/ChangeLog
gcc/cp/decl.c
gcc/cp/parser.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/enum32.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/enum33.C [new file with mode: 0644]

index c78abe83bbb0bdfb5d4eb52fa1632a22a64f91b1..b2185df76aef03d6c3348f1a2aaba30fb8289db5 100644 (file)
@@ -1,3 +1,11 @@
+2016-04-26  Patrick Palka  <ppalka@gcc.gnu.org>
+
+       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.
+
 2016-04-26  Marek Polacek  <polacek@redhat.com>
 
        PR c++/70744
index 461822ba16774d0729a0ebfc7df34ae764f40a78..a74e9a24a4ea002df3e034f4425876186b74fe92 100644 (file)
@@ -13686,10 +13686,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);
 
index 500a9b39a26e6ae8d55b45785742b8099c9e36aa..2dcb766a995afb222c1f9048006dadde7782c2db 100644 (file)
@@ -27238,13 +27238,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)
index 12d37f625d4484b8eb180c5a1792cfeed88cc300..8401206c7a0cd043ade88666b8f806b896a2189d 100644 (file)
@@ -1,4 +1,10 @@
-2016-04-06  Senthil Kumar Selvaraj  <senthil_kumar.selvaraj@atmel.com>
+2016-04-26  Patrick Palka  <ppalka@gcc.gnu.org>
+
+       PR c++/70241
+       * g++.dg/cpp0x/enum32.C: New test.
+       * g++.dg/cpp0x/enum33.C: New test.
+
+2016-04-26  Senthil Kumar Selvaraj  <senthil_kumar.selvaraj@atmel.com>
 
        * gcc.c-torture/compile/pr69102.c: Require scheduling support.
        * gcc.c-torture/compile/pr37669.c: Require >=32 bit integers.
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum32.C b/gcc/testsuite/g++.dg/cpp0x/enum32.C
new file mode 100644 (file)
index 0000000..9d7a7b5
--- /dev/null
@@ -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 (file)
index 0000000..ac39741
--- /dev/null
@@ -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" }
+};