diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp --- a/lld/COFF/InputFiles.cpp +++ b/lld/COFF/InputFiles.cpp @@ -500,6 +500,17 @@ leaderSelection = selection = IMAGE_COMDAT_SELECT_LARGEST; } + // GCCs __declspec(selectany) doesn't actually pick "any" but "same size as". + // Clang on the other hand picks "any". To be able to link two object files + // with a __declspec(selectany) declaration, one compiled with gcc and the + // other with clang, we merge them as proper "same size as" + if (config->mingw && ((selection == IMAGE_COMDAT_SELECT_ANY && + leaderSelection == IMAGE_COMDAT_SELECT_SAME_SIZE) || + (selection == IMAGE_COMDAT_SELECT_SAME_SIZE && + leaderSelection == IMAGE_COMDAT_SELECT_ANY))) { + leaderSelection = selection = IMAGE_COMDAT_SELECT_SAME_SIZE; + } + // Other than that, comdat selections must match. This is a bit more // strict than link.exe which allows merging "any" and "largest" if "any" // is the first symbol the linker sees, and it allows merging "largest" diff --git a/lld/test/COFF/comdat-gcc-compatibility.s b/lld/test/COFF/comdat-gcc-compatibility.s new file mode 100644 --- /dev/null +++ b/lld/test/COFF/comdat-gcc-compatibility.s @@ -0,0 +1,13 @@ +# REQUIRES: x86 +# RUN: llvm-mc %s -triple x86_64-pc-win32 -defsym obj=0 -filetype=obj -o %t1.obj +# RUN: llvm-mc %s -triple x86_64-pc-win32 -defsym obj=1 -filetype=obj -o %t2.obj +# RUN: lld-link /lldmingw /noentry /dll %t1.obj %t2.obj /out:%t3.dll +# RUN: not lld-link /noentry /dll %t1.obj %t2.obj /out:%t3.dll +.if obj==0 + .section .text$nm, "", discard, symbol +.else + .section .text$nm, "", same_size, symbol +.endif + .globl symbol +symbol: + .long 1