Clang tries to use GCC's stdatomic.h, and fails.

Consider the following source:

jscott@citra:/tmp$ cat /tmp/atomic.c
#include <stdatomic.h>

int f (atomic_int *p_x)
{
  return atomic_load(p_x);
}

On my system, Clang 3.6.1 fails to compile this, because it attempts to use GCC 5's stdatomic.h, which contains stuff it doesn't understand. [GCC 4.9's stdatomic.h fails similarly.]

jscott@citra:/tmp$ clang -std=c11 -c atomic.c
atomic.c:5:10: error: use of undeclared identifier '__auto_type'
  return atomic_load(p_x);
         ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.1.0/include/stdatomic.h:142:27: note: expanded from macro 'atomic_load'
#define atomic_load(PTR) atomic_load_explicit (PTR, __ATOMIC_SEQ_CST)
                          ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.1.0/include/stdatomic.h:136:5: note: expanded from macro 'atomic_load_explicit'
    __auto_type __atomic_load_ptr = (PTR); \
    ^
atomic.c:5:10: error: use of undeclared identifier '__atomic_load_ptr'
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.1.0/include/stdatomic.h:142:27: note: expanded from macro 'atomic_load'
#define atomic_load(PTR) atomic_load_explicit (PTR, __ATOMIC_SEQ_CST)
                          ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.1.0/include/stdatomic.h:137:18: note: expanded from macro 'atomic_load_explicit'
    __typeof__ (*__atomic_load_ptr) __atomic_load_tmp; \
                 ^
atomic.c:5:10: error: use of undeclared identifier '__atomic_load_ptr'; did you mean '__atomic_load_tmp'?
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.1.0/include/stdatomic.h:142:27: note: expanded from macro 'atomic_load'
#define atomic_load(PTR) atomic_load_explicit (PTR, __ATOMIC_SEQ_CST)
                          ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.1.0/include/stdatomic.h:138:20: note: expanded from macro 'atomic_load_explicit'
    __atomic_load (__atomic_load_ptr, &__atomic_load_tmp, (MO)); \
                   ^
atomic.c:5:10: note: '__atomic_load_tmp' declared here
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.1.0/include/stdatomic.h:142:27: note: expanded from macro 'atomic_load'
#define atomic_load(PTR) atomic_load_explicit (PTR, __ATOMIC_SEQ_CST)
                          ^
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.1.0/include/stdatomic.h:137:37: note: expanded from macro 'atomic_load_explicit'
    __typeof__ (*__atomic_load_ptr) __atomic_load_tmp; \
                                    ^
atomic.c:5:10: error: returning 'void' from a function with incompatible result type 'int'
  return atomic_load(p_x);
         ^~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.1.0/include/stdatomic.h:142:27: note: expanded from macro 'atomic_load'
#define atomic_load(PTR) atomic_load_explicit (PTR, __ATOMIC_SEQ_CST)
                          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.1.0/include/stdatomic.h:134:3: note: expanded from macro 'atomic_load_explicit'
  __extension__ \
  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
4 errors generated.

It looks like Clang has its own stdatomic.h at /usr/lib/llvm-3.6/lib/clang/3.6.1/include/stdatomic.h, but it defers to the GCC version because of this:

/* If we're hosted, fall back to the system's stdatomic.h. FreeBSD, for
* example, already has a Clang-compatible stdatomic.h header.
*/
#if __STDC_HOSTED__ && __has_include_next(<stdatomic.h>)
# include_next <stdatomic.h>
#else
...

Is there any way around this, besides hacking Clang's version of stdatomic to not do the #include_next?

Does Clang have an equivalent of __auto_type that I could try and use to get out of this?

e.g.
#define __auto_type __clangs_version_of_auto_type
#include <stdatomic.h>
?

Cheers,

John

<https://llvm.org/bugs/show_bug.cgi?id=22740&gt; suggests a workaround, but then I run into another problem, because my codebase has atomics embedded in structures which are sometimes passed using pointer-to-const.

jscott@citra:/tmp$ cat atomic.c
#undef __STDC_HOSTED__
#define __STDC_HOSTED__ 0
#include <stdatomic.h>
#undef __STDC_HOSTED__
#define __STDC_HOSTED__ 1

int f (const atomic_int *p_x)
{
  return atomic_load(p_x);
}
jscott@citra:/tmp$ clang -std=c11 -c atomic.c
atomic.c:9:10: error: address argument to atomic operation must be a pointer to non-const _Atomic type ('const atomic_int *' (aka 'const _Atomic(int) *') invalid)
  return atomic_load(p_x);
         ^ ~~~
/usr/lib/llvm-3.6/bin/../lib/clang/3.6.1/include/stdatomic.h:134:29: note: expanded from macro 'atomic_load'
#define atomic_load(object) __c11_atomic_load(object, __ATOMIC_SEQ_CST)
                            ^
1 error generated.

Reading <https://github.com/kcat/openal-soft/issues/3&gt; suggests this is technically correct with respect to the standard, but since it's not very useful, the standard is likely to change, via DR459 <http://www.open-std.org/jtc1/sc22/wg14/www/docs/dr_459.htm&gt;\.

Cheers,

John