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