Nicolai Hähnle via llvm-dev
2016-Jun-18 11:34 UTC
[llvm-dev] Linker failures in debug build - compiler/linker poll?
Hi, since recently I'm getting linker failures in debug builds. The root cause is that -fvisibility-inlines-hidden causes inline functions in explicit template instantiations to become hidden in certain cases. The following hunk works around this... --- a/cmake/modules/HandleLLVMOptions.cmake +++ b/cmake/modules/HandleLLVMOptions.cmake @@ -159,7 +159,13 @@ endif() if(NOT WIN32 AND NOT CYGWIN) # MinGW warns if -fvisibility-inlines-hidden is used. check_cxx_compiler_flag("-fvisibility-inlines-hidden" SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG) - append_if(SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG "-fvisibility-inlines-hidden" CMAKE_CXX_FLAGS) + + # The flag also hides inlines from explicit template instantiations, which + # leads to link failures in debug builds at least with gcc 5.3.1 and + # both GNU ld 2.26 or gold 1.11. + if (NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG") + append_if(SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG "-fvisibility-inlines-hidden" CMAKE_CXX_FLAGS) + endif() endif() if( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 ) ... but before I just wildly commit something, I'd say this does seem more like a compiler bug to me and so I'd like to poll people about which compilers they're using to see where this appears. FWIW, gcc 5.3.1 / ld 2.26 / gold 1.11 is what you get in Ubuntu 16.04. Also note: This has surfaced only recently, because of how the symbol types evolve during the different linker stages. PassManager<Function> is not affected, because it is referenced in libLLVMCore.a outside the .o file that contains the explicit instantiation, while PassManager<Loop> *is* affected, because it is referenced in libLLVMAnalysis.a outside the .o file that contains the explicit instantiation, but that .cpp file including the reference does *not* include LoopPassManager.h where the template instantiation is declared extern. This somehow causes the linker to treat the two cases differently. Thanks, Nicolai
Mehdi Amini via llvm-dev
2016-Jun-18 23:03 UTC
[llvm-dev] Linker failures in debug build - compiler/linker poll?
Hi,> On Jun 18, 2016, at 4:34 AM, Nicolai Hähnle via llvm-dev <llvm-dev at lists.llvm.org> wrote: > > Hi, > > since recently I'm getting linker failures in debug builds. The root cause is that -fvisibility-inlines-hidden causes inline functions in explicit template instantiations to become hidden in certain cases.I’m not sure I understand how it can be a link failure right now. A minimal test case would be nice. Thanks, — Mehdi> > The following hunk works around this... > > --- a/cmake/modules/HandleLLVMOptions.cmake > +++ b/cmake/modules/HandleLLVMOptions.cmake > @@ -159,7 +159,13 @@ endif() > if(NOT WIN32 AND NOT CYGWIN) > # MinGW warns if -fvisibility-inlines-hidden is used. > check_cxx_compiler_flag("-fvisibility-inlines-hidden" SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG) > - append_if(SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG "-fvisibility-inlines-hidden" CMAKE_CXX_FLAGS) > + > + # The flag also hides inlines from explicit template instantiations, which > + # leads to link failures in debug builds at least with gcc 5.3.1 and > + # both GNU ld 2.26 or gold 1.11. > + if (NOT uppercase_CMAKE_BUILD_TYPE STREQUAL "DEBUG") > + append_if(SUPPORTS_FVISIBILITY_INLINES_HIDDEN_FLAG "-fvisibility-inlines-hidden" CMAKE_CXX_FLAGS) > + endif() > endif() > > if( CMAKE_SIZEOF_VOID_P EQUAL 8 AND NOT WIN32 ) > > ... but before I just wildly commit something, I'd say this does seem more like a compiler bug to me and so I'd like to poll people about which compilers they're using to see where this appears. > > FWIW, gcc 5.3.1 / ld 2.26 / gold 1.11 is what you get in Ubuntu 16.04. > > Also note: This has surfaced only recently, because of how the symbol types evolve during the different linker stages. PassManager<Function> is not affected, because it is referenced in libLLVMCore.a outside the .o file that contains the explicit instantiation, while PassManager<Loop> *is* affected, because it is referenced in libLLVMAnalysis.a outside the .o file that contains the explicit instantiation, but that .cpp file including the reference does *not* include LoopPassManager.h where the template instantiation is declared extern. This somehow causes the linker to treat the two cases differently.