llvm/lib/Support/Signals.cpp fails to compile due to -Werror=global-constructors

Using clang 12.0.1 (Fedora 12.0.1-1.amzn2022) on AArch64 AmazonLinux 2022 (stdlibc++ 11.2.1), compiling the latest LLVM main branch lib/Support/Signals.cpp fails with the following:

/usr/bin/clang++ -DGTEST_HAS_RTTI=0 -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D_STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -Ilib/Support -I/llvm-project.git/llvm/lib/Support -Iinclude -I/llvm-project.git/llvm/include -pipe -fPIC -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -fdiagnostics-color -ffunction-sections -fdata-sections -Werror=global-constructors -O3 -DNDEBUG -std=c++2b  -fno-exceptions -fno-rtti -MD -MT lib/Support/CMakeFiles/LLVMSupport.dir/Signals.cpp.o -MF lib/Support/CMakeFiles/LLVMSupport.dir/Signals.cpp.o.d -o lib/Support/CMakeFiles/LLVMSupport.dir/Signals.cpp.o -c /llvm-project.git/llvm/lib/Support/Signals.cpp

/llvm-project.git/llvm/lib/Support/Signals.cpp:84:26: error: declaration requires a global constructor [-Werror,-Wglobal-constructors]

static CallbackAndCookie CallBacksToRun[MaxSignalHandlerCallbacks];

The -Werror=global-constructors flag is set in llvm/lib/Support/CMakeLists.txt since commit 402461beb051b6a5c158f1e36d8e2c2b676e8804 from July 2021, so already a little while ago.

Is this expected?

Some additional context:


… inside a docker build running on an M1 machine, using the latest arm64 public.ecr.aws/amazonlinux/amazonlinux:2022 as base image. Unrelated but perhaps interesting, gcc 11 in this setup fails to build lib/Passes/CMakeFiles/LLVMPasses.dir/StandardInstrumentations.cpp with error: template-id not allowed for destructor (line 468, the ChangeReporter<T> destructor), hence trying to build with clang 12…

Looks like the std::atomic in CallbackAndCookie may be triggering a global constructor in your environment.

We saw this in the past with some implementation of std::mutex having the same problem. Can you try to implement the same check as the one for mutex for std::atomic (or whatever inside CallbackAndCookie triggers the global constructor):

Will do, and I’ll check the relevant sources in libatomic.

What do you think about adding a user-facing CMake variable, defaulted to enable, for using -Werror=global-constructors (on top of the mutex test or equivalent)?

That might be a reasonable escape hatch for broken toolchains I guess.

Adding relevant static std::atomic<...> to the test code in the CMake file doesn’t change things – the flag is still set, so the build fails.

I’m not sure I’m following the logic though: Signals.cpp line 84 explicitly declares a global array of CallbackAndCookie instances. Are we trying to ensure that those are trivially default constructible (and standard layout types)? According to cppreference, std::atomic<> of integral types do not necessarily have a trivial default constructor starting with c++20 (P0883?). Why would a toolchain be broken if that’s not the case? Shouldn’t the code in Signals.cpp avoid declaring a non-trivial global instead? I must be missing something…

You probably need to put in a struct, an array, or include an initializer list to reproduce the condition that you see falling. The code you reported failing does not seem to complicated I would think you could simplify this to find the trigger?

Well C++20 isn’t our primary target is the likely explanation.

Sure, feel free to propose a patch!

Created D122067.

1 Like