return TREE_TYPE (tmpl);
}
+ if (TMPL_PARMS_DEPTH (DECL_TEMPLATE_PARMS (friend_tmpl)) == 1)
+ /* The template has already been fully substituted, e.g. for
+
+ template <typename> friend class ::C;
+
+ so we can just return it directly. */
+ return TREE_TYPE (friend_tmpl);
+
tree context = CP_DECL_CONTEXT (friend_tmpl);
if (TREE_CODE (context) == NAMESPACE_DECL)
push_nested_namespace (context);
--- /dev/null
+// PR c++/115801
+// { dg-additional-options "-fmodules-ts -Wno-global-module" }
+// { dg-module-cmi test }
+
+module;
+
+template <typename T> struct GMF;
+template <typename T> struct GMF_Hidden {
+ int go() { GMF<T> gmf; return gmf.x; }
+};
+
+template <typename T> struct GMF {
+private:
+ template <typename> friend struct ::GMF_Hidden;
+ int x = 1;
+};
+
+template <typename T> int test_gmf() {
+ GMF_Hidden<T> h; return h.go();
+}
+
+export module test;
+
+export using ::GMF;
+export using ::test_gmf;
+
+export template <typename> struct Attached;
+template <typename T> struct Attached_Hidden {
+ int go() { Attached<T> attached; return attached.x; }
+};
+
+template <typename T> struct Attached {
+private:
+ template <typename> friend struct ::Attached_Hidden;
+ int x = 2;
+};
+
+export template <typename T> int test_attached() {
+ Attached_Hidden<T> h; return h.go();
+}
--- /dev/null
+// PR c++/115801
+// { dg-additional-options "-fmodules-ts" }
+
+import test;
+
+int main() {
+ GMF<int> gmf;
+ Attached<int> attached;
+
+ int a = test_gmf<double>();
+ int b = test_attached<double>();
+
+ GMF_Hidden<int> gmf_hidden; // { dg-error "not declared" }
+ Attached_Hidden<int> attached_hidden; // { dg-error "not declared" }
+}
+
+// { dg-prune-output "expected primary-expression" }
--- /dev/null
+// { dg-do compile }
+
+template<class T>
+struct A {
+ template<class U> struct B;
+
+ template<class U>
+ struct C {
+ template<class V> friend struct A::B;
+ private:
+ int x;
+ };
+};
+
+template <class T>
+template <class U>
+struct A<T>::B {
+ int foo(A<int*>::C<long> c) { return c.x; } // { dg-error "private" }
+};
+
+template struct A<int*>::C<long>;
+template struct A<int*>::B<long>; // { dg-bogus "" }
+template struct A<double*>::B<long>; // { dg-message "required from here" }