Bug 60932 - make stdatomic.h compatible with C++
Summary: make stdatomic.h compatible with C++
Status: RESOLVED WONTFIX
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.9.0
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-04-23 07:23 UTC by Sebastian Huber
Modified: 2017-04-09 21:01 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Sebastian Huber 2014-04-23 07:23:26 UTC
Should <stdatomic.h> work with C++?  I use GCC as a cross-compiler for RTEMS targets.  RTEMS uses Newlib as C library.  I ported the FreeBSD version of <stdatomic.h> to Newlib and use this successfully with C/C++ and GCC pre-4.9 versions.

http://svnweb.freebsd.org/base/head/sys/sys/stdatomic.h?revision=263998&view=markup

Now with GCC 4.9 I have the problem that two <stdatomic.h> files are installed, e.g.

find /opt/rtems-4.11/ -name stdatomic.h
/opt/rtems-4.11/lib64/gcc/sparc-rtems4.11/4.9.0/include/stdatomic.h
/opt/rtems-4.11/sparc-rtems4.11/include/stdatomic.h

The first is provided by GCC, the second by Newlib.  The GCC version is the one used.  Now I get this when I compile a C++ source which indirectly includes <stdatomic.h>:

sparc-rtems4.11-g++ -std=c++11 somefile.cc
/opt/rtems-4.11/lib64/gcc/sparc-rtems4.11/4.9.0/include/stdatomic.h:40:9: error: '_Atomic' does not name a type
 typedef _Atomic _Bool atomic_bool;

