Bug 81358 - libatomic not automatically linked with C11 code
Summary: libatomic not automatically linked with C11 code
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: driver (show other bugs)
Version: 7.1.1
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
Keywords: link-failure
: 104248 (view as bug list)
Depends on:
Reported: 2017-07-08 11:01 UTC by Francois-Xavier Coudert
Modified: 2022-01-26 17:28 UTC (History)
8 users (show)

See Also:
Host: x86_64-apple-darwin16.5.0
Target: x86_64-apple-darwin16.5.0
Build: x86_64-apple-darwin16.5.0
Known to work:
Known to fail:
Last reconfirmed: 2017-07-08 00:00:00


Note You need to log in before you can comment on or make changes to this bug.
Description Francois-Xavier Coudert 2017-07-08 11:01:44 UTC
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));
    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.
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)
Comment 1 Marc Glisse 2017-07-09 01:45:59 UTC
That seems similar to using sqrt, which requires explicitly linking with libm.
Comment 2 Andreas Schwab 2017-07-09 05:43:51 UTC
That doesn't mean that the mistake should be repeated.
Comment 3 joseph@codesourcery.com 2017-07-10 17:01:14 UTC
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.
Comment 4 joseph@codesourcery.com 2017-07-10 17:02:49 UTC
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 
Comment 5 Jeff Hammond 2017-07-10 17:56:18 UTC
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.
Comment 6 joseph@codesourcery.com 2017-07-10 20:02:24 UTC
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: 
Comment 7 Joseph S. Myers 2019-09-15 16:40:53 UTC
This came up in the RISC-V BoF today.
Comment 8 Andreas Schwab 2019-09-15 17:37:20 UTC
See also bug 84568 and bug 86005.
Comment 9 joseph@codesourcery.com 2019-09-16 17:51:13 UTC
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 

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 
Comment 10 Andreas Schwab 2019-09-16 19:38:19 UTC
All these failure modes can already be observed on riscv-linux, where -pthread
implies -latomic.
Comment 11 Tobias Burnus 2020-10-22 10:00:37 UTC
RFC draft patch – also to solve an offload problem with atomic and nvptx libgomp:
See reply for what still needs to be done (esp. related to building libraries + testsuite).
Comment 12 Andrew Pinski 2022-01-26 17:28:05 UTC
*** Bug 104248 has been marked as a duplicate of this bug. ***