C++ 10.1.011 inline template not being instantiated

C++ 10.1.011 inline template not being instantiated

Hi,

I have found an issue with template instantiation of inlined functions.

Here is the code that uses MFC42:

#include
#include // MFC core and standard #include // MFC extensions
#include
#include // MFC support for #include
#include

int main() {

CArray SrcArray;

return 0;
}

When it is linked these unresolved symbols are printed:

tt.obj : error LNK2019: unresolved external symbol "void __stdcall DestructElements(class CString *,int)" (??$DestructElements@VCString@@@@YGXPAVCString@@H@Z) referenced in function "public: virtual void * __thiscall CArray::`scalar deleting destructor'(unsigned int)" (??_G?$CArray@VCString@@V1@@@UAEPAXI@Z)
tt.obj : error LNK2019: unresolved external symbol "void __stdcall ConstructElements(class CString *,int)" (??$ConstructElements@VCString@@@@YGXPAVCString@@H@Z) referenced in function "public: virtual void __thiscall CArray::Serialize(class CArchive &)" (?Serialize@?$CArray@VCString@@V1@@@UAEXAAVCArchive@@@Z)
tt.obj : error LNK2019: unresolved external symbol "void __stdcall SerializeElements(class CArchive &,class CString *,int)" (??$SerializeElements@VCString@@@@YGXAAVCArchive@@PAVCString@@H@Z) referenced in function "public: virtual void __thiscall CArray::Serialize(class CArchive &)" (?Serialize@?$CArray@VCString@@V1@@@UAEXAAVCArchive@@@Z)

All of these are inlined functions defined in afxtempl.h and used by CArray constructor and destructor (and other members as well).

Using /Od or even /Qinline-forceinline does not help.
If, at the same time, int or CStringData is used instead of CString in the template specialization, everything links just fine.

So finally I figured out that commenting out these lines in afxtempl.h:

template<> void AFXAPI ConstructElements (CString* pElements, INT_PTR nCount);
template<> void AFXAPI DestructElements (CString* pElements, INT_PTR nCount);
template<> void AFXAPI CopyElements (CString* pDest, const CString* pSrc, INT_PTR nCount);
template<> void AFXAPI SerializeElements (CArchive& ar, CString* pElements, INT_PTR nCount);

leads to them being properly inlined. This seems an Intel compiler problem because /Qms2 (full MS C++ compatibility) is used.

7 posts / novo 0
Último post
Para obter mais informações sobre otimizações de compiladores, consulte Aviso sobre otimizações.

Does this problem depend on which version of CL or link you have installed? It seems you would have to specify those in order to reproduce the problem (unless a bug was corrected in the current ICL):

$ icl /Qms2 max.cpp
Intel C++ Compiler for applications running on IA-32, Version 10.1 Build 2
0071116 Package ID: w_cc_p_10.1.013
Copyright (C) 1985-2007 Intel Corporation. All rights reserved.

max.cpp
WINVER not defined. Defaulting to 0x0600 (Windows Vista)
Microsoft Incremental Linker Version 9.00.20706.01
Copyright (C) Microsoft Corporation. All rights reserved.

-out:max.exe
max.obj

Hi,

Thank you for the reply.

Here is the info:

W:>max.cmd
Intel C++ Compiler for applications running on IA-32, Version 10.1 Build 20070913 Package ID: w_cc_p_10.1.011
Copyright (C) 1985-2007 Intel Corporation. All rights reserved.

max.cpp
Microsoft Incremental Linker Version 8.00.50727.42
Copyright (C) Microsoft Corporation. All rights reserved.

-out:max.exe
max.obj
max.obj : error LNK2019: unresolved external symbol "void __stdcall DestructElements(class CString *,int)" (??$DestructElements@VCString@@@@YGXPAVCString@@H@Z) referenced in function "public: virtual void * __thiscall CArray::`scalar deleting destructor'(unsigned int)" (??_G?$CArray@VCString@@V1@@@UAEPAXI@Z)
max.obj : error LNK2019: unresolved external symbol "void __stdcall ConstructElements(class CString *,int)" (??$ConstructElements@VCString@@@@YGXPAVCString@@H@Z) referenced in function "public: virtual void __thiscall CArray::Serialize(class CArchive &)" (?Serialize@?$CArray@VCString@@V1@@@UAEXAAVCArchive@@@Z)
max.obj : error LNK2019: unresolved external symbol "void __stdcall SerializeElements(class CArchive &,class CString *,int)" (??$SerializeElements@VCString@@@@YGXAAVCArchive@@PAVCString@@H@Z) referenced in function "public: virtual void __thiscall CArray::Serialize(class CArchive &)" (?Serialize@?$CArray@VCString@@V1@@@UAEXAAVCArchive@@@Z)
max.exe : fatal error LNK1120: 3 unresolved externals

On Visual Studio 8 this problem does not reproduce because these inlines are marked as deprecated in afxtempl.h and are not actually used.

My MFC version is (from afxver_.h):

#define _MFC_VER 0x0600 // Microsoft Foundation Classes version 6.00

while Visual Studio 8 version is (from afxver_.h):

#define _MFC_VER 0x0800 // Microsoft Foundation Classes version 8.00

Best regards.

VS6 specifically is no longer supported since ICL 10.0. ICL 9.1 had an option to install with VS6. In that case there is no compatibility with more recent versions. For a long shot, you could try editing the VC flag in the ICL installation file ICL.CFG, in case it is set for a more recent VC version.

We use quite modern cl.exe (14.00.50727.42) and link.exe (8.00.50727.42), and they handle old MFC version 6 headers and libraries just fine. So, given this case, icl.exe seems to have a compatibility defect - which may manifest itself with some other template based library, possibly not from Microsoft.

What does the file"max.cmd" contain?

Hi,

the file max.cmd contains just

icl /Qms2 max.cpp

while max.cpp has

#include
#include // MFC core and standard #include // MFC extensions
#include
#include // MFC support for #include
#include

int main() {

CArray SrcArray;

return 0;
}

To reproduce the issue use MFC from Visual Studio 6.

Deixar um comentário

Faça login para adicionar um comentário. Não é membro? Inscreva-se hoje mesmo!