Quuxplusone / LLVMBugzillaTest

0 stars 0 forks source link

clang-cl does not work with /MDd (dynamic debug CRT) due to std::locale link errors #18255

Open Quuxplusone opened 10 years ago

Quuxplusone commented 10 years ago
Bugzilla Link PR18256
Status NEW
Importance P normal
Reported by Edward Diener (eldlistmailingz@tropicsoft.com)
Reported on 2013-12-15 15:04:44 -0800
Last modified on 2014-05-01 12:09:10 -0700
Version trunk
Hardware PC Windows XP
CC dgregor@apple.com, llvm-bugs@lists.llvm.org, p_hampson@wargaming.net, rnk@google.com
Fixed by commit(s)
Attachments
Blocks
Blocked by PR11170
See also
Atempting to link an executable while testing Boost libraries with clang-cl I
am seeing this error in a number of situations:

clang-win.link ..\..\..\bin.v2\libs\vmd\test\test_begin_identifier.test\clang-
vc11-win-3.4\debug\test_begin_identifier.exe
test_begin_identifier.obj : error LNK2019: unresolved external symbol "public:
static class std::locale::id std::ctype<char>::id"
(?id@?$ctype@D@std@@2V0locale@2@A) referenced in function "class
std::ctype<char> const & __cdecl std::use_facet<class std::ctype<char> >(class
std::locale const &)"
(??$use_facet@V?$ctype@D@std@@@std@@YAABV?$ctype@D@0@ABVlocale@0@@Z)
test_begin_identifier.obj : error LNK2019: unresolved external symbol "public:
static class std::locale::id std::ctype<wchar_t>::id"
(?id@?$ctype@_W@std@@2V0locale@2@A) referenced in function "class
std::ctype<wchar_t> const & __cdecl std::use_facet<class std::ctype<wchar_t>
>(class std::locale const &)"
(??$use_facet@V?$ctype@_W@std@@@std@@YAABV?$ctype@_W@0@ABVlocale@0@@Z)
test_begin_identifier.obj : error LNK2019: unresolved external symbol "private:
static int std::locale::id::_Id_cnt" (?_Id_cnt@id@locale@std@@0HA) referenced
in function "public: __thiscall std::locale::id::operator unsigned int(void)"
(??Bid@locale@std@@QAEIXZ)
test_begin_identifier.obj : error LNK2019: unresolved external symbol "void
__cdecl std::_DebugHeapDelete<void>(void *)"
(??$_DebugHeapDelete@X@std@@YAXPAX@Z) referenced in function "private: void
__thiscall std::numpunct<wchar_t>::_Tidy(void)"
(?_Tidy@?$numpunct@_W@std@@AAEXXZ)

The command line for clang-cl has these options:

-TP /Od /Ob0 /W3 /GR /MDd  /Zc:forScope /Zc:wchar_t -fmsc-version=1700 /wd4675
/EHs /D_HAS_EXCEPTIONS=0 /GR- -c
Quuxplusone commented 10 years ago
I don't understand the first error, but the last looks like there's some kind
of debug/release mismatch (std::_DebugHeapDelete<void>):

test_begin_identifier.obj : error LNK2019: unresolved external symbol "void
__cdecl std::_DebugHeapDelete<void>(void *)"
(??$_DebugHeapDelete@X@std@@YAXPAX@Z) referenced in function "private: void
__thiscall std::numpunct<wchar_t>::_Tidy(void)"
(?_Tidy@?$numpunct@_W@std@@AAEXXZ)

This is probably a mangler bug, or we're failing to instantiate an inline
function that VC++ normally instantiates.
Quuxplusone commented 10 years ago

The compiler command line shows that it is compiling the debug version. The linker line, which invokes the Microsoft linker is:

link /nologo /DEBUG /MACHINE:X86 /MANIFEST /subsystem:console /out:"......\bin.v2\libs\vmd\test\test_after_identifier.test\clang-vc11-win-3.4\debug\test_after_identifier.exe" @"......\bin.v2\libs\vmd\test\test_after_identifier.test\clang-vc11-win-3.4\debug\test_after_identifier.exe.rsp"

where the response file is simply:

"......\bin.v2\libs\vmd\test\test_after_identifier.test\clang-vc11-win-3.4\debug\test_after_identifier.obj"

The compile succeeds but the link gives an error.

If you think the .obj file will help you discover what the problem is I can attach it if you like.

Quuxplusone commented 10 years ago
In Visual Studio 2012, when building with _DEBUG, the xdebug header provides a
template function:

template<class _Ty> void _DebugHeapDelete(_Ty *_Ptr)
{
 if (_Ptr != 0)
 {
  _Ptr->~_Ty();
  free(_Ptr);
 }
}

with no other overrides or overloads that I can see.

The clang-cl I'm using here just reports "no matching function call", as the
above template fails substitition [with _Ty = void], due to the call to
"(void*)->~void".

So it's probably not resolving when linking because it's supposed to be an
instantiated template that MSVC's CL doesn't fail on, but clang-cl does.

This is using the LLVM-3.5.r198737-win32 snapshot with -cxx-abi itanium, I'm
guessing one of the compiler switches in the original report is causing clang-
cl to turn the "cannot instantiate template" into an implicit "extern template
class". /Ob0 "Disable inlining" perhaps?
Quuxplusone commented 10 years ago
Sorry, left out that the same header also provides the following macro:

#define _DELETE_CRT_VEC(ptr)    _STD _DebugHeapDelete((void *)ptr)

So it's definitely intentional that "_DebugHeapDelete<void>" be called here.
Quuxplusone commented 10 years ago
I can reproduce the problem by streaming a number, which invokes the locale
machinery:

$ cat t.cpp
#include <iostream>
int main() {
  int x = 123;
  std::cout << x << '\n';
}

$ cl -nologo -D_HAS_EXCEPTIONS=0 -GR- -MTd -D_DEBUG -c t.cpp && dumpbin
/symbols t.obj | grep 'DebugHeapDelete<void>'
t.cpp
585 00000000 SECTAC notype ()    External     |
??$_DebugHeapDelete@X@std@@YAXPAX@Z (void __cdecl
std::_DebugHeapDelete<void>(void *))

$ clang-cl -D_HAS_EXCEPTIONS=0 -GR- -MTd -D_DEBUG -c t.cpp && dumpbin /symbols
t.obj | grep 'DebugHeapDelete<void>'
3F1 00000000 UNDEF  notype       External     |
??$_DebugHeapDelete@X@std@@YAXPAX@Z (void __cdecl
std::_DebugHeapDelete<void>(void *))

MSVC provides a definition for std::_DebugHeapDelete<void>(void*), but Clang
does not.  Clang should emit an error if it fails template instantiation, so
I'm not sure why this compiles successfully at all.

If I use /MTd to get the static CRT, a definition is provided.  However if I
use /MDd, I get link errors.  I've been linking the CRT statically because
clang doesn't support dllimport / export of full classes yet (PR11170).
Quuxplusone commented 10 years ago

I fixed the _DebugHeapDelete problem in r207771, but the others remain with /D_DEBUG /MDd. They are blocked on importing a full class definition, which is PR11170.