Bug 89088 - Dllexport for explicit template instantiation missing inline methods
Summary: Dllexport for explicit template instantiation missing inline methods
Status: UNCONFIRMED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 8.2.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: link-failure
Depends on:
Blocks:
 
Reported: 2019-01-28 11:57 UTC by Martin Storsjö
Modified: 2021-03-23 21:16 UTC (History)
2 users (show)

See Also:
Host:
Target: *-*-mingw*
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
Sample code showing the issue (741 bytes, application/zip)
2019-01-28 11:57 UTC, Martin Storsjö
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Martin Storsjö 2019-01-28 11:57:55 UTC
Created attachment 45538 [details]
Sample code showing the issue

With dllexported explicit template instantiation, inline methods aren't exported, but callers still create undefined references to the inline methods, which fail due to the missing export. (This can be remedied by applying -Wl,--export-all-symbols to export all generated symbols, regardless of dllexport attributes.)

Example:

header.h:
template <class T> struct C {
  void f();
  void g() {}
};

template <class T> void C<T>::f() {}

extern template class
#ifdef DLLEXPORT
__declspec(dllexport)
#elif defined(DLLIMPORT)
__declspec(dllimport)
#endif
C<char>;

lib.cpp:
#define DLLEXPORT
#include "header.h"

template class C<char>;

caller.cpp:
#define DLLIMPORT
#include "header.h"

int main(int argc, char* argv[]) {
  C<char> a;
  a.g();
  return 0;
}

Building of this fails in this way:
$ make
x86_64-w64-mingw32-g++    -c -o caller.o caller.cpp
x86_64-w64-mingw32-g++    -c -o lib.o lib.cpp
x86_64-w64-mingw32-g++ -shared -o lib.dll lib.o -Wl,--out-implib,liblib.dll.a
x86_64-w64-mingw32-g++ -o caller.exe caller.o -L. -llib
caller.o:caller.cpp:(.text+0x1c): undefined reference to `C<char>::g()'
collect2: error: ld returned 1 exit status
Makefile:5: recipe for target 'caller.exe' failed
make: *** [caller.exe] Error 1


The instantiation definition in lib.cpp emitted both methods, but only export the non-inline method:
$ x86_64-w64-mingw32-nm lib.o 
<snip>
0000000000000000 T _ZN1CIcE1fEv
0000000000000000 T _ZN1CIcE1gEv
$ x86_64-w64-mingw32-objdump -s lib.o
<snip>
Contents of section .drectve:
 0000 202d6578 706f7274 3a225f5a 4e314349   -export:"_ZN1CI
 0010 63453166 45762200                    cE1fEv".        

However, despite this, the caller creates an undefined reference to the inline method:
$ x86_64-w64-mingw32-nm caller.o 
<snip>
0000000000000000 T main
                 U _ZN1CIcE1gEv
Comment 1 Martin Storsjö 2019-04-26 19:52:52 UTC
FWIW, Clang (when operating in MinGW mode, where it tries to follow what GCC does) also had the same issue. There this issue was fixed by making dllexport export inline methods as well, for template instantiations: https://github.com/llvm-project/clang/commit/2061b0cab0002c264af632bf5e6ba5306c589c94