@@ -11284,6 +11284,9 @@ tsubst_friend_function (tree decl, tree args)
not_tmpl = DECL_TEMPLATE_RESULT (new_friend);
new_friend_result_template_info = DECL_TEMPLATE_INFO (not_tmpl);
}
+ else if (!constraints_satisfied_p (new_friend))
+ /* Only define a constrained hidden friend when satisfied. */
+ return error_mark_node;
/* Inside pushdecl_namespace_level, we will push into the
current namespace. However, the friend function should go
new file mode 100644
@@ -0,0 +1,21 @@
+// CWG2596
+// { dg-do compile { target c++20 } }
+
+struct Base {};
+
+int foo(Base&) { return 0; } // #0
+
+template<int N>
+struct S : Base {
+ friend int foo(Base&) requires (N == 1) { return 1; } // #1
+ // friend int foo(Base&) requires (N == 2) { return 3; } // #2
+};
+
+S<1> s1;
+S<2> s2; // OK, no conflict between #1 and #0
+int x = foo(s1); // { dg-error "ambiguous" }
+int y = foo(s2); // OK, selects #0
+
+// ??? currently the foos all mangle the same, so comment out #2
+// and only test that #1 isn't multiply defined and overloads with #0.
+// The 2596 example does not include #0 and expects both calls to work.