This is on macOS 10.12 (Darwin 16.6.0). Compiling C11 code with -std=c11 fails to link, unless one specifies -latomic $ cat a.c #include <stdio.h> #include <complex.h> #include <stdatomic.h> int main(void) { _Atomic long double _Complex x = 0.0 + 0.0*I; for (int i=0; i<1000; i++) { x += 1.0; } printf("(%Lf,%Lf)\n",creall(x), cimagl(x)); printf("%zu\n",sizeof(x)); return 0; } $ gcc-7 -std=c11 a.c -latomic $ gcc-7 -std=c11 a.c Undefined symbols for architecture x86_64: "___atomic_feraiseexcept", referenced from: _main in cceeEpua.o ld: symbol(s) not found for architecture x86_64 collect2: error: ld returned 1 exit status ------ From Homebrew report at https://github.com/Homebrew/homebrew-core/issues/14633 $ gcc-7 -v Using built-in specs. COLLECT_GCC=gcc-7 COLLECT_LTO_WRAPPER=/usr/local/Cellar/gcc/7.1.0/libexec/gcc/x86_64-apple-darwin16.6.0/7.1.0/lto-wrapper Target: x86_64-apple-darwin16.6.0 Configured with: ../configure --build=x86_64-apple-darwin16.6.0 --prefix=/usr/local/Cellar/gcc/7.1.0 --libdir=/usr/local/Cellar/gcc/7.1.0/lib/gcc/7 --enable-languages=c,c++,objc,obj-c++,fortran --program-suffix=-7 --with-gmp=/usr/local/opt/gmp --with-mpfr=/usr/local/opt/mpfr --with-mpc=/usr/local/opt/libmpc --with-isl=/usr/local/opt/isl --with-system-zlib --enable-checking=release --with-pkgversion='Homebrew GCC 7.1.0' --with-bugurl=https://github.com/Homebrew/homebrew-core/issues --disable-nls --with-native-system-header-dir=/usr/include --with-sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.12.sdk Thread model: posix gcc version 7.1.0 (Homebrew GCC 7.1.0)
That seems similar to using sqrt, which requires explicitly linking with libm.
That doesn't mean that the mistake should be repeated.
See what I said in <https://gcc.gnu.org/ml/gcc-patches/2013-11/msg02605.html> - I think linking --as-needed -latomic --no-as-needed makes sense by default when --as-needed is supported. The problem would be any platforms where (a) there is no --as-needed support, but (b) shared libraries are supported and linking with a shared library introduces a dependency into the binary even if no symbols from that shared library are used.
In the libm case, POSIX has an explicit list of headers whose functions may require particular libraries to be linked in. libatomic is required for use of language features without any reference to functions from any header.
Indeed, _Atomic is a language keyword and doesn't require any headers (the inclusion of stdatomic.h in this code is superfluous), so the "header->explicit library" argument doesn't apply. In any case, I do not see why language intrinsics that require headers should require libraries. Why is sqrt() from math.h different from fprintf() from stdio.h? Maybe POSIX requires that, but ISO C11 doesn't, and I'm using -std=c11 not -std=posix. --as-needed would greatly enhance user experience for both this and libm.
The design of what's in separate libraries is historical; since it probably predates shared libraries, the reason isn't obvious (with shared libraries, before --as-needed, it avoided unnecessary runtime dependencies). The conformance documentation for an implementation as a whole (compiler plus libraries) would of course specify using -std=c11 -pedantic -lm -latomic, or whatever. For a new libc implementation for Unix-like systems it would be natural just to use libc.so for everything, subject to performance issues from causing everything to be (potentially) multithreaded by linking with pthreads functions. Note e.g. glibc moved some clock/timer functions from librt to libc a while back to avoid such issues from linking in librt. The POSIX rules for the c99 utility, which correspond more or less to the traditional division into libraries on Unix-like systems, are at: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/c99.html
This came up in the RISC-V BoF today.
See also bug 84568 and bug 86005.
I should also note the testsuite point I mentioned in the BoF, and related points about building target libraries, which mean this is more complicated than just the driver specs change: There is testsuite logic (see gcc/testsuite/lib/atomic-dg.exp) to locate libatomic for build-tree testing and set appropriate -L options and LD_LIBRARY_PATH. This is only used in gcc/testsuite/gcc.dg/atomic/atomic.exp at present. If the driver specs change to use "--as-needed -latomic --no-as-needed" whenever libatomic is built (obviously they shouldn't do so for configurations not building libatomic, whether because unsupported for the target or because disabled at configure time), linking *any* target program will then require libatomic to be somewhere that ld can find it (because ld requires a library named with -l to be somewhere it can find, even inside --as-needed; it can only know whether a library is needed after seeing what symbols it defines). Thus, that logic would need to be used globally for all testsuites. In addition, all configure tests in target libraries that run link tests, and linking of shared target libraries, would need to pass appropriate -L options to find libatomic, and we'd need to make sure the target library dependencies in toplevel Makefile.def ensure libatomic is built before other target libraries are configured for this to work. I think libgcc should still be built before libatomic and so we'd need some driver option to disable linking with libatomic that would be passed when linking shared libgcc.
All these failure modes can already be observed on riscv-linux, where -pthread implies -latomic.
RFC draft patch – also to solve an offload problem with atomic and nvptx libgomp: https://gcc.gnu.org/pipermail/gcc-patches/2020-October/556297.html See reply for what still needs to be done (esp. related to building libraries + testsuite).
*** Bug 104248 has been marked as a duplicate of this bug. ***