aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/pt.cc3
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-friend11.C21
2 files changed, 24 insertions, 0 deletions
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 57917de..af96c5c 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 0000000..0350ac3
--- /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<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.