For the following: #pragma GCC visibility push(hidden) template<class T> class __attribute__((__visibility__("default"))) foo; class bar { template<class T> friend class foo; }; clang emits the following error: t.cpp:1:13: error: visibility does not match previous declaration #pragma GCC visibility push(hidden) ^ t.cpp:2:40: note: previous attribute is here template<class T> class __attribute__((__visibility__("default"))) foo; ^ 1 error generated. Not only does the error point to the incorrect location (see bug 13658), but it also seems to be wrong. At least, r160105 doesn't complain about it, while r160495 does (I'm still bisecting). The sample has been reduced from the following, something which Firefox apparently does, and which now doesn't work with libc++: #pragma GCC visibility push(hidden) #include <iterator> In libc++ <iterator>, it first includes at least one forward declaration of basic_string with a default visibility attribute, and then follows: template <class _Iter> class __wrap_iter { ... template <class _CharT, class _Traits, class _Alloc> friend class basic_string; And this now causes an error with clang trunk.
Note also that the testcase with the templates removed, e.g.: #pragma GCC visibility push(hidden) class __attribute__((__visibility__("default"))) foo; class bar { friend class foo; }; compiles without error. Apparently the visibility isn't a problem then...
I will take a look.
Fixed in r162360.