The following code which doesn\'t compile under clang but does under gcc and VS:
template class bar;
namespace NS
{
template
I believe that clang is correct. According to [namespace.memdef]/3:
Every name first declared in a namespace is a member of that namespace. If a
frienddeclaration in a non-local class first declares a class, function, class template or function template the friend is a member of the innermost enclosing namespace.
In your case, the name wouldn't appear to be "first declared" by the friend declaration. Later in that paragraph, however, emphasis mine:
If the name in a
frienddeclaration is neither qualified nor a template-id and the declaration is a function or an elaborated-type-specifier, the lookup to determine whether the entity has been previously declared shall not consider any scopes outside the innermost enclosing namespace.
That is, this declaration:
template friend class bar;
will not look for bar outside of namespace NS, so it will not find your earlier declaration. As such, it declares a class template NS::bar to be a friend of foo. You will have to qualify the name bar in order for it to be found:
template friend class ::bar;
This seems related to GCC Bug 37804.