Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clang generates duplicated Win32 APIs definitions, causing linking error #9649

Closed
llvmbot opened this issue Feb 21, 2011 · 6 comments
Closed
Labels
bugzilla Issues migrated from bugzilla clang:frontend Language frontend issues, e.g. anything involving "Sema"

Comments

@llvmbot
Copy link
Collaborator

llvmbot commented Feb 21, 2011

Bugzilla Link 9277
Resolution FIXED
Resolved on Apr 15, 2019 12:15
Version trunk
OS Windows NT
Blocks llvm/llvm-bugzilla-archive#12477
Attachments An example of the bitcode of a.c
Reporter LLVM Bugzilla Contributor
CC @asl,@tritao,@timurrrr

Extended Description

I'm using clang on Windows. This bug can be reproduced by the following steps:
(1) Make two files: say a.c and b.c.
(2) Both of the files include <windows.h>
(3) Both files call a simple Win32 API such as GetTickCount();
(4) Try to compile (w/o optimizations), then we will get a bunch of duplication linking error.

==========
error LNK2005: _Int64ShllMod32@12 already defined in cc-000000.o
error LNK2005: _Int64ShraMod32@12 already defined in cc-000000.o
error LNK2005: _Int64ShrlMod32@12 already defined in cc-000000.o
error LNK2005: _InterlockedBitTestAndSet already defined in cc-000000.o
error LNK2005: _InterlockedBitTestAndReset already defined in cc-000000.o
error LNK2005: _InterlockedBitTestAndComplement already defined in cc-000000.o
error LNK2005: _MemoryBarrier already defined in cc-000000.o
error LNK2005: _ReadPMC already defined in cc-000000.o
error LNK2005: _ReadTimeStampCounter already defined in cc-000000.o
error LNK2005: _DbgRaiseAssertionFailure already defined in cc-000000.o
error LNK2005: _HEAP_MAKE_TAG_FLAGS already defined in cc-000000.o
error LNK2005: _RtlSecureZeroMemory already defined in cc-000000.o
error LNK2005: _TpInitializeCallbackEnviron already defined in cc-000000.o
error LNK2005: _TpSetCallbackThreadpool already defined in cc-000000.o
error LNK2005: _TpSetCallbackCleanupGroup already defined in cc-000000.o
error LNK2005: _TpSetCallbackActivationContext already defined in cc-000000.o
error LNK2005: _TpSetCallbackNoActivationContext already defined in cc-000000.o
error LNK2005: _TpSetCallbackLongFunction already defined in cc-000000.o
error LNK2005: _TpSetCallbackRaceWithDll already defined in cc-000000.o
error LNK2005: _TpSetCallbackFinalizationCallback already defined in cc-000000.o
error LNK2005: _TpSetCallbackPriority already defined in cc-000000.o
error LNK2005: _TpSetCallbackPersistent already defined in cc-000000.o
error LNK2005: _TpDestroyCallbackEnviron already defined in cc-000000.o
error LNK2005: _InterlockedAnd64 already defined in cc-000000.o
error LNK2005: _InterlockedOr64 already defined in cc-000000.o
error LNK2005: _InterlockedXor64 already defined in cc-000000.o
error LNK2005: _InterlockedIncrement64 already defined in cc-000000.o
error LNK2005: _InterlockedDecrement64 already defined in cc-000000.o
error LNK2005: _InterlockedExchange64 already defined in cc-000000.o
error LNK2005: _InterlockedExchangeAdd64 already defined in cc-000000.o
error LNK2005: _InitializeThreadpoolEnvironment already defined in cc-000000.o
error LNK2005: _SetThreadpoolCallbackPool already defined in cc-000000.o
error LNK2005: _SetThreadpoolCallbackCleanupGroup already defined in cc-000000.o
error LNK2005: _SetThreadpoolCallbackRunsLong already defined in cc-000000.o
error LNK2005: _SetThreadpoolCallbackLibrary already defined in cc-000000.o
error LNK2005: _SetThreadpoolCallbackPriority already defined in cc-000000.o
error LNK2005: _SetThreadpoolCallbackPersistent already defined in cc-000000.o
error LNK2005: _DestroyThreadpoolEnvironment already defined in cc-000000.o
error LNK2005: _HRESULT_FROM_WIN32 already defined in cc-000000.o

