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.

Reply via email to