Compiling this well-formed program with -std=c++2a: namespace X { inline namespace Y { int swap; } template<class> struct S { friend void swap(S&, S&) {} }; } int main() { X::S<int> s1, s2; swap(s1, s2); } produces diagnostics (https://godbolt.org/g/ceWLxY): <source>:6:21: error: redefinition of 'swap' as different kind of symbol friend void swap(S&, S&) {} ^ <source>:11:15: note: in instantiation of template class 'X::S<int>' requested here X::S<int> s1, s2; ^ <source>:2:30: note: previous definition is here inline namespace Y { int swap; } ^ 1 error generated. Note that the program compiles successfully if S is replaced by a non-template class. Discussion on the CWG reflector verified that this program is well-formed, including Richard's statement "Oops, Clang's redeclaration check in the template instantiation case is incorrectly performing a redeclaration lookup as if for a qualified name here, rather than a redeclaration lookup for an unqualified name."
Eric, Marshall: this bug is likely to cause problems for the C++20 ranges library.
Any chance of getting this fixed for Clang 10? This will affect the STL soon. (I may have spent all of my bug points on #42694; I should have poked this bug first ;))
For posterity, this workaround seems to work portably (https://godbolt.org/z/q4fe1e): namespace X { #ifdef WORKAROUND namespace Y { int swap; } using namespace Y; #else inline namespace Y { int swap; } #endif template<class> struct S { friend void swap(S&, S&) {} }; } int main() { X::S<int> s1, s2; swap(s1, s2); }
Fixed in trunk. Hans, is it too late for the 11.0 release? Should we target this at 11.0.1 instead?
(In reply to Richard Smith from comment #4) > Fixed in trunk. > > Hans, is it too late for the 11.0 release? Should we target this at 11.0.1 > instead? Seems okay for 11. I've cherry-picked it as c160ff1564d8047c852f54d64ba4e9a81d080cac.