https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111018
Bug ID: 111018 Summary: lexical interpretation of friendship rules depends on whether the friend function has a definition Product: gcc Version: 14.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: eric.niebler at gmail dot com Target Milestone: --- Starting in gcc 12, transitive friendship is extended to friend functions that are defined lexically within the body of the friend class. E.g.: struct S; struct T { friend struct S; private: template <class T> static void foo(T) {} }; struct S { template <class Self> friend auto bar(Self s) -> decltype(::T::foo(s)) { // (1) return ::T::foo(s); } }; Prior to gcc-12, the commented line would have been rejected, but now it is accepted. Great, it brings gcc in line with clang and is arguably more sensible. HOWEVER, it does NOT work if the friend function is merely declared but not defined. For instance, this is still an error: struct S; struct T { friend struct S; private: template <class T> static void foo(T) {} }; struct S { template <class Self> friend auto bar(Self s) -> decltype(::T::foo(s)); // NO FN DEFINITION }; int main() { S s; using T = decltype(bar(s)); // ERROR: T::foo is private } This is very confusing and inconsistent behavior. See: https://godbolt.org/z/WT9P37Wba