public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c++: access scope during partial spec matching [PR96204]
@ 2021-06-25 15:03 Patrick Palka
  2021-06-25 15:43 ` Patrick Palka
  2021-06-25 15:50 ` Jason Merrill
  0 siblings, 2 replies; 5+ messages in thread
From: Patrick Palka @ 2021-06-25 15:03 UTC (permalink / raw)
  To: gcc-patches

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);
   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;
+  }
+};
-- 
2.32.0.93.g670b81a890


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] c++: access scope during partial spec matching [PR96204]
  2021-06-25 15:03 [PATCH] c++: access scope during partial spec matching [PR96204] Patrick Palka
@ 2021-06-25 15:43 ` Patrick Palka
  2021-06-25 15:50 ` Jason Merrill
  1 sibling, 0 replies; 5+ messages in thread
From: Patrick Palka @ 2021-06-25 15:43 UTC (permalink / raw)
  To: Patrick Palka; +Cc: gcc-patches, jason

On Fri, 25 Jun 2021, 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

Er, this should say has_type_method<Child>.

> 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);

D'oh, this pair of calls is equivalent to push_nested_class; consider
this hunk replaced by a single call to push_nested_class(type).

>    t = most_specialized_partial_spec (type, tf_warning_or_error);
> +  popclass ();
> +  pop_access_scope (TYPE_NAME (type));

Likewise consider this replaced with pop_nested_class().

>    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;
> +  }
> +};
> -- 
> 2.32.0.93.g670b81a890
> 
> 


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] c++: access scope during partial spec matching [PR96204]
  2021-06-25 15:03 [PATCH] c++: access scope during partial spec matching [PR96204] Patrick Palka
  2021-06-25 15:43 ` Patrick Palka
@ 2021-06-25 15:50 ` Jason Merrill
  2021-06-25 17:14   ` Patrick Palka
  1 sibling, 1 reply; 5+ messages in thread
From: Jason Merrill @ 2021-06-25 15:50 UTC (permalink / raw)
  To: Patrick Palka, gcc-patches

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


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] c++: access scope during partial spec matching [PR96204]
  2021-06-25 15:50 ` Jason Merrill
@ 2021-06-25 17:14   ` Patrick Palka
  2021-06-25 20:25     ` Jason Merrill
  0 siblings, 1 reply; 5+ messages in thread
From: Patrick Palka @ 2021-06-25 17:14 UTC (permalink / raw)
  To: Jason Merrill; +Cc: Patrick Palka, gcc-patches

On Fri, 25 Jun 2021, Jason Merrill wrote:

> 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?

That works nicely.  Would the patch be OK with that change?
Bootstrapped and regtested on x86_64-pc-linux-gnu.

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


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] c++: access scope during partial spec matching [PR96204]
  2021-06-25 17:14   ` Patrick Palka
@ 2021-06-25 20:25     ` Jason Merrill
  0 siblings, 0 replies; 5+ messages in thread
From: Jason Merrill @ 2021-06-25 20:25 UTC (permalink / raw)
  To: Patrick Palka; +Cc: gcc-patches

On 6/25/21 1:14 PM, Patrick Palka wrote:
> On Fri, 25 Jun 2021, Jason Merrill wrote:
> 
>> 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?
> 
> That works nicely.  Would the patch be OK with that change?
> Bootstrapped and regtested on x86_64-pc-linux-gnu.

OK with that and the matching change...

>>>      t = most_specialized_partial_spec (type, tf_warning_or_error);
>>> +  popclass ();
>>> +  pop_access_scope (TYPE_NAME (type));

...here.

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


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2021-06-25 20:25 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-25 15:03 [PATCH] c++: access scope during partial spec matching [PR96204] Patrick Palka
2021-06-25 15:43 ` Patrick Palka
2021-06-25 15:50 ` Jason Merrill
2021-06-25 17:14   ` Patrick Palka
2021-06-25 20:25     ` Jason Merrill

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).