start_preparsed_function (member_function, NULL_TREE,
                                SF_PRE_PARSED | SF_INCLASS_INLINE);
 
-      /* Don't do access checking if it is a templated function.  */
-      if (processing_template_decl)
-       push_deferring_access_checks (dk_no_check);
-
       /* #pragma omp declare reduction needs special parsing.  */
       if (DECL_OMP_DECLARE_REDUCTION_P (member_function))
        {
        cp_parser_function_definition_after_declarator (parser,
                                                        /*inline_p=*/true);
 
-      if (processing_template_decl)
-       pop_deferring_access_checks ();
-
       /* Leave the scope of the containing function.  */
       if (function_scope)
        pop_function_context ();
 
       if (DECL_CLASS_SCOPE_P (scope)
          && friend_accessible_p (DECL_CONTEXT (scope), decl, type, otype))
        return 1;
+      /* Perhaps SCOPE is a friend function defined inside a class from which
+        DECL is accessible.  Checking this is necessary only when the class
+        is dependent, for otherwise add_friend will already have added the
+        class to SCOPE's DECL_BEFRIENDING_CLASSES.  */
+      if (tree fctx = DECL_FRIEND_CONTEXT (scope))
+       if (dependent_type_p (fctx)
+           && protected_accessible_p (decl, fctx, type, otype))
+         return 1;
     }
 
   /* Maybe scope's template is a friend.  */
 
     struct j {
        using c = int *;
     };
+public:
     using as = j::c;
 };
 template <typename> class k {
 
--- /dev/null
+// PR c++/58993
+// { dg-do compile }
+
+class base { void foo(); };
+
+template <class T>
+struct bar : public base {
+  void f1() {
+    &base::foo;  // { dg-error "private" }
+  }
+
+  template <class>
+  void f2() {
+    &base::foo;  // { dg-error "private" }
+  }
+
+  void f3();
+};
+
+template <class T>
+void bar<T>::f3() {
+  (void) &base::foo; // { dg-error "private" }
+}
+
+int main() {
+  bar<int>().f1();
+  bar<int>().f2<int>();
+  bar<int>().f3();
+}
 
--- /dev/null
+// { dg-do compile }
+
+template <class>
+struct S {
+  S();
+  friend int f(S x) { return x.i + x.j; }
+  template <class T>
+    friend int g(S x, T) { return x.i + x.j; }
+private:
+  int i;
+protected:
+  int j;
+};
 
--- /dev/null
+// { dg-do compile }
+
+struct A;
+
+struct B {
+  friend struct A;
+private:
+  static void f();
+protected:
+  static void g();
+};
+
+struct A {
+  friend void g(A) {
+    B::f(); // { dg-error "private" }
+    B::g(); // { dg-error "protected" }
+  }
+};