Clang Bug or Not-to-Spec C++ Question

I found another case where clang doesn't work with a piece of code but gcc and Visual C++ do.

#include <iostream>
#include <string>

class foo {
    foo(std::string string) : string_(string) {}
    friend inline std::ostream & operator<<(std::ostream & os, foo const & f) {
        os << f.string_;
        return os;
    std::string string_;

// commenting the next line out allows linking to work
std::ostream & operator<<(std::ostream & os, foo const & f);

int main(void) {
    foo f("Hello World!");
    std::cout << f << std::endl;
    return 0;

In this case, the error comes up at link time:

clang -lstdc++
/tmp/cc-D9nHGS.o: In function `main': undefined reference to `operator<<(std::basic_ostream<char, std::char_traits<char> >&, foo const&)'
collect2: ld returned 1 exit status
clang: error: linker (via gcc) command failed with exit code 1 (use -v to see invocation)

It seems as if the operator declaration outside the class is making clang think the operator will be implemented elsewhere, ignoring the implementation inside the class declaration. As noted, removing the outside operator declaration allows everything to work, both with gcc and clang. The question is whether the outside operator declaration is against the C++ spec clang implements, or whether clang isn't dealing with it correctly.



This is (another) shade of the bug reported here:

and, in general, Clang has some interesting ordering issues with linking up declarations of friends in classes (particularly, class templates) with declarations outside of the class. If you could add this example (hopefully reduced to not involve any C++ headers!) to that bug, it would help us test when someone tackles the general issue.

  - Doug