Is this working as intended?
Comment 1 Andrew Pinski 2014-04-23 08:56:13 UTC
The answer is no.  Use atomic for C++11 code instead (since that is what the standard defines).
Comment 2 Sebastian Huber 2014-04-23 09:13:11 UTC
So I cannot use C libraries using atomics with C++ on GCC targets?  With FreeBSD and clang this works fine.
Comment 3 Andrew Pinski 2014-04-23 09:27:20 UTC
(In reply to Sebastian Huber from comment #2)
> So I cannot use C libraries using atomics with C++ on GCC targets?  With
> FreeBSD and clang this works fine.

Until the c++ front-end implements _Atomic keyword, that is correct. 

You could exactly what FreeBSD does (but take into account gcc 4.9 c front end implementing _Atomic):
271	#if !__has_extension(c_atomic) && !__has_extension(cxx_atomic)
272	/*
273	 * No native support for _Atomic(). Place object in structure to prevent
274	 * most forms of direct non-atomic access.
275	 */
276	#define _Atomic(T)              struct { T volatile __val; }
277	#endif

But this is not correct and in most cases broken. You could also just use c++11 atomic header.
Comment 4 Sebastian Huber 2014-04-23 09:41:23 UTC
It is surely not the fault of GCC developers that C and C++ diverge more and more, but for embedded systems developers this is quite painful.

It is clear that you cannot use C++ header files from C.  So if you want to provide a library intended for C and C++ applications you must use C as the base line.  With this C++ incompatible <stdatomic.h> you cannot do this for applications requiring atomic operations.  So you are forced to provide two implementations.  I don't think this is the spirit of the atomics provided by the recent C/C++ standards.

GCC provides also a C++ compatible <stdbool.h> for example.
Comment 5 Jonathan Wakely 2014-04-23 12:57:31 UTC
(In reply to Sebastian Huber from comment #4)
> It is clear that you cannot use C++ header files from C.  So if you want to
> provide a library intended for C and C++ applications you must use C as the
> base line.  With this C++ incompatible <stdatomic.h> you cannot do this for
> applications requiring atomic operations.  So you are forced to provide two
> implementations.

Not true, I think this should work fine:

#ifdef __cplusplus
#include <atomic>
using namespace std;
#else
#include <stdatomic.h>
#endif

atomic<int> i;

int main()
{
  atomic_store(&i, 0);
  return atomic_load(&i);
}

The fact it doesn't looks like a problem with libstdc++'s <atomic> not <stdatomic.h>

I don't think we want to support the _Atomic qualifier in C++.
Comment 6 Jonathan Wakely 2014-04-23 13:01:47 UTC
(In reply to Jonathan Wakely from comment #5)
> #ifdef __cplusplus
> #include <atomic>
> using namespace std;
> #else
> #include <stdatomic.h>
> #endif
> 
> atomic<int> i;

Doh, sorry, that should say atomic_int not atomic<int>
(I changed my testcase after finding the atomic_int version failed with libstdc++)
Comment 7 Jonathan Wakely 2014-04-23 13:14:29 UTC
(In reply to Sebastian Huber from comment #2)
> With FreeBSD and clang this works fine.

Not on my freebsd host:

$ clang++ -std=c++11 a.cc
In file included from a.cc:5:
/usr/include/stdatomic.h:187:17: error: unknown type name '_Bool'
typedef _Atomic(_Bool)                  atomic_bool;
                ^
/usr/include/stdatomic.h:187:26: error: C++ requires a type specifier for all declarations
typedef _Atomic(_Bool)                  atomic_bool;
~~~~~~~                                 ^

[... and other similar errors]
Comment 8 Jonathan Wakely 2014-04-23 13:22:57 UTC
(In reply to Sebastian Huber from comment #4)
> I don't think this is the spirit of the atomics provided
> by the recent C/C++ standards.

The atomics are supposed to be roughly source-compatible, in that the relevant headers for each language define types and functions and macros with the same names and equivalent effects. But the two languages define those features in different headers.

If you want to use atomics in C, use <stdatomic.h>, and if you want to use them in C++, use <atomic> and appropriate using-declarations or a using-directive.

I've created Bug 60940 for the libstdc++ issue.
Comment 9 Sebastian Huber 2014-04-23 13:29:43 UTC
(In reply to Jonathan Wakely from comment #5)
> (In reply to Sebastian Huber from comment #4)
> > It is clear that you cannot use C++ header files from C.  So if you want to
> > provide a library intended for C and C++ applications you must use C as the
> > base line.  With this C++ incompatible <stdatomic.h> you cannot do this for
> > applications requiring atomic operations.  So you are forced to provide two
> > implementations.
> 
> Not true, I think this should work fine:
> 
> #ifdef __cplusplus
> #include <atomic>
> using namespace std;
> #else
> #include <stdatomic.h>
> #endif
> 
> atomic<int> i;
> 
> int main()
> {
>   atomic_store(&i, 0);
>   return atomic_load(&i);
> }
> 
> The fact it doesn't looks like a problem with libstdc++'s <atomic> not
> <stdatomic.h>
> 
> I don't think we want to support the _Atomic qualifier in C++.

Ok, but if I create a data structure definition like for example in example.h:

#ifdef __cplusplus
#include <atomic>
using namespace std;
#else
#include <stdatomic.h>
#endif

struct s {
  atomic_int i;
};

Who guarantees that this definition is binary compatible in C and C++?
Comment 10 Jonathan Wakely 2014-04-23 13:56:40 UTC
(In reply to Sebastian Huber from comment #9)
> Who guarantees that this definition is binary compatible in C and C++?

The compiler/stdlib implementors.

The same people who you want to guarantee that if you include <stdatomic.h> with a C++ compiler that understands the _Atomic keyword that the results will be binary compatible with C code including the same header.
Comment 11 Sebastian Huber 2014-04-23 14:05:55 UTC
Ok, I will use this

#ifdef __cplusplus
#include <atomic>
using namespace std;
#else
#include <stdatomic.h>
#endif

approach, but from my point of view this is quite an unsatisfactory user experience.
Comment 12 Patrick Pelissier 2017-04-07 17:42:50 UTC
Is the status really "wontfix"?

This makes any C library which uses stdatomic.h incompatible with g++ (and more and more C code uses stdatomic.h) which is rather bothersome. clang doesn't have this issue.

What prevent stdatomic.h to detect if it is included in C++ mode and includes C++ <atomic> instead?
Comment 13 Jonathan Wakely 2017-04-09 21:01:28 UTC
(In reply to Patrick Pelissier from comment #12)
> Is the status really "wontfix"?
> 
> This makes any C library which uses stdatomic.h incompatible with g++ (and

<stdatomic.h> is not part of the C++ standard.

> more and more C code uses stdatomic.h) which is rather bothersome. clang
> doesn't have this issue.

Clang allows the C keyword _Atomic in C++. That's not part of the C++ standard either

> What prevent stdatomic.h to detect if it is included in C++ mode and
> includes C++ <atomic> instead?

Even if it did that, it wouldn't guarantee that C's atomic_int and C++'s std::atomic_int are compatible. So you'd still need to rely on non-portable implementation-specific assumptions.