https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94198
Bug ID: 94198 Summary: Placement of source file in GCC command line has impact on whether the link succeeds Product: gcc Version: 9.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: driver Assignee: unassigned at gcc dot gnu.org Reporter: ldionne.2 at gmail dot com Target Milestone: --- It seems that the position where the source file is specified to GCC has an impact on how it is linked when other `-l` options are passed. For example, the following command (with the source file specified last) fails to link: $ /usr/bin/g++-9 -L/llvm/build-linux/lib -Wl,-rpath,/llvm/build-linux/lib -nodefaultlibs -lc++ -lm -lgcc_s -lgcc -lpthread -lc -lgcc_s -lgcc go.cpp /tmp/ccusVxoZ.o: In function `main': go.cpp:(.text+0xa): undefined reference to `__cxa_allocate_exception' go.cpp:(.text+0x1a): undefined reference to `typeinfo for int' go.cpp:(.text+0x22): undefined reference to `__cxa_throw' go.cpp:(.text+0x2a): undefined reference to `__cxa_begin_catch' go.cpp:(.text+0x2f): undefined reference to `__cxa_end_catch' /tmp/ccusVxoZ.o:(.eh_frame+0x13): undefined reference to `__gxx_personality_v0' collect2: error: ld returned 1 exit status However, the same command-line with the source file specified first links successfully: $ /usr/bin/g++-9 go.cpp -L/llvm/build-linux/lib -Wl,-rpath,/llvm/build-linux/lib -nodefaultlibs -lc++ -lm -lgcc_s -lgcc -lpthread -lc -lgcc_s -lgcc <works> I've tracked it down to a difference in how `collect2` is called after the assembler. When the source file appears first (which works), `collect2` is called as: $ collect2 [...] /tmp/XXXXX.o -rpath /llvm/build-linux/lib -lc++ -lm -lgcc_s -lgcc -lpthread -lc -lgcc_s -lgcc [...] However, when the source file appears last (which fails), `collect2` is called as follows: $ collect2 [...] -rpath /llvm/build-linux/lib -lc++ -lm -lgcc_s -lgcc -lpthread -lc -lgcc_s -lgcc /tmp/XXXXX.o [...] You can notice how in the former, the temporary object file `/tmp/XXXXX.o` appears _before_ the various libraries to link, and in the latter it appears after. Because of how most linkers operate, the latter can't possibly link. Since the way GCC calls the linker with a temporary object file is an implementation detail, I believe the correct behavior here should be that in both cases, GCC passes the object file before the various libraries to link. This issue was discovered while running the libc++ conformance test suite with GCC.