Regtested on x86_64-pc-linux-gnu.

This fix works, but I believe the real issue is that 
member_like_constrained_friend_p is incorrectly returning false because
DECL_TEMPLATE_INFO isn't set up for the friend before duplicate_decls is
called. I tried a few fixes to defer pushdecl_namespace_level after we
call build_template_info in push_template_decl, but they caused some
regressions. Suggestions on how i might fix this correctly?
(also, using && probably goes against [temp.friend]/9 requirements)

-- >8 --

function_requirements_equivalent_p was incorrectly treating a constrained
friend function template and its namespace-scope forward declaration as
having inequivalent requirements, causing an ambiguity error.

        PR c++/122550

gcc/cp/ChangeLog:

        * decl.cc (function_requirements_equivalent_p): Use && instead
        of || when checking member_like_constrained_friend_p.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp2a/concepts-friend18.C: New test.

Signed-off-by: Egas Ribeiro <[email protected]>
---
 gcc/cp/decl.cc                                 |  2 +-
 gcc/testsuite/g++.dg/cpp2a/concepts-friend18.C | 18 ++++++++++++++++++
 2 files changed, 19 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/concepts-friend18.C

diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 74c862ec1c7..689332363aa 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -1146,7 +1146,7 @@ function_requirements_equivalent_p (tree newfn, tree 
oldfn)
      same function as a declaration in any other scope."  So no need to
      actually compare the requirements.  */
   if (member_like_constrained_friend_p (newfn)
-      || member_like_constrained_friend_p (oldfn))
+      && member_like_constrained_friend_p (oldfn))
     return false;
 
   /* Compare only trailing requirements.  */
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-friend18.C 
b/gcc/testsuite/g++.dg/cpp2a/concepts-friend18.C
new file mode 100644
index 00000000000..5a6b0d67ef7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-friend18.C
@@ -0,0 +1,18 @@
+// PR c++/122550
+// { dg-do compile { target c++20 } }
+
+class Hasher;
+template <class a>
+concept C = true;
+
+template<C T>
+void add(Hasher&, T);
+
+struct Hasher {
+    template<C T>
+    friend void add(Hasher& hasher, T integer) {}
+};
+
+void f(Hasher& hasher, unsigned long integer) {
+  add(hasher, (unsigned int) integer);
+}
-- 
2.52.0

Reply via email to