Some libstdc++ tests were failing with import std because ADL didn't find
rethrow_exception, even though it's a friend. The problem turned out to be
because it's not in the same namespace, and in C++17 ADL only makes hidden
friends visible. But in C++20 P1787 changed [basic.lookup.argdep]/4.2 to
directly include all friends in the lookup.
Note that my change still excludes class members, even though the standard
doesn't specify that; including implicit object member functions would just
break, and even foreign static/xobj member functions seem like they would be
strange to include.
gcc/cp/ChangeLog:
* name-lookup.cc (name_lookup::adl_class_fns): Include all
namespace-scope friends.
gcc/testsuite/ChangeLog:
* g++.dg/lookup/koenig16.C: New test.
{
tree fn = TREE_VALUE (friends);
- /* Only interested in global functions with potentially hidden
- (i.e. unqualified) declarations. */
+ /* Before C++20, ADL just makes hidden friends visible, so we
+ only include functions in the same namespace. After C++20,
+ include all namespace-scope functions. */
if (!context)
context = decl_namespace_context (type);
- if (CP_DECL_CONTEXT (fn) != context)
+ if (cxx_dialect < cxx20
+ ? CP_DECL_CONTEXT (fn) != context
+ : !DECL_NAMESPACE_SCOPE_P (fn))
continue;
dedup (true);
--- /dev/null
+// Before P1787 (C++20), only hidden friends are included in ADL.
+// After P1787, all friends are included.
+
+namespace N {
+ namespace NN {
+ struct A;
+ }
+ using NN::A;
+ void fn (A);
+ namespace NN {
+ struct A {
+ friend void N::fn (A);
+ };
+ }
+ void fn (A) { }
+}
+
+int main()
+{
+ N::A a;
+ fn(a); // { dg-error "not declared" "" { target c++17_down } }
+}
--- /dev/null
+// Before P1787 (C++20), only hidden friends are included in ADL.
+// After P1787, all friends are included.
+
+// { dg-additional-options "-fmodules -Wno-global-module" }
+
+export module M;
+
+namespace N {
+ namespace NN {
+ export struct A;
+ }
+ export using NN::A;
+
+ export void fn (A);
+
+ namespace NN {
+ struct A {
+ friend void N::fn (A);
+ };
+ }
+}
--- /dev/null
+// Before P1787 (C++20), only hidden friends are included in ADL.
+// After P1787, all friends are included.
+
+// { dg-additional-options -fmodules }
+
+import M;
+
+int main()
+{
+ N::A a;
+ fn(a); // { dg-error "not declared" "" { target c++17_down } }
+}