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