aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@gcc.gnu.org>2016-04-26 22:24:43 +0000
committerPatrick Palka <ppalka@gcc.gnu.org>2016-04-26 22:24:43 +0000
commit843ce8abafc0ba4ff7e15588c9713a784a771f0d (patch)
tree89e4c1f9086d639dff4c482b7ed34eea53576798 /gcc
parent3866f82f5847a4bb81a98a18ec7480fefacba74a (diff)
downloadgcc-843ce8abafc0ba4ff7e15588c9713a784a771f0d.zip
gcc-843ce8abafc0ba4ff7e15588c9713a784a771f0d.tar.gz
gcc-843ce8abafc0ba4ff7e15588c9713a784a771f0d.tar.bz2
Fix PR c++/70241 (inconsistent access with in-class enumeration)
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/decl.c28
-rw-r--r--gcc/cp/parser.c8
-rw-r--r--gcc/testsuite/ChangeLog8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum32.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum33.C11
6 files changed, 80 insertions, 8 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index c78abe8..b2185df 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 461822b..a74e9a2 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 500a9b3..2dcb766 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 12d37f6..8401206 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
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" }
+};