0

Recently installed the new LLVM/clang-cl toolset in Visual Studio 2019, which is a potentially brilliant addition! However, when building my EXE and DLL files, I get the following error at link time:

lld-link : error : undefined symbol: "__declspec(dllimport) public: static void __cdecl ATL::CSimpleStringT<wchar_t, 1>::CopyChars(wchar_t *, unsigned __int64, wchar_t const *, int)" (__imp_?CopyChars@?$CSimpleStringT@_W$00@ATL@@SAXPEA_W_KPEB_WH@Z)

It only happens when building with "Use MFC in a Shared DLL" and in the "Release" configuration: i.e., with either "Use MFC in a Static Library" or in "Debug" configuration, the error disappears.

The 'offending function is defined in the cstringt.h header with the _ATL_INSECURE_DEPRECATE("blah blah") attribute, but re-defining this to 'empty' doesn't fix the problem.

To reproduce, create a default MFC, dialog-based app in VS-2019 with the New Project wizard and add the following in the OnInitDialog() function:

// TODO: Add extra initialization here
    CString txt1 = L"Hello, ";
    CString txt2 = L"world!";
    CString mess = txt1 + txt2;
    SetDlgItemText(IDC_STATIC, mess);

Build as default to check, then switch the "Platform Toolset" to "LLVM (clang-cl)" and rebuild! You'll need to comment-out or disable the manifest-related lines at the end of the generated "framework.h" file:

    #ifndef __clang__
    #ifdef _UNICODE
    #if defined _M_IX86
    #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*'\"")
    #elif defined _M_X64
    #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='amd64' publicKeyToken='6595b64144ccf1df' language='*'\"")
    #else
    #pragma comment(linker,"/manifestdependency:\"type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='*' publicKeyToken='6595b64144ccf1df' language='*'\"")
    #endif
    #endif
    #endif

I've tried the following #defines in my global header, but to no avail:

    #define _CRT_SECURE_NO_DEPRECATE
    #define _SECURE_ATL 0
    #define _SECURE_SCL 0
    #define _ATL_INSECURE_DEPRECATE(a)
    #define _ATL_DEBUG_INTERFACES

So: (1) Is this a 'bug' that I should report to Microsoft or am I doing something daft? (2) Can anyone suggest a patch/fix so I can really test my MFC projects with clang? Note: I have to use MFC in a DLL as I rely on extension DLLs.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83

2 Answers2

2

Aha! I have a fix that works (for now) but relies on the fact that the EXEs I'm building all call a common DLL, which I also build. I added this code to that DLL's source and they now build and run!

template<> void __declspec(dllexport) __cdecl ATL::CSimpleStringT<wchar_t,1>::CopyChars(wchar_t *pchDest, size_t, const
    wchar_t *pchSrc, int nChars) throw()
{
    memcpy(pchDest, pchSrc, size_t(nChars) * sizeof(wchar_t));
    return;
}

However, this relies on the fact that I'm calling that DLL. For other apps that don't, I can't (yet) get this approach to work. Also, my "MFC Extension DLLs" don't seem to like it: they are optional 'plug-in' modules but just cause a complete exit/crash when I try to load one - but that could be caused by a number of other factors, as this uses really deep/subtle MFC stuffs.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83
0

I have come across the same issue and found that disabling inline function expansion (/Ob0) in the project configuration solves the problem. Did you happen to have it enabled (/Ob1 or /Ob2)?

Michal
  • 32
  • 1
  • Yes, this works! However, my concern here would be the impact on optimization. – Adrian Mole Nov 06 '19 at 12:26
  • I have reported the issue to the VS support team and it is now flagged as "under investigation." I shall pass on this fix to them, as it may help them resolve the issue. – Adrian Mole Nov 06 '19 at 12:27
  • 1
    Yes, the optimization will be affected, but it is not a big concern for me at this point. I use LLVM toolset as an addition to enable clang-based tools verification of my projects. For production I still use MSVC one. Please post an update once you get more information from VS support. – Michal Nov 07 '19 at 07:08