aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Palka <ppalka@redhat.com>2021-06-03 09:37:11 -0400
committerPatrick Palka <ppalka@redhat.com>2021-06-03 09:37:11 -0400
commit69f517ac20566a645ff41a9bfca535822205a538 (patch)
tree2875107dbf5de313799318d11e5d0f1c1f3da5f7
parent7ed1cd9665d8ca0fa07b2483e604c25e704584af (diff)
downloadgcc-69f517ac20566a645ff41a9bfca535822205a538.zip
gcc-69f517ac20566a645ff41a9bfca535822205a538.tar.gz
gcc-69f517ac20566a645ff41a9bfca535822205a538.tar.bz2
c++: using-enum and access specifiers [PR100862]
When copying the enumerators imported by a class-scope using-enum declaration, we need to override current_access_specifier so that finish_member_declaration gives the copies the same access as the using-enum decl. (A class-scope using-enum is processed late, so current_access_specifier at this point is otherwise set to the last access specifier within the class.) To that end, this patch makes handle_using_decl call set_current_access_from_decl accordingly. For consistency, this patch makes build_enumerator use set_current_access_from_decl too. PR c++/100862 gcc/cp/ChangeLog: * pt.c (set_current_access_from_decl): Move to ... * class.c (set_current_access_from_decl): ... here. (handle_using_decl): Use it to propagate the access of the using-enum decl to the copy of the imported enumerator. * cp-tree.h (set_current_access_from_decl): Declare. * decl.c (build_enumerator): Simplify using make_temp_override and set_current_access_from_decl. gcc/testsuite/ChangeLog: * g++.dg/cpp2a/using-enum-9.C: New test.
-rw-r--r--gcc/cp/class.c15
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c12
-rw-r--r--gcc/cp/pt.c14
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/using-enum-9.C28
5 files changed, 46 insertions, 24 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 354addd..b53a4db 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -207,6 +207,19 @@ static bool type_maybe_constexpr_default_constructor (tree);
static bool type_maybe_constexpr_destructor (tree);
static bool field_poverlapping_p (tree);
+/* Set CURRENT_ACCESS_SPECIFIER based on the protection of DECL. */
+
+void
+set_current_access_from_decl (tree decl)
+{
+ if (TREE_PRIVATE (decl))
+ current_access_specifier = access_private_node;
+ else if (TREE_PROTECTED (decl))
+ current_access_specifier = access_protected_node;
+ else
+ current_access_specifier = access_public_node;
+}
+
/* Return a COND_EXPR that executes TRUE_STMT if this execution of the
'structor is in charge of 'structing virtual bases, or FALSE_STMT
otherwise. */
@@ -1359,6 +1372,8 @@ handle_using_decl (tree using_decl, tree t)
CONST_DECL_USING_P is true. */
gcc_assert (TREE_CODE (decl) == CONST_DECL);
+ auto cas = make_temp_override (current_access_specifier);
+ set_current_access_from_decl (using_decl);
tree copy = copy_decl (decl);
DECL_CONTEXT (copy) = t;
DECL_ARTIFICIAL (copy) = true;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c95a820..b1b7e61 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -8186,6 +8186,7 @@ struct atom_hasher : default_hash_traits<tree>
extern bool subsumes (tree, tree);
/* In class.c */
+extern void set_current_access_from_decl (tree);
extern void cp_finish_injected_record_type (tree);
/* in vtable-class-hierarchy.c */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index e7268d5..fb21a3a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -16333,17 +16333,9 @@ incremented enumerator value is too large for %<long%>"));
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;
-
+ auto cas = make_temp_override (current_access_specifier);
+ set_current_access_from_decl (TYPE_NAME (enumtype));
finish_member_declaration (decl);
-
- current_access_specifier = saved_cas;
}
else
pushdecl (decl);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 15ef488..7211bdc 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -190,7 +190,6 @@ static tree tsubst_arg_types (tree, tree, tree, tsubst_flags_t, tree);
static tree tsubst_function_type (tree, tree, tsubst_flags_t, tree);
static bool check_specialization_scope (void);
static tree process_partial_specialization (tree);
-static void set_current_access_from_decl (tree);
static enum template_base_result get_template_base (tree, tree, tree, tree,
bool , tree *);
static tree try_class_unification (tree, tree, tree, tree, bool);
@@ -26432,19 +26431,6 @@ tsubst_initializer_list (tree t, tree argvec)
return inits;
}
-/* Set CURRENT_ACCESS_SPECIFIER based on the protection of DECL. */
-
-static void
-set_current_access_from_decl (tree decl)
-{
- if (TREE_PRIVATE (decl))
- current_access_specifier = access_private_node;
- else if (TREE_PROTECTED (decl))
- current_access_specifier = access_protected_node;
- else
- current_access_specifier = access_public_node;
-}
-
/* Instantiate an enumerated type. TAG is the template type, NEWTAG
is the instantiation (which should have been created with
start_enum) and ARGS are the template arguments to use. */
diff --git a/gcc/testsuite/g++.dg/cpp2a/using-enum-9.C b/gcc/testsuite/g++.dg/cpp2a/using-enum-9.C
new file mode 100644
index 0000000..3e02605
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/using-enum-9.C
@@ -0,0 +1,28 @@
+// PR c++/100862
+// { dg-do compile { target c++20 } }
+
+enum class fruit { orange, apple };
+
+struct A {
+public:
+ using enum fruit;
+private:
+};
+
+struct B {
+protected:
+ using enum fruit;
+public:
+};
+
+struct C {
+private:
+ using enum fruit;
+public:
+};
+
+int main() {
+ A::orange, A::apple;
+ B::orange, B::apple; // { dg-error "protected" }
+ C::orange, C::apple; // { dg-error "private" }
+}