diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 77bcf046608..b8035b4360d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7832,6 +7832,7 @@ extern void remove_constraints                  (tree);
 extern tree current_template_constraints	(void);
 extern tree associate_classtype_constraints     (tree);
 extern tree build_constraints                   (tree, tree);
+extern tree maybe_substitute_reqs_for		(tree, const_tree);
 extern tree get_template_head_requirements	(tree);
 extern tree get_trailing_function_requirements	(tree);
 extern tree get_shorthand_constraints           (tree);
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 823604afb89..cda644eabe2 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -1189,6 +1189,29 @@ remove_constraints (tree t)
     decl_constraints->remove (t);
 }
 
+/* If DECL is a friend, substitute into REQS to produce requirements suitable
+   for declaration matching.  */
+
+tree
+maybe_substitute_reqs_for (tree reqs, const_tree decl_)
+{
+  if (reqs == NULL_TREE)
+    return NULL_TREE;
+  tree decl = CONST_CAST_TREE (decl_);
+  tree result = STRIP_TEMPLATE (decl);
+  if (DECL_FRIEND_P (result))
+    {
+      tree tmpl = decl == result ? DECL_TI_TEMPLATE (result) : decl;
+      tree gargs = generic_targs_for (tmpl);
+      processing_template_decl_sentinel s;
+      if (uses_template_parms (gargs))
+	++processing_template_decl;
+      reqs = tsubst_constraint (reqs, gargs,
+				tf_warning_or_error, NULL_TREE);
+    }
+  return reqs;
+}
+
 /* Returns the template-head requires clause for the template
    declaration T or NULL_TREE if none.  */
 
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 98ed79f3579..e55de5dd53d 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -942,6 +942,8 @@ function_requirements_equivalent_p (tree newfn, tree oldfn)
   tree reqs2 = get_trailing_function_requirements (oldfn);
   if ((reqs1 != NULL_TREE) != (reqs2 != NULL_TREE))
     return false;
+  reqs1 = maybe_substitute_reqs_for (reqs1, newfn);
+  reqs2 = maybe_substitute_reqs_for (reqs2, oldfn);
   return cp_tree_equal (reqs1, reqs2);
 }
 
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 209044135cb..45c204e4269 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10834,29 +10834,12 @@ tsubst_friend_function (tree decl, tree args)
       DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (new_friend))
 	= DECL_SAVED_TREE (DECL_TEMPLATE_RESULT (decl));
 
-      /* Attach the template requirements to the new declaration
-         for declaration matching. We need to rebuild the requirements
-         so that parameter levels match.  */
-      if (tree ci = get_constraints (decl))
-	{
-	  tree parms = DECL_TEMPLATE_PARMS (new_friend);
-	  tree args = generic_targs_for (new_friend);
-	  tree treqs = tsubst_constraint (CI_TEMPLATE_REQS (ci), args,
-					  tf_warning_or_error, NULL_TREE);
-	  tree freqs = tsubst_constraint (CI_DECLARATOR_REQS (ci), args,
-					  tf_warning_or_error, NULL_TREE);
-
-	  /* Update the constraints -- these won't really be valid for
-	     checking, but that's not what we need them for. These ensure
-	     that the declared function can find the friend during
-	     declaration matching.  */
-	  tree new_ci = get_constraints (new_friend);
-	  CI_TEMPLATE_REQS (new_ci) = treqs;
-	  CI_DECLARATOR_REQS (new_ci) = freqs;
-
-	  /* Also update the template parameter list.  */
-	  TEMPLATE_PARMS_CONSTRAINTS (parms) = treqs;
-	}
+      /* Substitute TEMPLATE_PARMS_CONSTRAINTS so that parameter levels will
+	 match in decls_match.  */
+      tree parms = DECL_TEMPLATE_PARMS (new_friend);
+      tree treqs = TEMPLATE_PARMS_CONSTRAINTS (parms);
+      treqs = maybe_substitute_reqs_for (treqs, new_friend);
+      TEMPLATE_PARMS_CONSTRAINTS (parms) = treqs;
     }
 
   /* The mangled name for the NEW_FRIEND is incorrect.  The function
@@ -13225,6 +13208,8 @@ tsubst_template_parms (tree parms, tree args, tsubst_flags_t complain)
 	tree_cons (size_int (TMPL_PARMS_DEPTH (parms)
 			     - TMPL_ARGS_DEPTH (args)),
 		   new_vec, NULL_TREE);
+      TEMPLATE_PARMS_CONSTRAINTS (*new_parms)
+	= TEMPLATE_PARMS_CONSTRAINTS (parms);
     }
 
   --processing_template_decl;
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-friend3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-friend3.C
index 4f49358ed7d..4278278b9df 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-friend3.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-friend3.C
@@ -4,6 +4,7 @@ template <class T> concept True = true;
 
 template <True U> struct B { int i = ++U::x; };
 template <True U> void f() { ++U::x; }
+template <class U> void g() requires True<U> { ++U::x; }
 
 template <class V> class C
 {
@@ -11,10 +12,12 @@ template <class V> class C
 
   template <True U> friend struct B;
   template <True U> friend void f();
+  template <class U> friend void g() requires True<U>;
 };
 
 int main()
 {
   f<C<int>>();
+  g<C<int>>();
   B<C<int>>();
 }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-friend5.C b/gcc/testsuite/g++.dg/cpp2a/concepts-friend5.C
new file mode 100644
index 00000000000..394f141bf17
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-friend5.C
@@ -0,0 +1,8 @@
+// PR c++/93400
+// { dg-do compile { target concepts } }
+
+template <typename> bool a = true;
+template <typename i> concept b = a<i>;
+template <int> struct f { template <b c> friend auto g(c, f); };
+auto d = f<1>{};
+auto e = f<0>{};
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84140.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84140.C
index d901ab20cbf..83a9083cf17 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84140.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84140.C
@@ -1,14 +1,13 @@
 // { dg-do run { target c++2a } }
-// { dg-additional-options "-fconcepts-ts" }
 
 template<class, class> constexpr bool is_same_v = false;
 template<class T> constexpr bool is_same_v<T, T> = true;
 
 template<class T, class U>
-concept bool Same = is_same_v<T, U>;
+concept Same = is_same_v<T, U>;
 
 template<class T, class U>
-concept bool Diff = requires(T& t, U& u) { u - t; };
+concept Diff = requires(T& t, U& u) { u - t; };
 
 template<class I, class S>
 int distance(I, S) { return 0; }
