Skip to content

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

@llvmbot

Description

@llvmbot
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();
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugzillaIssues migrated from bugzillaclang:frontendLanguage frontend issues, e.g. anything involving "Sema"

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions