public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r12-1829] c++: access scope during partial spec matching [PR96204]
@ 2021-06-26 15:08 Patrick Palka
  0 siblings, 0 replies; only message in thread
From: Patrick Palka @ 2021-06-26 15:08 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:9f26e34a5a9614a5b66f146752ecef9ea67b3e2d

commit r12-1829-g9f26e34a5a9614a5b66f146752ecef9ea67b3e2d
Author: Patrick Palka <ppalka@redhat.com>
Date:   Sat Jun 26 11:05:54 2021 -0400

    c++: access scope during partial spec matching [PR96204]
    
    Here, when determining whether the partial specialization matches
    has_type_member<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 of has_type_member::value fails
    with access errors since the friend declaration that we relied on to
    choose the partial specialization 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.
    
            PR c++/96204
    
    gcc/cp/ChangeLog:
    
            * pt.c (instantiate_class_template_1): Enter the scope of the
            type when calling most_specialized_partial_spec.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/template/access40.C: New test.
            * g++.dg/template/access40a.C: New test.

Diff:
---
 gcc/cp/pt.c                               |  5 ++++-
 gcc/testsuite/g++.dg/template/access40.C  | 28 ++++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/template/access40a.C | 28 ++++++++++++++++++++++++++++
 3 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e5a2a2cd525..f2039e09cd7 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -11769,8 +11769,11 @@ 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 class for
+     sake of access checking.  */
+  push_nested_class (type);
   t = most_specialized_partial_spec (type, tf_warning_or_error);
+  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..d035e99e462
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/access40.C
@@ -0,0 +1,28 @@
+// PR c++/96204
+
+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 does not match despite Child::type
+    // being accessible from the current scope.
+    extern int x[1];
+    extern int x[!has_type_member<Child>::value];
+  }
+};
diff --git a/gcc/testsuite/g++.dg/template/access40a.C b/gcc/testsuite/g++.dg/template/access40a.C
new file mode 100644
index 00000000000..94025c513b7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/access40a.C
@@ -0,0 +1,28 @@
+// PR c++/96204
+
+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 has_type_member<Child>
+    // is a friend of Child.
+    extern int x[1];
+    extern int x[has_type_member<Child>::value];
+  }
+};


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2021-06-26 15:08 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-26 15:08 [gcc r12-1829] c++: access scope during partial spec matching [PR96204] Patrick Palka

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