Intel® C++ Compiler
Community support and assistance for creating C++ code that runs on platforms based on Intel® processors.
7956 Discussions

problem moving to icc 17 (from 16 and 15)

James_Burgess
Beginner
1,733 Views

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;
}
If I compile that with icc 17 with -O3 I see the following symbol with dumpbin, notice the non-demangled name:
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

0 Kudos
3 Replies
Judith_W_Intel
Employee
1,733 Views

 

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
!%

 

0 Kudos
James_Burgess
Beginner
1,733 Views

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.

0 Kudos
Varsha_M_Intel
Employee
1,733 Views

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.)   “

0 Kudos
Reply