Bug 20805 – C++ mangling mismatch with templates and namespaces

Status
NEW
Severity
major
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Windows
Creation time
2020-05-08T11:02:39Z
Last change time
2024-12-13T19:08:27Z
Assigned to
No Owner
Creator
Andrej Mitrovic
Moved to GitHub: dmd#17954 →

Comments

Comment #0 by andrej.mitrovich — 2020-05-08T11:02:39Z
Using DMD v2.091.1. Take these two files: cpp.cpp ----- #include <vector> static const uint32_t XDR_MAX_LEN = 0xfffffffc; namespace xdr { template<typename T, uint32_t N = XDR_MAX_LEN> struct xvector { }; } template<typename T, typename VectorT> void push_back(VectorT& this_, T& value) { } #define PUSHBACKINST1(T) template void push_back<T, xdr::xvector<T> >(xdr::xvector<T>&, T&); PUSHBACKINST1(xdr::xvector<unsigned char>) ----- and d.d: ----- import core.stdc.stdint; extern (D) static immutable XDR_MAX_LEN = 0xffff_fffc; extern (C++, `xdr`) struct xvector(T, uint32_t N = XDR_MAX_LEN) { } extern (C++) public void push_back(T, VectorT) (ref VectorT this_, ref T value); void main () { xvector!(xvector!ubyte) vec; xvector!ubyte val; vec.push_back(val); } ----- $ cl /JMC /MP /GS /c /Zc:forScope /std:c++14 cpp.cpp $ dmd -m64 cpp.obj d.d d.obj : error LNK2019: unresolved external symbol "void __cdecl push_back<struct xdr::xvector<unsigned char,4294967292>,struct xdr::xvector<struct xdr::xvector<unsigned char,4294967292>,4294967292> >(struct xdr::xvector<struct xdr::xvector<unsigned char,4294967292>,4294967292> &,struct xvector<unsigned char,4294967292>::xvector<unsigned char,4294967292> &)" (??$push_back@U?$xvector@E$0PPPPPPPM@@xdr@@U?$xvector@U?$xvector@E$0PPPPPPPM@@xdr@@$0PPPPPPPM@@2@@@YAXAEAU?$xvector@U?$xvector@E$0PPPPPPPM@@xdr@@$0PPPPPPPM@@xdr@@AEAU?$xvector@E$0PPPPPPPM@@2@@Z) referenced in function _Dmain cpp.exe : fatal error LNK1120: 1 unresolved externals The actual exported symbol is: void __cdecl push_back<struct xdr::xvector<unsigned char,4294967292>,struct xdr::xvector<struct xdr::xvector<unsigned char,4294967292>,4294967292> >(struct xdr::xvector<struct xdr::xvector<unsigned char,4294967292>,4294967292> &,struct xdr::xvector<unsigned char,4294967292> &)" (??$push_back@U?$xvector@E$0PPPPPPPM@@xdr@@U?$xvector@U?$xvector@E$0PPPPPPPM@@xdr@@$0PPPPPPPM@@2@@@YAXAEAU?$xvector@U?$xvector@E$0PPPPPPPM@@xdr@@$0PPPPPPPM@@xdr@@AEAU?$xvector@E$0PPPPPPPM@@1@@Z) The difference is at the very end. @2@@Z in D vs @1@@Z in C++. It seems the namespace is not mangled properly. Demangled D: void __cdecl push_back<struct xdr::xvector<unsigned char,-4>,struct xdr::xvector<struct xdr::xvector<unsigned char,-4>,-4> >(struct xdr::xvector<struct xdr::xvector<unsigned char,-4>,-4> & __ptr64,struct xvector<unsigned char,-4>::xvector<unsigned char,-4> & __ptr64) Demangled C++: void __cdecl push_back<struct xdr::xvector<unsigned char,-4>,struct xdr::xvector<struct xdr::xvector<unsigned char,-4>,-4> >(struct xdr::xvector<struct xdr::xvector<unsigned char,-4>,-4> & __ptr64,struct xdr::xvector<unsigned char,-4> & __ptr64) Notice the missing 'xdr::' close to the end.
Comment #1 by andrej.mitrovich — 2020-05-08T11:04:58Z
By the way please disregard the "-4" part, this is a bug on demangler.com. c++filt works fine and will demangle the symbols properly.
Comment #2 by andrej.mitrovich — 2020-05-12T12:55:07Z
Simplified test-case: ``` extern (C++, `xdr`) struct xvector(T) { } extern (C++) public void push_back1 (ref xvector!(xvector!ubyte), ref xvector!ubyte); extern (C++) public void push_back2 ()(ref xvector!(xvector!ubyte), ref xvector!ubyte); void main () { xvector!(xvector!ubyte) vec; xvector!ubyte val; vec.push_back1(val); vec.push_back2(val); } ```
Comment #3 by pro.mathias.lang — 2021-06-16T05:56:29Z
Actually, the reduction is a different issue. C++ does not have parameterless templates, so the compiler should probably disallow them since it can't mangle them.
Comment #4 by robert.schadek — 2024-12-13T19:08:27Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/17954 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB