llvm-project
llvm-project copied to clipboard
accessing member in trailing return type of locally defined friend function triggers error with clang
Example code as below or on Godbolt. All friend functions compile with GCC and Visual Studio. Clang fails when trying to access S<T>::foo()
in trailing return type. The question could also be found on StackOverflow.
#include <concepts>
template<typename T>
struct S {
T m_t;
T const& foo() const& { return m_t; }
auto mem_fn_trailing_return(S const& s) -> decltype(s.foo()) {
return s.foo();
}
friend auto bar_auto(S const& s) {
return s.foo();
}
friend decltype(auto) bar_decltype_auto(S const& s) {
return s.foo();
}
friend decltype(auto) bar_requires(S const& s) requires std::same_as<T const&, decltype(s.foo())> {
return s.foo();
}
friend auto bar_trailing_return(S const& s) -> decltype(s.foo()) { // clang error: member access into incomplete type 'const S<int>'
return s.foo();
}
};
S<int> s{1};
According to expr.ref#4:
Otherwise, the object expression shall be of class type. The class type shall be complete unless the class member access appears in the definition of that class. [Note 3: The program is ill-formed if the result differs from that when the class is complete ([class.member.lookup]). — end note] [Note 4: [basic.lookup.qual] describes how names are looked up after the . and -> operators. — end note]
The class member access in trailing return type of a locally defined friend function does appear in the definition of that class. IMO Clang should allow it.
@llvm/issue-subscribers-clang-frontend
We have some other bugs around complete class contexts: https://github.com/llvm/llvm-project/issues/58245
In a trailing-return-type, the class being defined is not required to be complete for purposes of class member access