Forward declaration of inline operator overload within class member causes linker error


Consider the following code:

struct Foo {
    float f;
    Foo& operator+=(Foo rhs) {
        Foo operator+(Foo, Foo);
        *this = *this + rhs;
        return *this;

inline Foo operator+(Foo lhs, Foo rhs) {
    return Foo{lhs.f + rhs.f};

If and only if operator+(Foo, Foo) is inline, GCC and MSVC give "undefined reference to operator+(Foo, Foo)" linker errors, while Clang has no issues. See here for a live example.

I would presume this code is valid; the inline-ness of the function should have no effect, since the function should not need to be declared as inline if it’s defined as inline (and anyway, a function cannot be declared inline at block scope).
Note that if operator+(Foo, Foo) is instead declared (as non-inline) before the definition of Foo, it is accepted by all 3 compilers.

However, such issues as linkage are tricky within the Standard, so I’m aware it could also be undefined behaviour or "ill-formed, no diagnostic required" and GCC and MSVC just happen to give errors.

So is this code valid? Which compiler is correct?

Source: Windows Questions C++