https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92914

            Bug ID: 92914
           Summary: Hidden visibility incompatible with extern'd
                    specialized explicit template instantiations
           Product: gcc
           Version: 10.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: steveire at gmail dot com
  Target Milestone: ---

I'm trying to use hidden visibility with a library which is already used with
MSVC. It uses exported explicit template specializations.

mylib.h:-------------
#pragma once

#if _MSC_VER
#  ifdef mylib_EXPORTS
#    define MYLIB_EXPORT __declspec(dllexport)
#  else
#    define MYLIB_EXPORT __declspec(dllimport)
#  endif
#else
#  ifdef mylib_EXPORTS
#    define MYLIB_EXPORT __attribute__((visibility("default")))
#  else
#    define MYLIB_EXPORT
#  endif
#endif

template<typename T>
class Templ
{
public:
    T getNum() const;
    T getAnotherNum() const;
};
#ifdef SPECIALIZE_INT
template<> MYLIB_EXPORT int Templ<int>::getNum() const;
#endif

#ifndef mylib_EXPORTS
extern template class Templ<int>;
extern template class Templ<float>;
#endif
-----------------


mylib.cpp---------

#include "mylib.h"

template<typename T>
T Templ<T>::getNum() const
{
    return 7;
}

template<typename T>
T Templ<T>::getAnotherNum() const
{
    return 5;
}

#ifdef SPECIALIZE_INT
template<>
int Templ<int>::getNum() const
{
    return 42;
}
#endif

template class MYLIB_EXPORT Templ<int>;
template class MYLIB_EXPORT Templ<float>;
-----------------

main.cpp--------------

#include "mylib.h"

#include <iostream>

int main()
{
    Templ<int> ti;
    Templ<float> tf;
    std::cout
        << ti.getNum() << " -- " << ti.getAnotherNum()
        << tf.getNum() << " -- " << tf.getAnotherNum() << std::endl;
    return 0;
}
---------------------


build.sh--------------
#!/bin/sh
set -x

COMPILE_DRIVER=g++
COMPILE_DRIVER=clang++

$COMPILE_DRIVER -Dmylib_EXPORTS  -fPIC -fvisibility=hidden
-fvisibility-inlines-hidden -o mylib.$COMPILE_DRIVER.o -c ../mylib.cpp
$COMPILE_DRIVER -fPIC   -Wl,--no-undefined -shared -o libmylib.so
mylib.$COMPILE_DRIVER.o
$COMPILE_DRIVER -fvisibility=hidden -fvisibility-inlines-hidden -o
main.$COMPILE_DRIVER.o -c ../main.cpp
$COMPILE_DRIVER main.$COMPILE_DRIVER.o  -o myexe  -Wl,-rpath,$PWD libmylib.so

# Compile with SPECIALIZE_INT defined:

$COMPILE_DRIVER -DSPECIALIZE_INT -Dmylib_EXPORTS  -fPIC -fvisibility=hidden
-fvisibility-inlines-hidden -o mylib.$COMPILE_DRIVER.o -c ../mylib.cpp
$COMPILE_DRIVER -fPIC   -Wl,--no-undefined -shared -o libmylib.so
mylib.$COMPILE_DRIVER.o
$COMPILE_DRIVER -DSPECIALIZE_INT -fvisibility=hidden
-fvisibility-inlines-hidden -o main.$COMPILE_DRIVER.o -c ../main.cpp
$COMPILE_DRIVER main.$COMPILE_DRIVER.o  -o myexe  -Wl,-rpath,$PWD libmylib.so
-----------------------



clang ---------------
+ clang++ -Dmylib_EXPORTS -fPIC -fvisibility=hidden -fvisibility-inlines-hidden
-o mylib.clang++.o -c ../mylib.cpp
+ clang++ -fPIC -Wl,--no-undefined -shared -o libmylib.so mylib.clang++.o
+ clang++ -fvisibility=hidden -fvisibility-inlines-hidden -o main.clang++.o -c
../main.cpp
+ clang++ main.clang++.o -o myexe
-Wl,-rpath,/home/stephen/dev/src/playground/cpp/build libmylib.so
+ clang++ -DSPECIALIZE_INT -Dmylib_EXPORTS -fPIC -fvisibility=hidden
-fvisibility-inlines-hidden -o mylib.clang++.o -c ../mylib.cpp
+ clang++ -fPIC -Wl,--no-undefined -shared -o libmylib.so mylib.clang++.o
+ clang++ -DSPECIALIZE_INT -fvisibility=hidden -fvisibility-inlines-hidden -o
main.clang++.o -c ../main.cpp
+ clang++ main.clang++.o -o myexe
-Wl,-rpath,/home/stephen/dev/src/playground/cpp/build libmylib.so
---------------------------

While this works with clang above, it does not work with GCC:

gcc -------------------
+ g++ -Dmylib_EXPORTS -fPIC -fvisibility=hidden -fvisibility-inlines-hidden -o
mylib.g++.o -c ../mylib.cpp
+ g++ -fPIC -Wl,--no-undefined -shared -o libmylib.so mylib.g++.o
+ g++ -fvisibility=hidden -fvisibility-inlines-hidden -o main.g++.o -c
../main.cpp
+ g++ main.g++.o -o myexe -Wl,-rpath,/home/stephen/dev/src/playground/cpp/build
libmylib.so
+ g++ -DSPECIALIZE_INT -Dmylib_EXPORTS -fPIC -fvisibility=hidden
-fvisibility-inlines-hidden -o mylib.g++.o -c ../mylib.cpp
../mylib.cpp:24:29: warning: type attributes ignored after type is already
defined [-Wattributes]
 template class MYLIB_EXPORT Templ<int>;
                             ^~~~~~~~~~
+ g++ -fPIC -Wl,--no-undefined -shared -o libmylib.so mylib.g++.o
+ g++ -DSPECIALIZE_INT -fvisibility=hidden -fvisibility-inlines-hidden -o
main.g++.o -c ../main.cpp
+ g++ main.g++.o -o myexe -Wl,-rpath,/home/stephen/dev/src/playground/cpp/build
libmylib.so
main.g++.o: In function `main':
main.cpp:(.text+0x4c): undefined reference to `Templ<int>::getAnotherNum()
const'
collect2: error: ld returned 1 exit status

-----------------------

Reply via email to