With this code in `test.c`: ``` struct S { int x; int y; int z; }; int main() { __attribute__((aligned(16))) static const _Atomic struct S a; struct S b; b = a; } ``` On x86_64 I get: ``` $ gcc test.c -latomic && ./a.out Segmentation fault (core dumped) ``` It crashes on a `lock cmpxchg16b` with the address of `a`, so I imagine the libatomic implementation is dispatching to an optimized __atomic_load case where the code assumes it can get a (mutable) lock from the object itself, and when it tries to acquire that lock it writes to `.rodata`, causing the crash.
The fix would be to have libatomic use a lock instead of the lock-free cmpxchg16b instruction to implement atomic_load. But I think this is impossible without causing incompatibility with older GCCs. Older versions of GCC (before GCC 7), and Clang to this day, emitted cmpxchg16b inline for a 16-byte atomic load when you compile with -mcx16. And thus, unfortunately, I think if libatomic switched to a lock now, it would not be compatible with those older programs.
I think _Atomic can be ignored on const qualified objects? Or maybe should even be ill-formed?
See bugs 70490 and 84563 regarding atomic_load of const. The atomic_load generic function takes a pointer-to-const-atomic argument just like any other library function that takes an argument it does not modify. It's certainly valid to do an atomic load through such a pointer in a case where the original object was not defined as const but a pointer to const was passed to the function doing the load. The question is whether it is or should be valid in the case where the object was defined as const. If it is, that would constrain code sequences used in any case where the compiler cannot see that the object definitely isn't in read-only memory, including for other operations that might only be valid for writable memory but need to interact correctly with atomic_load.
*** Bug 101439 has been marked as a duplicate of this bug. ***