Alexey, Is that patch really correct? On 06.01.21 16:45, Richard B. Kreckel via GiNaC-devel wrote:
commit c3195f0b5a7ac9fdbfdd04e5f4acf6a836063de0 Author: Alexey Sheplyakov <asheplyakov@altlinux.org> Date: Wed Jan 6 11:20:46 2021 +0400
Avoid multiple definitions of `lst::info` (MinGW compile fix)
[55/59] Linking CXX shared library bin/libginac.dll FAILED: bin/libginac.dll ginac/libginac.dll.a [skipped long list of object files] /usr/bin/x86_64-w64-mingw32-ld: ginac/CMakeFiles/ginac.dir/lst.cpp.obj: in function `GiNaC::ptr<GiNaC::basic>::~ptr()': /home/asheplyakov/work/sw/ginac/_build_w64/../ginac/container.h:150: multiple definition of `GiNaC::container<std::__cxx11::list>::info(unsigned int) const'; ginac/CMakeFiles/ginac.dir/integration_kernel.cpp.obj:/home/asheplyakov/work/sw/ginac/_build_w64/../ginac/container.h:116: first defined here
integration_kernel.cpp makes use of GiNaC::lst without including the `lst.h` header. That's possible since there's a typedef in `registrar.h` (included by virtually all GiNaC sources) and a defintion in `container.h` (included via `add.h` -> `expairseq.h` -> `indexed.h` -> `exprseq.h`), so the compiler can instantiate container<std::list>. However the explicit specialization of `lst::info` is not available (in integration_kernel.cpp). This violates 17.8.3.6 [templ.expl.spec] which demands
If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required. If the program does not provide a definition for an explicit specialization and either the specialization is used ina way that would cause an implicit instantiation to take place or the member is a virtual member function, the program is ill-formed, no diagnostic required.
On ELF platforms libginac appears to link just fine despite having two instantiations of `lst::info` since the of them (in `integration_kernel.o`) is a weak symbol:
$ find ginac -type f -name '*.o' | xargs -n 1 nm --print-file-name --defined | c++filt | grep -e 'list>::info(' ginac/CMakeFiles/ginac.dir/integration_kernel.cpp.o:0000000000000000 W GiNaC::container<std::__cxx11::list>::info(unsigned int) const ginac/CMakeFiles/ginac.dir/lst.cpp.o:0000000000000000 T GiNaC::container<std::__cxx11::list>::info(unsigned int) const
so the linker discards the wrong instantiation of `lst::info` method. However on MinGW there are no weak symbols (in ELF sense):
$ find ginac -type f -name '*.obj' | xargs -n 1 x86_64-w64-mingw32-nm --print-file-name --defined | c++filt | grep -e 'list>::info(' ginac/CMakeFiles/ginac.dir/lst.cpp.obj:0000000000000010 T GiNaC::container<std::__cxx11::list>::info(unsigned int) const ginac/CMakeFiles/ginac.dir/integration_kernel.cpp.obj:0000000000000000 T GiNaC::container<std::__cxx11::list>::info(unsigned int) const
Hence the above multiple definition error.
To avoid the problem #include "lst.h" (so explicit specialization is available). While at it explicitly instantiate lst::info method in lst.cpp
A better solution would be to remove declaration of lst from registrar.h, but that's too disruptive since GiNaC uses lst a lot: subs, unarchive, etc.
I came across it because clang++ now complains: lst.cpp:41:37: warning: explicit instantiation of 'info' that occurs after an explicit specialization has no effect [-Winstantiation-after-specialization] Wouldn't it be sufficent to include "lst.h" in "integration_kernel.cpp"? I must admit that I do not understand the rest of it. All my best, -richy. -- Richard B. Kreckel <https://in.terlu.de/~kreckel/>