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 -----------------------