- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I was trying to get going with 17 (version 17.0.0.109) and I'm coming from 15.0 and 16.0 (versions 15.0.3.208 and 16.0.3.207) which are all hosted under vc11 using vc11 compatibility mode. I have a fair-sized code base that takes about an hour to compile and everything built fine but one part where I got a strange looking undefined symbol linker error. It was strange in that the demangled name was the same as the mangled name.
I spent some time getting an example down to the smallest possible code that exhibits the problem and what appears to happen is, while compiling with optimization on (-O3) if I use a #pragma optimize(“”, off) and then refer to an in line method the symbol name seems to be incorrectly mangled. This comes out of a pretty large and complicated build but I’ve whittled it down to the smallest example I can make. The “missing” symbol is the operator!=.
Here's the code in question:
define DLLAPI _declspec( dllimport ) class DLLAPI PStatus { public: enum PStatusCode { kSuccess = 0, kFailure, }; PStatus(); friend DLLAPI inline bool operator!=( const PStatus::PStatusCode code, const PStatus& status ) { return ( status.fStatusCode != code ); } private: unsigned char fStatusCode; }; #pragma optimize("", off) int initialize() { PStatus status; if ( PStatus::kSuccess != status ) { return 1; } return 0; }
009 00000000 UNDEF notype External | __imp_??9..0@YA_NW4PStatusCode@PStatus@@AEBV1@@Z (__declspec(dllimport) ??9..0@YA_NW4PStatusCode@PStatus@@AEBV1@@Z)
If compiled with icc 17 with -Od I get this:
009 00000000 UNDEF notype External | __imp_??9@YA_NW4PStatusCode@PStatus@@AEBV1@@Z (__declspec(dllimport) bool __cdecl operator!=(enum PStatus::PStatusCode,class PStatus const &))
Compared to either icc 15 or icc 16 with -O3 I get:
009 00000000 UNDEF notype External | __imp_??9@YA_NW4PStatusCode@PStatus@@AEBV1@@Z (__declspec(dllimport) bool __cdecl operator!=(enum PStatus::PStatusCode,class PStatus const &))
The class definition is not my code and I can't change it. If you remove the declspec(dllimport) the symbol looks normal again but I can't test that since it's not my code.
Cheers,
James
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I can't reproduce this. I tried our latest 17.0 compiler with MSVC++ 2010 and 2015.
I did the following. Did you do something differently?
!% cat b.cpp
#define DLLAPI _declspec( dllimport )
class DLLAPI PStatus
{
public:
enum PStatusCode
{
kSuccess = 0,
kFailure,
};
PStatus();
friend DLLAPI inline bool operator!=( const PStatus::PStatusCode code,
const PStatus& status )
{
return ( status.fStatusCode != code );
}
private:
unsigned char fStatusCode;
};
#pragma optimize("", off)
int
initialize()
{
PStatus status;
if ( PStatus::kSuccess != status )
{
return 1;
}
return 0;
}
!% icl -O3 -c b.cpp
Intel(R) C++ Intel(R) 64 Compiler for applications running on Intel(R) 64, Version 17.0 Beta Build x
Built Sep 7 2016 14:15:38 by jward4 on JWARD4-DESK1 in D:/workspaces/17_0cfe/dev
Copyright (C) 1985-2016 Intel Corporation. All rights reserved.
b.cpp
!% dumpbin /symbols b.obj
Microsoft (R) COFF/PE Dumper Version 14.00.24210.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file b.obj
File Type: COFF OBJECT
COFF SYMBOL TABLE
000 00000000 SECT1 notype Static | .text
Section length 60, #relocs 2, #linenums 0, checksum 1F6CFB72, select
ion 1 (pick no duplicates)
002 00000000 SECT1 notype () External | ?initialize@@YAHXZ (int __cdecl
initialize(void))
003 00000000 UNDEF notype External | __imp_??9@YA_NW4PStatusCode@PSta
tus@@AEBV1@@Z (__declspec(dllimport) bool __cdecl operator!=(enum PStatus::PStat
usCode,class PStatus const &))
004 00000000 UNDEF notype External | __imp_??0PStatus@@QEAA@XZ (__dec
lspec(dllimport) public: __cdecl PStatus::PStatus(void))
005 00000000 SECT2 notype Static | .xdata
Section length C, #relocs 0, #linenums 0, checksum 0, select
ion 5 (pick associative Section 0x1)
007 00000000 SECT3 notype Static | .pdata
Section length C, #relocs 3, #linenums 0, checksum 0, select
ion 5 (pick associative Section 0x1)
009 00000000 UNDEF notype () External | __ImageBase
00A 00000000 SECT4 notype Static | .drectve
Section length 89, #relocs 0, #linenums 0, checksum 0
String Table Size = 0x6B bytes
Summary
89 .drectve
C .pdata
60 .text
C .xdata
!%
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Judith,
I did not do anything differently. Well other than the fact I did say vc11, not vc10 nor vc14 that you tried (VS2010/VS2015). So that might be it? Also my icl doesn't print "Beta Build x", it reports "Version 17.0.0.109 Build 20160721", maybe it's already fixed!
I've managed to get around the problem entirely by avoiding the #pragma in the code that refs the inline so I'm happily moving towards icc 17 now.
Thanks,
James.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi James,
In response to the CQ filed for this issue
"You have a inline function operator!= in your example. Your concern is that you saw code emitted for this function in older compilers, but now 17_0 that function is not emitted.
In your example, because the function is marked "inline", the intent is normally to inline the function and NOT lay down a definition. But in your case, the function will NOT be inlined because the function fcalling it is "optimize off". In this case, the compiler would normally lay down a definition of the inline function so that it is not unresolved during the link. This copy is laid down ONLY for the purpose of resolving of non-inlined inline function. It should NOT be depended on to resolve a reference to this function in another translation unit.
In 17.0, the compiler does additional CLONING of functions. So, instead of inlining, it decided to clone a version of this inline function, and lay down the clone. The clone has the same name as the original function, but has a ..0 suffix. It is this suffix that seems to be confusing the demangler, which is not aware of cloning done by the Intel compiler. In any case, the clone does adequately resolve the uninlined function instance.
It may be questionable whether the cloning should be allowed into a function that is marked "optimize off". However, it is NEVER appropriate for a program to rely on an inline function to resolve an reference in a DIFFERENT translation unit. This is a violation of the programming model.
Looking at 17_0 after the 20160721 release, I can see that the cloning is no longer happening. The reason is that the C/C++ front is marking the inline function as "never-emit-def", and the back-end specifically excludes such functions from cloning. Presumably, this is done because the function is indicated to be dllimport by the user, and so no defintion should be needed as there is an importable definition is available. (This does NOT happen when the function is NOT dllimport.) “

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page