public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jason Merrill <jason@redhat.com>
To: Patrick Palka <ppalka@redhat.com>, gcc-patches@gcc.gnu.org
Subject: Re: [PATCH] c++: access scope during partial spec matching [PR96204]
Date: Fri, 25 Jun 2021 11:50:44 -0400	[thread overview]
Message-ID: <6d414d65-3666-f17d-d5dc-1de7a9e4c929@redhat.com> (raw)
In-Reply-To: <20210625150352.913072-1-ppalka@redhat.com>

On 6/25/21 11:03 AM, Patrick Palka wrote:
> Here, when determining whether the partial specialization matches the
> specialization has_set_attr_method<Child>, we do so from the scope of
> where the template-id appears rather than from the scope of the
> specialization, and this causes us to select the partial specialization
> (since Child::type is accessible from Parent).  When we later
> instantiate this partial specialization, we've entered the scope of the
> specialization and so substitution into e.g. the DECL_CONTEXT for
> 'value' yields access errors for Child::type since the friend
> declaration no longer applies.
> 
> It seems the appropriate access scope from which to perform partial
> specialization matching is the specialization itself (similar to how
> we check access of base-clauses), which is what this patch implements.

> There's implementation divergence however: Clang accepts both testcases
> below whereas MSVC and ICC reject both (indicating that Clang performs
> partial spec matching from the scope of the specialization and MSVC/ICC
> performs it from whatever scope the template-id appears).
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk?
> 
> 	PR c++/96204
> 
> gcc/cp/ChangeLog:
> 
> 	* pt.c (instantiate_class_template_1): Enter the scope of the
> 	type before calling most_specialized_partial_spec.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/template/access40.C: New test.
> 	* g++.dg/template/access40a.C: New test.
> ---
>   gcc/cp/pt.c                               |  6 ++++-
>   gcc/testsuite/g++.dg/template/access40.C  | 30 +++++++++++++++++++++++
>   gcc/testsuite/g++.dg/template/access40a.C | 30 +++++++++++++++++++++++
>   3 files changed, 65 insertions(+), 1 deletion(-)
>   create mode 100644 gcc/testsuite/g++.dg/template/access40.C
>   create mode 100644 gcc/testsuite/g++.dg/template/access40a.C
> 
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index f4e0abe5c1e..5107bfbf9d1 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -11774,8 +11774,12 @@ instantiate_class_template_1 (tree type)
>     deferring_access_check_sentinel acs (dk_no_deferred);
>   
>     /* Determine what specialization of the original template to
> -     instantiate.  */
> +     instantiate; do this relative to the scope of the type.  */
> +  push_access_scope (TYPE_NAME (type));
> +  pushclass (type);

How about replacing these two calls with push_nested_class (type), like 
we use later in the function?

>     t = most_specialized_partial_spec (type, tf_warning_or_error);
> +  popclass ();
> +  pop_access_scope (TYPE_NAME (type));
>     if (t == error_mark_node)
>       return error_mark_node;
>     else if (t)
> diff --git a/gcc/testsuite/g++.dg/template/access40.C b/gcc/testsuite/g++.dg/template/access40.C
> new file mode 100644
> index 00000000000..e0d30779377
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/template/access40.C
> @@ -0,0 +1,30 @@
> +// PR c++/96204
> +
> +template<bool> struct bool_constant;
> +
> +template<class, class = void>
> +struct has_type_member {
> +  static const bool value = false;
> +};
> +
> +template<class T>
> +struct has_type_member<T, typename T::type> {
> +  static const bool value = true;
> +};
> +
> +struct Parent;
> +
> +struct Child {
> +private:
> +  friend struct Parent;
> +  typedef void type;
> +};
> +
> +struct Parent {
> +  static void f() {
> +    // The partial specialization of has_type_member does not match
> +    // despite Child::type being accessible from the current scope.
> +    typedef bool_constant<has_type_member<Child>::value> type;
> +    typedef bool_constant<false> type;
> +  }
> +};
> diff --git a/gcc/testsuite/g++.dg/template/access40a.C b/gcc/testsuite/g++.dg/template/access40a.C
> new file mode 100644
> index 00000000000..85138c9e570
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/template/access40a.C
> @@ -0,0 +1,30 @@
> +// PR c++/96204
> +
> +template<bool> struct bool_constant;
> +
> +template<class, class = void>
> +struct has_type_member {
> +  static const bool value = false;
> +};
> +
> +template<class T>
> +struct has_type_member<T, typename T::type> {
> +  static const bool value = true;
> +};
> +
> +struct Parent;
> +
> +struct Child {
> +private:
> +  friend struct has_type_member<Child>;
> +  typedef void type;
> +};
> +
> +struct Parent {
> +  static void f() {
> +    // The partial specialization matches because Child::type is
> +    // accessible from has_type_member<Child>.
> +    typedef bool_constant<has_type_member<Child>::value> type;
> +    typedef bool_constant<true> type;
> +  }
> +};
> 


  parent reply	other threads:[~2021-06-25 15:50 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-06-25 15:03 Patrick Palka
2021-06-25 15:43 ` Patrick Palka
2021-06-25 15:50 ` Jason Merrill [this message]
2021-06-25 17:14   ` Patrick Palka
2021-06-25 20:25     ` Jason Merrill

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=6d414d65-3666-f17d-d5dc-1de7a9e4c929@redhat.com \
    --to=jason@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=ppalka@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).