(Both MSVC's link.exe and gcc linker generate the errors. So, it's the problem of the front end.)

I checked how the bitcode was generated by clang when <windows.h> is included. Then, each bit code contains a number of Win32 API's definitions (while many of them are inline hints). For example:

========
define x86_stdcallcc i64 @​Int64ShraMod32(i64 %Value, i32 %ShiftCount) nounwind inlinehint {
%1 = alloca i64, align 8
%2 = alloca i64, align 8
%3 = alloca i32, align 4
store i64 %Value, i64* %2, align 8
call void @​llvm.dbg.declare(metadata !{i64* %2}, metadata !​97), !dbg !​98
store i32 %ShiftCount, i32* %3, align 4
call void @​llvm.dbg.declare(metadata !{i32* %3}, metadata !​99), !dbg !​100
call void asm sideeffect "/FIXME: not done/", "{dirflag},{fpsr},~{flags}"() nounwind, !dbg !​101, !srcloc !​95
%4 = load i64* %1, !dbg !​103
ret i64 %4, !dbg !​103

These definitions exist in every object files that use <windows.h>, resulting in duplication linking errors.

My current workaround is killing these functions' definition via a module pass where just call Function::deleteBody().

I don't have deep knowledge of front end, so I can't figure it out the reason further.

I'm attaching the bitcode of a simple file:

// a.c
#include <windows.h>

unsigned int foo()
{
return GetTickCount();
}

@asl
Copy link
Collaborator

asl commented Feb 21, 2011

Please attach the preprocessed source.

@llvmbot
Copy link
Collaborator Author

llvmbot commented Feb 21, 2011

Preprocessed a.c
#include <windows.h>

unsigned int foo()
{
return GetTickCount();
}

#include "..." search starts here:
#include <...> search starts here:
z:/dev/build-prospector/bin/MinSizeRel/../lib/clang/2.9/include
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\include
End of search list.

@llvmbot
Copy link
Collaborator Author

llvmbot commented Feb 21, 2011

Please attach the preprocessed source.

It looks like "__forceinline" functions are defined even if they're not actually used. I believe the patch would be simple. All the problematic APIs were declared as __forceinline.

@llvmbot
Copy link
Collaborator Author

llvmbot commented Jun 7, 2011

Please attach the preprocessed source.

It looks like "__forceinline" functions are defined even if they're not
actually used. I believe the patch would be simple. All the problematic APIs
were declared as __forceinline.

I just ran into this problem too.

As a quick test, I made the __forceinline token handler do something vaguely appropriate (instead of doing nothing at all)

(\llvm\tools\clang\lib\Parse\ParseDecl.cpp:1632)

// Microsoft single token adornments.
case tok::kw___forceinline:
  DS.SetFunctionSpecInline(Loc, PrevSpec, DiagID);
  break;

Compiling with this in place wiped out 95% of the duplicated symbols being moaned about during linking. The 3 remaining ones - Int64Shra, Int64Shll, Int64Shrl - are perhaps being mistakenly instantiated in each object file because in WinNT.h (line 789 on Win SDK 7.0A), the forward declarations for those functions lack inline tokens. They are only declared inline when implemented, a few lines further down the file.

If I add those 'missing' inlines, all my duplicated symbols disappear.

@tritao
Copy link
Mannequin

tritao mannequin commented May 7, 2012

*** Bug llvm/llvm-bugzilla-archive#12041 has been marked as a duplicate of this bug. ***

@tritao
Copy link
Mannequin

tritao mannequin commented Jun 18, 2012

Fixed as of r158653 by mspencer.

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 3, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla clang:frontend Language frontend issues, e.g. anything involving "Sema"
Projects
None yet
Development

No branches or pull requests

2 participants