aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/pt.c5
-rw-r--r--gcc/testsuite/g++.dg/template/access40.C28
-rw-r--r--gcc/testsuite/g++.dg/template/access40a.C28
3 files changed, 60 insertions, 1 deletions
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e5a2a2c..f2039e0 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 0000000..d035e99
--- /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 0000000..94025c5
--- /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];
+ }
+};