https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107708
Bug ID: 107708 Summary: LTO causes gnu::constructor functions to not be called with correct arguments if there is more than one constructor Product: gcc Version: 11.3.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: lto Assignee: unassigned at gcc dot gnu.org Reporter: cfsteefel at arista dot com CC: marxin at gcc dot gnu.org Target Milestone: --- When a function is marked with the constructor attribute, if there is more than one function marked with the constructor attribute, the function's arguments are not passed when LTO inlines the function into DT_INIT_ARRAY. If LTO is disabled, the function will instead be passed argc, argv, and envp by glibc (other libc implementation may or may not pass anything). See the following code: #include <iostream> namespace { int c; char ** a; [[ gnu::constructor ]] void foo( int argc, char ** argv ) { a = argv; c = argc; } [[ gnu::constructor ]] void bar( int argc, char ** argv ) { asm( "" ); } } int main() { std::cerr << "argc: " << c << std::endl; std::cerr << std::hex << a << std::endl; return 0; } When compiled and run as: > g++ text.cpp -g -shared -o libMain.so -fPIC -O2 -flto -Wall -Wextra > g++ libMain.so > LD_LIBRARY_PATH=. ./a.out 4 1 2 4 A sample output is: argc: -638171435 0x7f20366efdd0 (the use of cerr is only meaningful for actually seeing output, and is not needed to reproduce the error) Using a specific and unique priority for the `gnu::constructor` attribute will lead to the arguments being passed correctly, and argc will end up correct. If the function is instead not defined inside an anonymous namespace, as just: int c; char ** a; [[ gnu::constructor ]] void foo( int argc, char ** argv ) { a = argv; c = argc; } g++ instead reports the error (using -Wall -Wextra): In function '_sub_I_65535_0': text.cpp:8:6: warning: 'argv' is used uninitialized [-Wuninitialized] 8 | a = argv; | ^ lto1: note: 'argv' was declared here text.cpp:9:6: warning: 'argc' is used uninitialized [-Wuninitialized] 9 | c = argc; | ^ lto1: note: 'argc' was declared here Using a unique constructor priority again will disable that warning. g++ (GCC) 11.3.1 20220421 (Red Hat 11.3.1-2) glibc 2.34