[PATCH] c++: using-enum and access specifiers [PR100862]

Jason Merrill jason@redhat.com
Wed Jun 2 19:48:18 GMT 2021


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" }
> +}
> 



More information about the Gcc-patches mailing list