diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 57917de321f09..af96c5ca25f72 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -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 diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-friend11.C b/gcc/testsuite/g++.dg/cpp2a/concepts-friend11.C new file mode 100644 index 0000000000000..0350ac3553e1b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/concepts-friend11.C @@ -0,0 +1,21 @@ +// CWG2596 +// { dg-do compile { target c++20 } } + +struct Base {}; + +int foo(Base&) { return 0; } // #0 + +template +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.