https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77306
Bug ID: 77306 Summary: Unable to specify visibility for explicit template instantiations Product: gcc Version: 7.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: abbeyj+gcc at gmail dot com Target Milestone: --- Created attachment 39477 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=39477&action=edit Reproducer This bug is being filed as a request for a more limited form of attributes than that which was rejected in bug #71154. That bug requested any attribute be allowed on an explicit template instantiation. This bug limits the scope to just __attribute__((visibility)) which should hopefully be more acceptable. The visibility attribute is somewhat different from other attributes in that it doesn't affect the layout or semantics of the type. Trying to apply a visibility("default") attribute to an explicit template instantiation does not work if the type has been previously mentioned in the translation unit. STR: ====== $ cat main.cpp template <typename T> class C { void foo(); }; C<int> g_c_int; C<double> g_c_double; template <typename T> void C<T>::foo() {} template class __attribute__((visibility("default"))) C<int>; template class C<double>; $ g++ -fvisibility=hidden -fPIC -shared main.cpp -o main.so main.cpp:13:55: warning: type attributes ignored after type is already defined [-Wattributes] template class __attribute__((visibility("default"))) C<int>; ^~~~~~ $ nm -C main.so | grep foo 000000000000061c t C<double>::foo() 0000000000000610 t C<int>::foo() ====== Note that C<int>::foo() is marked as local (lowercase t) when the intent was to make it global (uppercase). When compiled with clang++ instead there are no warnings and nm reports: 0000000000000510 t C<double>::foo() 0000000000000500 W C<int>::foo() where C<int>::foo() is global as desired. Similar code, with the __attribute__ replaced with __declspec(dllexport), works as expected with MSVC 2012. That is, C<int>::foo() is exported from the DLL and C<double>::foo() is not. I have a patch for this which I will attach. It relaxes the existing check to allow attributes on a type that has already been defined as long as the attribute is a visibility attribute.