Message ID | 20210602183914.958300-1-ppalka@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: using-enum and access specifiers [PR100862] | expand |
On 6/2/21 2:39 PM, Patrick Palka wrote: > 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 them the same access as the using-enum > decl. The processing of a using-enum is performed after we've seen the > entire definition of the class, so current_access_specifier at this > point is otherwise set to the last access specifier within the class. > > For consistency, this patch makes build_enumerator use > set_current_access_from_decl too. > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for > trunk/11? OK. > 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. > --- > gcc/cp/class.c | 15 ++++++++++++ > gcc/cp/cp-tree.h | 1 + > gcc/cp/decl.c | 12 ++-------- > gcc/cp/pt.c | 14 ------------ > gcc/testsuite/g++.dg/cpp2a/using-enum-9.C | 28 +++++++++++++++++++++++ > 5 files changed, 46 insertions(+), 24 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/cpp2a/using-enum-9.C > > diff --git a/gcc/cp/class.c b/gcc/cp/class.c > index 354addde773..b53a4dbdd4e 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 c95a820037f..b1b7e615bcc 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 e7268d5ad18..fb21a3a1ae8 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 31302803c62..86259e900e9 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); > @@ -26431,19 +26430,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 00000000000..3e026057b40 > --- /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" } > +} >
diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 354addde773..b53a4dbdd4e 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 c95a820037f..b1b7e615bcc 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 e7268d5ad18..fb21a3a1ae8 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 31302803c62..86259e900e9 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); @@ -26431,19 +26430,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 00000000000..3e026057b40 --- /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" } +}