diff mbox

[v3] updated atomic configury

Message ID 20111121182914.76e9cde9@shotwell
State New
Headers show

Commit Message

Benjamin Kosnik Nov. 22, 2011, 2:29 a.m. UTC
Here's the first step in making the libstdc++ atomic configure bits into
something that makes more sense. This consolidates the builtin parts of
the configury, such that builtins mean C++11 atomics, not C++11 atomics
mixed with pre-C++11 atomics.

I think this is mostly right, modulo my logic on the equivalency of
ATOMIC_INT_LOCK_FREE == _GLIBCXX_ATOMIC_BUILTINS_4. This is something
that should hold, IMHO.

I was expecting
the C++11 macros for lock-free properties, ie ATOMIC_BOOL_LOCK_FREE to
be either 0, 1, 2, and to be able to use them like:

#if (ATOMIC_INT_LOCK_FREE > 1)
// yes, cool, yeah!
#endif

But this doesn't seem to work. And what I have in this patch, which is

#if defined(ATOMIC_INT_LOCK_FREE)

doesn't really say the same thing...

-benjamin

tested x86/linux
tested x86/linux x cris-elf
tested x86/linux x arm-eabi-elf

Comments

Andrew MacLeod Nov. 22, 2011, 4:02 a.m. UTC | #1
On 11/21/2011 09:29 PM, Benjamin Kosnik wrote:
> Here's the first step in making the libstdc++ atomic configure bits into
> something that makes more sense. This consolidates the builtin parts of
> the configury, such that builtins mean C++11 atomics, not C++11 atomics
> mixed with pre-C++11 atomics.
>
> I think this is mostly right, modulo my logic on the equivalency of
> ATOMIC_INT_LOCK_FREE == _GLIBCXX_ATOMIC_BUILTINS_4. This is something
> that should hold, IMHO.
>

Well, I guess it should.  _GLIBCXX_ATOMIC_BUILTINS_4 is defined as an 
'int' in the configure file, even if an 'int' isn't 4 bytes for some 
target.  So that should work for backwards compatibility.

If you really want it to be 4 bytes you would have to use 
__atomic_always_lock_free (4) then its not dependent on the sizeof(int).

> I was expecting
> the C++11 macros for lock-free properties, ie ATOMIC_BOOL_LOCK_FREE to
> be either 0, 1, 2, and to be able to use them like:
>
> #if (ATOMIC_INT_LOCK_FREE>  1)
> // yes, cool, yeah!
> #endif
>
> But this doesn't seem to work. And what I have in this patch, which is

That should work.  The __atomic_always_lock_free(X) does fold to a 
compile time constant... but perhaps it doesn't fold early enough to be 
used by the preprocessor?

oh, I see you changed it to:

#define __LOCK_FREE_PROPERTY(T) (__atomic_always_lock_free(sizeof(T), 0) ? 2 : __atomic_is_lock_free(sizeof(T)))

The problem with that is that under the new regime, if an atomic size is 
not *always* lock free, then __atomic_is_lock_free() becomes a runtime 
libary call.   So this definition you have will resolve to either a 2, 
or a runtime function call.

All we can now tell at compile time is whether something is a 2 or 
not.   __atomic_always_lock_free() was created to be the compile time 
version that never resolves to a library call, so you can set the macro 
to either 2 if its true, or 1 if its false like I had before.   we will 
never, ever, set the macro to a value of 0.

Anyway, it looks like __atomic_always_lock_free doesn't fold early 
enough to be usable by the preprocessor like that even with my earlier 
version. ugg.  I think I can get something defined in cpp-builtins that 
we can use.   We're going to need it for C1x next release anyway.  
Should be ready to try tomorrow sometime.

Andrew
Andrew MacLeod Nov. 22, 2011, 5:19 a.m. UTC | #2
On 11/21/2011 11:02 PM, Andrew MacLeod wrote:
>
> Anyway, it looks like __atomic_always_lock_free doesn't fold early 
> enough to be usable by the preprocessor like that even with my earlier 
> version. ugg.  I think I can get something defined in cpp-builtins 
> that we can use.   We're going to need it for C1x next release 
> anyway.  Should be ready to try tomorrow sometime.
>
>
Ok, try this.  I've changed CPP to define a set of macros
__GCC_ATOMIC_{TYPE}_IS_LOCK_FREE
which we can use directly in the c++ header.  We're going to need 
something like this for C1x next release when stdatomic.h defines the 
same macros.

C currently doesn't have a char16_t and char32_t, so they aren't defined 
there. I defined them in the C++ header with the appropriate 
HAVE_COMPARE_AND_SWAP.

this should make things work the way you were looking for, ie

#if (ATOMIC_INT_LOCK_FREE>  1)
// yes, cool, yeah!
#endif

should work just fine.

Give it a shot and see if you get what you are looking for.  Ive 
bootstrapped this on x86_64-unknown-linux-gnu, and didn't see any 
regressions in libstdc++-v3...   Im running a full bootstrap and 
testsuite run overnight

Andrew
* c-cppbuiltin.c (cpp_atomic_builtins): New.  Emit all atomic
	predefines in one place.  Add LOCK_FREE predefines.
	(c_cpp_builtins): Move Legacy HAVE_SYNC predefines to new func.
	* include/bits/atomic_base.h (ATOMIC_TYPE_LOCK_FREE): Use new cpp
	predefined macros.


Index: gcc/c-family/c-cppbuiltin.c
===================================================================
*** gcc/c-family/c-cppbuiltin.c	(revision 181584)
--- gcc/c-family/c-cppbuiltin.c	(working copy)
*************** c_cpp_builtins_optimize_pragma (cpp_read
*** 568,573 ****
--- 568,672 ----
  }
  
  
+ /* This function will emit cpp macros to indicate the presence of various lock
+    free atomic operations.  */
+    
+ static void
+ cpp_atomic_builtins (cpp_reader *pfile)
+ {
+   /* Set a flag for each size of object that compare and swap exists for up to
+      a 16 byte object.  */
+ #define SWAP_LIMIT  17
+   bool have_swap[SWAP_LIMIT];
+ 
+   /* Clear the map of sizes compare_and swap exists for.  */
+   memset (have_swap, 0, sizeof (have_swap));
+ 
+   /* Tell source code if the compiler makes sync_compare_and_swap
+      builtins available.  */
+ #ifndef HAVE_sync_compare_and_swapqi
+ #define HAVE_sync_compare_and_swapqi 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swapqi
+ #define HAVE_atomic_compare_and_swapqi 0
+ #endif
+ 
+   if (HAVE_sync_compare_and_swapqi || HAVE_atomic_compare_and_swapqi)
+     {
+       cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+       have_swap[1] = true;
+     }
+ 
+ #ifndef HAVE_sync_compare_and_swaphi
+ #define HAVE_sync_compare_and_swaphi 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swaphi
+ #define HAVE_atomic_compare_and_swaphi 0
+ #endif
+   if (HAVE_sync_compare_and_swaphi || HAVE_atomic_compare_and_swaphi)
+     {
+       cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+       have_swap[2] = true;
+     }
+ 
+ #ifndef HAVE_sync_compare_and_swapsi
+ #define HAVE_sync_compare_and_swapsi 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swapsi
+ #define HAVE_atomic_compare_and_swapsi 0
+ #endif
+   if (HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi)
+     {
+       cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+       have_swap[4] = true;
+     }
+ 
+ #ifndef HAVE_sync_compare_and_swapdi
+ #define HAVE_sync_compare_and_swapdi 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swapdi
+ #define HAVE_atomic_compare_and_swapdi 0
+ #endif
+   if (HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi)
+     {
+       cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+       have_swap[8] = true;
+     }
+ 
+ #ifndef HAVE_sync_compare_and_swapti
+ #define HAVE_sync_compare_and_swapti 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swapti
+ #define HAVE_atomic_compare_and_swapti 0
+ #endif
+   if (HAVE_sync_compare_and_swapti || HAVE_atomic_compare_and_swapti)
+     {
+       cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16");
+       have_swap[16] = true;
+     }
+ 
+   /* Tell the source code about various types.  These map to the C++11 and C1x
+      macros where 2 indicates lock-free always, and 1 indicates sometimes
+      lock free.  */
+ #define SWAP_INDEX(I) ( ((I) < SWAP_LIMIT) ? I : 0)
+   builtin_define_with_int_value ("__GCC_ATOMIC_BOOL_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (sizeof(bool))]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_CHAR_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (sizeof(char))]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_WCHAR_T_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (sizeof(wchar_t))]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_SHORT_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (sizeof(short))]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_INT_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (sizeof(int))]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_LONG_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (sizeof(long))]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_LLONG_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (sizeof(long long))]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_ADDRESS_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (sizeof(void *))]? 2 : 1));
+ }
+ 
  /* Hook that registers front end and target-specific built-ins.  */
  void
  c_cpp_builtins (cpp_reader *pfile)
*************** c_cpp_builtins (cpp_reader *pfile)
*** 756,808 ****
    if (c_dialect_cxx () && TYPE_UNSIGNED (wchar_type_node))
      cpp_define (pfile, "__WCHAR_UNSIGNED__");
  
!   /* Tell source code if the compiler makes sync_compare_and_swap
!      builtins available.  */
! #ifndef HAVE_sync_compare_and_swapqi
! #define HAVE_sync_compare_and_swapqi 0
! #endif
! #ifndef HAVE_atomic_compare_and_swapqi
! #define HAVE_atomic_compare_and_swapqi 0
! #endif
!   if (HAVE_sync_compare_and_swapqi || HAVE_atomic_compare_and_swapqi)
!     cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
! 
! #ifndef HAVE_sync_compare_and_swaphi
! #define HAVE_sync_compare_and_swaphi 0
! #endif
! #ifndef HAVE_atomic_compare_and_swaphi
! #define HAVE_atomic_compare_and_swaphi 0
! #endif
!   if (HAVE_sync_compare_and_swaphi || HAVE_atomic_compare_and_swaphi)
!     cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
! 
! #ifndef HAVE_sync_compare_and_swapsi
! #define HAVE_sync_compare_and_swapsi 0
! #endif
! #ifndef HAVE_atomic_compare_and_swapsi
! #define HAVE_atomic_compare_and_swapsi 0
! #endif
!   if (HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi)
!     cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
! 
! #ifndef HAVE_sync_compare_and_swapdi
! #define HAVE_sync_compare_and_swapdi 0
! #endif
! #ifndef HAVE_atomic_compare_and_swapdi
! #define HAVE_atomic_compare_and_swapdi 0
! #endif
!   if (HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi)
!     cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
! 
! #ifndef HAVE_sync_compare_and_swapti
! #define HAVE_sync_compare_and_swapti 0
! #endif
! #ifndef HAVE_atomic_compare_and_swapti
! #define HAVE_atomic_compare_and_swapti 0
! #endif
!   if (HAVE_sync_compare_and_swapti || HAVE_atomic_compare_and_swapti)
!     cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16");
! 
  #ifdef DWARF2_UNWIND_INFO
    if (dwarf2out_do_cfi_asm ())
      cpp_define (pfile, "__GCC_HAVE_DWARF2_CFI_ASM");
--- 855,862 ----
    if (c_dialect_cxx () && TYPE_UNSIGNED (wchar_type_node))
      cpp_define (pfile, "__WCHAR_UNSIGNED__");
  
!   cpp_atomic_builtins (pfile);
!     
  #ifdef DWARF2_UNWIND_INFO
    if (dwarf2out_do_cfi_asm ())
      cpp_define (pfile, "__GCC_HAVE_DWARF2_CFI_ASM");
Index: libstdc++-v3/include/bits/atomic_base.h
===================================================================
*** libstdc++-v3/include/bits/atomic_base.h	(revision 181584)
--- libstdc++-v3/include/bits/atomic_base.h	(working copy)
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
*** 91,108 ****
  
    /// Lock-free Property
  
- #define LOCKFREE_PROP(T) (__atomic_always_lock_free (sizeof (T), 0) ? 2 : 1)
  
! #define ATOMIC_BOOL_LOCK_FREE		LOCKFREE_PROP (bool)
! #define ATOMIC_CHAR_LOCK_FREE 		LOCKFREE_PROP (char)
! #define ATOMIC_CHAR16_T_LOCK_FREE	LOCKFREE_PROP (char16_t)
! #define ATOMIC_CHAR32_T_LOCK_FREE	LOCKFREE_PROP (char32_t)
! #define ATOMIC_WCHAR_T_LOCK_FREE	LOCKFREE_PROP (wchar_t)
! #define ATOMIC_SHORT_LOCK_FREE		LOCKFREE_PROP (short)
! #define ATOMIC_INT_LOCK_FREE		LOCKFREE_PROP (int)
! #define ATOMIC_LONG_LOCK_FREE		LOCKFREE_PROP (long)
! #define ATOMIC_LLONG_LOCK_FREE		LOCKFREE_PROP (long long)
! #define ATOMIC_POINTER_LOCK_FREE	LOCKFREE_PROP (void *)
  
    // Base types for atomics.
    template<typename _IntTp>
--- 91,117 ----
  
    /// Lock-free Property
  
  
! #ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2
! #define ATOMIC_CHAR16_T_LOCK_FREE	2
! #else
! #define ATOMIC_CHAR16_T_LOCK_FREE	1
! #endif
! 
! #ifdef __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4
! #define ATOMIC_CHAR32_T_LOCK_FREE	2
! #else
! #define ATOMIC_CHAR32_T_LOCK_FREE	1
! #endif
! 
! #define ATOMIC_BOOL_LOCK_FREE		__GCC_ATOMIC_BOOL_LOCK_FREE
! #define ATOMIC_CHAR_LOCK_FREE		__GCC_ATOMIC_CHAR_LOCK_FREE
! #define ATOMIC_WCHAR_T_LOCK_FREE	__GCC_ATOMIC_WCHAR_T_LOCK_FREE
! #define ATOMIC_SHORT_LOCK_FREE		__GCC_ATOMIC_SHORT_LOCK_FREE
! #define ATOMIC_INT_LOCK_FREE		__GCC_ATOMIC_INT_LOCK_FREE
! #define ATOMIC_LONG_LOCK_FREE		__GCC_ATOMIC_LONG_LOCK_FREE
! #define ATOMIC_LLONG_LOCK_FREE		__GCC_ATOMIC_LLONG_LOCK_FREE
! #define ATOMIC_POINTER_LOCK_FREE	__GCC_ATOMIC_POINTER_LOCK_FREE
  
    // Base types for atomics.
    template<typename _IntTp>
Joseph Myers Nov. 22, 2011, 3:32 p.m. UTC | #3
On Tue, 22 Nov 2011, Andrew MacLeod wrote:

> C currently doesn't have a char16_t and char32_t, so they aren't defined

It certainly does have those types, as typedefs defined in <uchar.h> for 
the same types as uint_least16_t and uint_least32_t.  And <stdatomic.h> is 
also required to define ATOMIC_CHAR16_T_LOCK_FREE and 
ATOMIC_CHAR32_T_LOCK_FREE.

Your code in c-cppbuiltin.c appears to be using sizeof applied to *host* 
types, which is definitely wrong.  You need to examine the precision of 
the relevant tree nodes.
Andrew MacLeod Nov. 22, 2011, 6:13 p.m. UTC | #4
On 11/22/2011 10:32 AM, Joseph S. Myers wrote:
> On Tue, 22 Nov 2011, Andrew MacLeod wrote:
>
>> C currently doesn't have a char16_t and char32_t, so they aren't defined
> It certainly does have those types, as typedefs defined in<uchar.h>  for
> the same types as uint_least16_t and uint_least32_t.  And<stdatomic.h>  is
> also required to define ATOMIC_CHAR16_T_LOCK_FREE and
> ATOMIC_CHAR32_T_LOCK_FREE.
but there isn't a stdatomic.h until we support C1x right? didnt we bail 
on that last release until things were more settled?   I just presumed 
that those types are part of C1x and then fix it all up for C1x support 
in the next release since I don't think we are yet.
> Your code in c-cppbuiltin.c appears to be using sizeof applied to *host*
> types, which is definitely wrong.  You need to examine the precision of
> the relevant tree nodes.
>
hmm, yeah I was thinking that file was compiled for the target, so it 
would work.  Guess its a host file so I do need to look at the nodes 
instead:-P
Joseph Myers Nov. 22, 2011, 8:48 p.m. UTC | #5
On Tue, 22 Nov 2011, Andrew MacLeod wrote:

> On 11/22/2011 10:32 AM, Joseph S. Myers wrote:
> > On Tue, 22 Nov 2011, Andrew MacLeod wrote:
> > 
> > > C currently doesn't have a char16_t and char32_t, so they aren't defined
> > It certainly does have those types, as typedefs defined in<uchar.h>  for
> > the same types as uint_least16_t and uint_least32_t.  And<stdatomic.h>  is
> > also required to define ATOMIC_CHAR16_T_LOCK_FREE and
> > ATOMIC_CHAR32_T_LOCK_FREE.
> but there isn't a stdatomic.h until we support C1x right? didnt we bail on

It still seems better to predefine the macros for those types, using 
char16_type_node and char32_type_node, using them initially for C++ and 
then later for C as well.
Andrew MacLeod Nov. 28, 2011, 2:35 p.m. UTC | #6
On 11/22/2011 03:48 PM, Joseph S. Myers wrote:
> On Tue, 22 Nov 2011, Andrew MacLeod wrote:
>
>>>
>>> It certainly does have those types, as typedefs defined in<uchar.h>   for
>>> the same types as uint_least16_t and uint_least32_t.  And<stdatomic.h>   is
>>> also required to define ATOMIC_CHAR16_T_LOCK_FREE and
>>> ATOMIC_CHAR32_T_LOCK_FREE.
>> but there isn't a stdatomic.h until we support C1x right? didnt we bail on
> It still seems better to predefine the macros for those types, using
> char16_type_node and char32_type_node, using them initially for C++ and
> then later for C as well.
>
OK, here's a reworked patch.  This bootstraps but there is a 
regression... one set of PCH tests fail in a very odd way. I've 
investigated it and it turns out that for some reason,  ptr_type_node 
doesn't always have it size set if code isn't being generated (all the 
other nodes do)... in particular I can reproduce it on a small test case 
on my x86-64 machine where size is 8 when generating code, and 0 if -E 
is used to output pre-processed source.  I'm looking into that today.

Question, the purpose of the testcase in the patch  macros.c...  is it 
to simply test for standard compliance, or to test both compliance PLUS 
what we expect?  I made the change assuming the latter.  We will always 
generate a 1 or a 2 for the macros, and we also want the macros to now 
be compile time satisfied so they can be used in #if statements like 
bkoz was trying to do.

Andrew
c-family
	* c-cpp-builtin.c (cpp_atomic_builtins):New.  Emit all atomic
	predefines in one place.  Add LOCK_FREE predefines.
	(c_cpp_builtins): Move Legacy HAVE_SYNC predefines to
	new func.

	libstdc++-v3
	* include/bits/atomic_base.h (ATOMIC_*_LOCK_FREE): Use new cpp
	predefined macros.
	* testsuite/29_atomics/headers/atomic/macros.cc: Add BOOL and POINTER
	macro checks.  Check for expected compile time values.

Index: gcc/c-family/c-cppbuiltin.c
===================================================================
*** gcc/c-family/c-cppbuiltin.c	(revision 181698)
--- gcc/c-family/c-cppbuiltin.c	(working copy)
*************** c_cpp_builtins_optimize_pragma (cpp_read
*** 568,573 ****
--- 568,677 ----
  }
  
  
+ /* This function will emit cpp macros to indicate the presence of various lock
+    free atomic operations.  */
+    
+ static void
+ cpp_atomic_builtins (cpp_reader *pfile)
+ {
+   /* Set a flag for each size of object that compare and swap exists for up to
+      a 16 byte object.  */
+ #define SWAP_LIMIT  17
+   bool have_swap[SWAP_LIMIT];
+ 
+   /* Clear the map of sizes compare_and swap exists for.  */
+   memset (have_swap, 0, sizeof (have_swap));
+ 
+   /* Tell source code if the compiler makes sync_compare_and_swap
+      builtins available.  */
+ #ifndef HAVE_sync_compare_and_swapqi
+ #define HAVE_sync_compare_and_swapqi 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swapqi
+ #define HAVE_atomic_compare_and_swapqi 0
+ #endif
+ 
+   if (HAVE_sync_compare_and_swapqi || HAVE_atomic_compare_and_swapqi)
+     {
+       cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+       have_swap[1] = true;
+     }
+ 
+ #ifndef HAVE_sync_compare_and_swaphi
+ #define HAVE_sync_compare_and_swaphi 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swaphi
+ #define HAVE_atomic_compare_and_swaphi 0
+ #endif
+   if (HAVE_sync_compare_and_swaphi || HAVE_atomic_compare_and_swaphi)
+     {
+       cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+       have_swap[2] = true;
+     }
+ 
+ #ifndef HAVE_sync_compare_and_swapsi
+ #define HAVE_sync_compare_and_swapsi 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swapsi
+ #define HAVE_atomic_compare_and_swapsi 0
+ #endif
+   if (HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi)
+     {
+       cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+       have_swap[4] = true;
+     }
+ 
+ #ifndef HAVE_sync_compare_and_swapdi
+ #define HAVE_sync_compare_and_swapdi 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swapdi
+ #define HAVE_atomic_compare_and_swapdi 0
+ #endif
+   if (HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi)
+     {
+       cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+       have_swap[8] = true;
+     }
+ 
+ #ifndef HAVE_sync_compare_and_swapti
+ #define HAVE_sync_compare_and_swapti 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swapti
+ #define HAVE_atomic_compare_and_swapti 0
+ #endif
+   if (HAVE_sync_compare_and_swapti || HAVE_atomic_compare_and_swapti)
+     {
+       cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16");
+       have_swap[16] = true;
+     }
+ 
+   /* Tell the source code about various types.  These map to the C++11 and C1x
+      macros where 2 indicates lock-free always, and 1 indicates sometimes
+      lock free.  */
+ #define SIZEOF_NODE(T) (tree_low_cst (TYPE_SIZE_UNIT (T), 1))
+ #define SWAP_INDEX(T) ((SIZEOF_NODE (T) < SWAP_LIMIT) ? SIZEOF_NODE (T) : 0)
+   builtin_define_with_int_value ("__GCC_ATOMIC_BOOL_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (boolean_type_node)]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_CHAR_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (signed_char_type_node)]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_CHAR16_T_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (char16_type_node)]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_CHAR32_T_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (char32_type_node)]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_WCHAR_T_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (wchar_type_node)]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_SHORT_LOCK_FREE", 
+ 		      (have_swap[SWAP_INDEX (short_integer_type_node)]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_INT_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (integer_type_node)]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_LONG_LOCK_FREE", 
+ 		      (have_swap[SWAP_INDEX (long_integer_type_node)]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_LLONG_LOCK_FREE", 
+ 		(have_swap[SWAP_INDEX (long_long_integer_type_node)]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_POINTER_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (ptr_type_node)]? 2 : 1));
+ }
+ 
  /* Hook that registers front end and target-specific built-ins.  */
  void
  c_cpp_builtins (cpp_reader *pfile)
*************** c_cpp_builtins (cpp_reader *pfile)
*** 756,808 ****
    if (c_dialect_cxx () && TYPE_UNSIGNED (wchar_type_node))
      cpp_define (pfile, "__WCHAR_UNSIGNED__");
  
!   /* Tell source code if the compiler makes sync_compare_and_swap
!      builtins available.  */
! #ifndef HAVE_sync_compare_and_swapqi
! #define HAVE_sync_compare_and_swapqi 0
! #endif
! #ifndef HAVE_atomic_compare_and_swapqi
! #define HAVE_atomic_compare_and_swapqi 0
! #endif
!   if (HAVE_sync_compare_and_swapqi || HAVE_atomic_compare_and_swapqi)
!     cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
! 
! #ifndef HAVE_sync_compare_and_swaphi
! #define HAVE_sync_compare_and_swaphi 0
! #endif
! #ifndef HAVE_atomic_compare_and_swaphi
! #define HAVE_atomic_compare_and_swaphi 0
! #endif
!   if (HAVE_sync_compare_and_swaphi || HAVE_atomic_compare_and_swaphi)
!     cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
! 
! #ifndef HAVE_sync_compare_and_swapsi
! #define HAVE_sync_compare_and_swapsi 0
! #endif
! #ifndef HAVE_atomic_compare_and_swapsi
! #define HAVE_atomic_compare_and_swapsi 0
! #endif
!   if (HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi)
!     cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
! 
! #ifndef HAVE_sync_compare_and_swapdi
! #define HAVE_sync_compare_and_swapdi 0
! #endif
! #ifndef HAVE_atomic_compare_and_swapdi
! #define HAVE_atomic_compare_and_swapdi 0
! #endif
!   if (HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi)
!     cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
! 
! #ifndef HAVE_sync_compare_and_swapti
! #define HAVE_sync_compare_and_swapti 0
! #endif
! #ifndef HAVE_atomic_compare_and_swapti
! #define HAVE_atomic_compare_and_swapti 0
! #endif
!   if (HAVE_sync_compare_and_swapti || HAVE_atomic_compare_and_swapti)
!     cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16");
! 
  #ifdef DWARF2_UNWIND_INFO
    if (dwarf2out_do_cfi_asm ())
      cpp_define (pfile, "__GCC_HAVE_DWARF2_CFI_ASM");
--- 860,867 ----
    if (c_dialect_cxx () && TYPE_UNSIGNED (wchar_type_node))
      cpp_define (pfile, "__WCHAR_UNSIGNED__");
  
!   cpp_atomic_builtins (pfile);
!     
  #ifdef DWARF2_UNWIND_INFO
    if (dwarf2out_do_cfi_asm ())
      cpp_define (pfile, "__GCC_HAVE_DWARF2_CFI_ASM");
Index: libstdc++-v3/include/bits/atomic_base.h
===================================================================
*** libstdc++-v3/include/bits/atomic_base.h	(revision 181698)
--- libstdc++-v3/include/bits/atomic_base.h	(working copy)
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
*** 91,108 ****
  
    /// Lock-free Property
  
- #define LOCKFREE_PROP(T) (__atomic_always_lock_free (sizeof (T), 0) ? 2 : 1)
  
! #define ATOMIC_BOOL_LOCK_FREE		LOCKFREE_PROP (bool)
! #define ATOMIC_CHAR_LOCK_FREE 		LOCKFREE_PROP (char)
! #define ATOMIC_CHAR16_T_LOCK_FREE	LOCKFREE_PROP (char16_t)
! #define ATOMIC_CHAR32_T_LOCK_FREE	LOCKFREE_PROP (char32_t)
! #define ATOMIC_WCHAR_T_LOCK_FREE	LOCKFREE_PROP (wchar_t)
! #define ATOMIC_SHORT_LOCK_FREE		LOCKFREE_PROP (short)
! #define ATOMIC_INT_LOCK_FREE		LOCKFREE_PROP (int)
! #define ATOMIC_LONG_LOCK_FREE		LOCKFREE_PROP (long)
! #define ATOMIC_LLONG_LOCK_FREE		LOCKFREE_PROP (long long)
! #define ATOMIC_POINTER_LOCK_FREE	LOCKFREE_PROP (void *)
  
    // Base types for atomics.
    template<typename _IntTp>
--- 91,107 ----
  
    /// Lock-free Property
  
  
! #define ATOMIC_BOOL_LOCK_FREE		__GCC_ATOMIC_BOOL_LOCK_FREE
! #define ATOMIC_CHAR_LOCK_FREE		__GCC_ATOMIC_CHAR_LOCK_FREE
! #define ATOMIC_WCHAR_T_LOCK_FREE	__GCC_ATOMIC_WCHAR_T_LOCK_FREE
! #define ATOMIC_CHAR16_T_LOCK_FREE	__GCC_ATOMIC_CHAR16_T_LOCK_FREE
! #define ATOMIC_CHAR32_T_LOCK_FREE	__GCC_ATOMIC_CHAR32_T_LOCK_FREE
! #define ATOMIC_SHORT_LOCK_FREE		__GCC_ATOMIC_SHORT_LOCK_FREE
! #define ATOMIC_INT_LOCK_FREE		__GCC_ATOMIC_INT_LOCK_FREE
! #define ATOMIC_LONG_LOCK_FREE		__GCC_ATOMIC_LONG_LOCK_FREE
! #define ATOMIC_LLONG_LOCK_FREE		__GCC_ATOMIC_LLONG_LOCK_FREE
! #define ATOMIC_POINTER_LOCK_FREE	__GCC_ATOMIC_POINTER_LOCK_FREE
  
    // Base types for atomics.
    template<typename _IntTp>
Index: libstdc++-v3/testsuite/29_atomics/headers/atomic/macros.cc
===================================================================
*** libstdc++-v3/testsuite/29_atomics/headers/atomic/macros.cc	(revision 181698)
--- libstdc++-v3/testsuite/29_atomics/headers/atomic/macros.cc	(working copy)
***************
*** 20,25 ****
--- 20,29 ----
  
  #include <atomic>
  
+ #ifndef ATOMIC_BOOL_LOCK_FREE 
+ # error "ATOMIC_BOOL_LOCK_FREE must be a macro"
+ #endif
+ 
  #ifndef ATOMIC_CHAR_LOCK_FREE 
  # error "ATOMIC_CHAR_LOCK_FREE must be a macro"
  #endif
***************
*** 52,57 ****
--- 56,65 ----
  # error "ATOMIC_LLONG_LOCK_FREE must be a macro"
  #endif
  
+ #ifndef ATOMIC_POINTER_LOCK_FREE 
+ # error "ATOMIC_POINTER_LOCK_FREE must be a macro"
+ #endif
+ 
  #ifndef ATOMIC_FLAG_INIT
      #error "ATOMIC_FLAG_INIT_must_be_a_macro"
  #endif
*************** extern void abort(void);
*** 65,99 ****
  
  int main ()
  {
!  if (ATOMIC_CHAR_LOCK_FREE != 0 && ATOMIC_CHAR_LOCK_FREE != 1
!      && ATOMIC_CHAR_LOCK_FREE != 2)
     abort ();
  
!  if (ATOMIC_CHAR16_T_LOCK_FREE != 0 && ATOMIC_CHAR16_T_LOCK_FREE != 1
!      && ATOMIC_CHAR16_T_LOCK_FREE != 2)
     abort ();
  
!  if (ATOMIC_CHAR32_T_LOCK_FREE != 0 && ATOMIC_CHAR32_T_LOCK_FREE != 1
!      && ATOMIC_CHAR32_T_LOCK_FREE != 2)
     abort ();
  
!  if (ATOMIC_WCHAR_T_LOCK_FREE != 0 && ATOMIC_WCHAR_T_LOCK_FREE != 1
!      && ATOMIC_WCHAR_T_LOCK_FREE != 2)
     abort ();
  
!  if (ATOMIC_SHORT_LOCK_FREE != 0 && ATOMIC_SHORT_LOCK_FREE != 1
!      && ATOMIC_SHORT_LOCK_FREE != 2)
     abort ();
  
!  if (ATOMIC_INT_LOCK_FREE != 0 && ATOMIC_INT_LOCK_FREE != 1
!      && ATOMIC_INT_LOCK_FREE != 2)
     abort ();
  
!  if (ATOMIC_LONG_LOCK_FREE != 0 && ATOMIC_LONG_LOCK_FREE != 1
!      && ATOMIC_LONG_LOCK_FREE != 2)
     abort ();
  
!  if (ATOMIC_LLONG_LOCK_FREE != 0 && ATOMIC_LLONG_LOCK_FREE != 1
!      && ATOMIC_LLONG_LOCK_FREE != 2)
     abort ();
  }
--- 73,115 ----
  
  int main ()
  {
! #if (ATOMIC_BOOL_LOCK_FREE != 1 && ATOMIC_BOOL_LOCK_FREE != 2)
!    abort ();
! #endif
! 
! #if (ATOMIC_CHAR_LOCK_FREE != 1 && ATOMIC_CHAR_LOCK_FREE != 2)
!    abort ();
! #endif
! 
! #if (ATOMIC_CHAR16_T_LOCK_FREE != 1 && ATOMIC_CHAR16_T_LOCK_FREE != 2)
     abort ();
+ #endif
  
! #if (ATOMIC_CHAR32_T_LOCK_FREE != 1 && ATOMIC_CHAR32_T_LOCK_FREE != 2)
     abort ();
+ #endif
  
! #if (ATOMIC_WCHAR_T_LOCK_FREE != 1 && ATOMIC_WCHAR_T_LOCK_FREE != 2)
     abort ();
+ #endif
  
! #if (ATOMIC_SHORT_LOCK_FREE != 1 && ATOMIC_SHORT_LOCK_FREE != 2)
     abort ();
+ #endif
  
! #if (ATOMIC_INT_LOCK_FREE != 1 && ATOMIC_INT_LOCK_FREE != 2)
     abort ();
+ #endif
  
! #if (ATOMIC_LONG_LOCK_FREE != 1 && ATOMIC_LONG_LOCK_FREE != 2)
     abort ();
+ #endif
  
! #if (ATOMIC_LLONG_LOCK_FREE != 1 && ATOMIC_LLONG_LOCK_FREE != 2)
     abort ();
+ #endif
  
! #if (ATOMIC_POINTER_LOCK_FREE != 1 && ATOMIC_POINTER_LOCK_FREE != 2)
     abort ();
+ #endif
  }
Joseph Myers Nov. 28, 2011, 4:42 p.m. UTC | #7
On Mon, 28 Nov 2011, Andrew MacLeod wrote:

> OK, here's a reworked patch.  This bootstraps but there is a regression... one
> set of PCH tests fail in a very odd way. I've investigated it and it turns out
> that for some reason,  ptr_type_node doesn't always have it size set if code
> isn't being generated (all the other nodes do)... in particular I can
> reproduce it on a small test case on my x86-64 machine where size is 8 when
> generating code, and 0 if -E is used to output pre-processed source.  I'm
> looking into that today.

That would be why cppbuiltin.c, defining __SIZEOF_POINTER__, needs to use 
the POINTER_SIZE macro instead of directly using ptr_type_node.  You may 
need to do something similar.

  /* ptr_type_node can't be used here since ptr_mode is only set when
     toplev calls backend_init which is not done with -E switch.  */
  cpp_define_formatted (pfile, "__SIZEOF_POINTER__=%d",
                        POINTER_SIZE / BITS_PER_UNIT);

> Question, the purpose of the testcase in the patch  macros.c...  is it to
> simply test for standard compliance, or to test both compliance PLUS what we
> expect?  I made the change assuming the latter.  We will always generate a 1
> or a 2 for the macros, and we also want the macros to now be compile time
> satisfied so they can be used in #if statements like bkoz was trying to do.

Yes, test that the macros do what we expect.
Andrew MacLeod Nov. 28, 2011, 7:29 p.m. UTC | #8
On 11/28/2011 11:42 AM, Joseph S. Myers wrote:
> On Mon, 28 Nov 2011, Andrew MacLeod wrote:
>
> That would be why cppbuiltin.c, defining __SIZEOF_POINTER__, needs to use
> the POINTER_SIZE macro instead of directly using ptr_type_node.  You may
> need to do something similar.
>
>    /* ptr_type_node can't be used here since ptr_mode is only set when
>       toplev calls backend_init which is not done with -E switch.  */
>    cpp_define_formatted (pfile, "__SIZEOF_POINTER__=%d",
>                          POINTER_SIZE / BITS_PER_UNIT);
>
How bizarre...  thanks you saved me some hair pulling I'm sure :-)  That 
does work, here's a patch which does that..
bootstraps on x86_64-unknown-linux-gnu and has no new regressions.  OK 
for mainline?

Andrew
c-family
	* c-cpp-builtin.c (cpp_atomic_builtins):New.  Emit all atomic
	predefines in one place.  Add LOCK_FREE predefines.
	(c_cpp_builtins): Move Legacy HAVE_SYNC predefines to
	new func.

	libstdc++-v3
	* include/bits/atomic_base.h (ATOMIC_*_LOCK_FREE): Use new cpp
	predefined macros.
	* testsuite/29_atomics/headers/atomic/macros.cc: Add BOOL and POINTER
	macro checks.  Check for expected compile time values.

Index: gcc/c-family/c-cppbuiltin.c
===================================================================
*** gcc/c-family/c-cppbuiltin.c	(revision 181698)
--- gcc/c-family/c-cppbuiltin.c	(working copy)
*************** c_cpp_builtins_optimize_pragma (cpp_read
*** 568,573 ****
--- 568,684 ----
  }
  
  
+ /* This function will emit cpp macros to indicate the presence of various lock
+    free atomic operations.  */
+    
+ static void
+ cpp_atomic_builtins (cpp_reader *pfile)
+ {
+   /* Set a flag for each size of object that compare and swap exists for up to
+      a 16 byte object.  */
+ #define SWAP_LIMIT  17
+   bool have_swap[SWAP_LIMIT];
+   unsigned int psize;
+ 
+   /* Clear the map of sizes compare_and swap exists for.  */
+   memset (have_swap, 0, sizeof (have_swap));
+ 
+   /* Tell source code if the compiler makes sync_compare_and_swap
+      builtins available.  */
+ #ifndef HAVE_sync_compare_and_swapqi
+ #define HAVE_sync_compare_and_swapqi 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swapqi
+ #define HAVE_atomic_compare_and_swapqi 0
+ #endif
+ 
+   if (HAVE_sync_compare_and_swapqi || HAVE_atomic_compare_and_swapqi)
+     {
+       cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
+       have_swap[1] = true;
+     }
+ 
+ #ifndef HAVE_sync_compare_and_swaphi
+ #define HAVE_sync_compare_and_swaphi 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swaphi
+ #define HAVE_atomic_compare_and_swaphi 0
+ #endif
+   if (HAVE_sync_compare_and_swaphi || HAVE_atomic_compare_and_swaphi)
+     {
+       cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
+       have_swap[2] = true;
+     }
+ 
+ #ifndef HAVE_sync_compare_and_swapsi
+ #define HAVE_sync_compare_and_swapsi 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swapsi
+ #define HAVE_atomic_compare_and_swapsi 0
+ #endif
+   if (HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi)
+     {
+       cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
+       have_swap[4] = true;
+     }
+ 
+ #ifndef HAVE_sync_compare_and_swapdi
+ #define HAVE_sync_compare_and_swapdi 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swapdi
+ #define HAVE_atomic_compare_and_swapdi 0
+ #endif
+   if (HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi)
+     {
+       cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
+       have_swap[8] = true;
+     }
+ 
+ #ifndef HAVE_sync_compare_and_swapti
+ #define HAVE_sync_compare_and_swapti 0
+ #endif
+ #ifndef HAVE_atomic_compare_and_swapti
+ #define HAVE_atomic_compare_and_swapti 0
+ #endif
+   if (HAVE_sync_compare_and_swapti || HAVE_atomic_compare_and_swapti)
+     {
+       cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16");
+       have_swap[16] = true;
+     }
+ 
+   /* Tell the source code about various types.  These map to the C++11 and C1x
+      macros where 2 indicates lock-free always, and 1 indicates sometimes
+      lock free.  */
+ #define SIZEOF_NODE(T) (tree_low_cst (TYPE_SIZE_UNIT (T), 1))
+ #define SWAP_INDEX(T) ((SIZEOF_NODE (T) < SWAP_LIMIT) ? SIZEOF_NODE (T) : 0)
+   builtin_define_with_int_value ("__GCC_ATOMIC_BOOL_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (boolean_type_node)]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_CHAR_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (signed_char_type_node)]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_CHAR16_T_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (char16_type_node)]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_CHAR32_T_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (char32_type_node)]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_WCHAR_T_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (wchar_type_node)]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_SHORT_LOCK_FREE", 
+ 		      (have_swap[SWAP_INDEX (short_integer_type_node)]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_INT_LOCK_FREE", 
+ 			(have_swap[SWAP_INDEX (integer_type_node)]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_LONG_LOCK_FREE", 
+ 		      (have_swap[SWAP_INDEX (long_integer_type_node)]? 2 : 1));
+   builtin_define_with_int_value ("__GCC_ATOMIC_LLONG_LOCK_FREE", 
+ 		(have_swap[SWAP_INDEX (long_long_integer_type_node)]? 2 : 1));
+ 
+   /* ptr_type_node can't be used here since ptr_mode is only set when
+      toplev calls backend_init which is not done with -E  or pch.  */
+   psize = POINTER_SIZE / BITS_PER_UNIT;
+   if (psize >= SWAP_LIMIT)
+     psize = 0;
+   builtin_define_with_int_value ("__GCC_ATOMIC_POINTER_LOCK_FREE", 
+ 			(have_swap[psize]? 2 : 1));
+ }
+ 
  /* Hook that registers front end and target-specific built-ins.  */
  void
  c_cpp_builtins (cpp_reader *pfile)
*************** c_cpp_builtins (cpp_reader *pfile)
*** 756,808 ****
    if (c_dialect_cxx () && TYPE_UNSIGNED (wchar_type_node))
      cpp_define (pfile, "__WCHAR_UNSIGNED__");
  
!   /* Tell source code if the compiler makes sync_compare_and_swap
!      builtins available.  */
! #ifndef HAVE_sync_compare_and_swapqi
! #define HAVE_sync_compare_and_swapqi 0
! #endif
! #ifndef HAVE_atomic_compare_and_swapqi
! #define HAVE_atomic_compare_and_swapqi 0
! #endif
!   if (HAVE_sync_compare_and_swapqi || HAVE_atomic_compare_and_swapqi)
!     cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
! 
! #ifndef HAVE_sync_compare_and_swaphi
! #define HAVE_sync_compare_and_swaphi 0
! #endif
! #ifndef HAVE_atomic_compare_and_swaphi
! #define HAVE_atomic_compare_and_swaphi 0
! #endif
!   if (HAVE_sync_compare_and_swaphi || HAVE_atomic_compare_and_swaphi)
!     cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
! 
! #ifndef HAVE_sync_compare_and_swapsi
! #define HAVE_sync_compare_and_swapsi 0
! #endif
! #ifndef HAVE_atomic_compare_and_swapsi
! #define HAVE_atomic_compare_and_swapsi 0
! #endif
!   if (HAVE_sync_compare_and_swapsi || HAVE_atomic_compare_and_swapsi)
!     cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
! 
! #ifndef HAVE_sync_compare_and_swapdi
! #define HAVE_sync_compare_and_swapdi 0
! #endif
! #ifndef HAVE_atomic_compare_and_swapdi
! #define HAVE_atomic_compare_and_swapdi 0
! #endif
!   if (HAVE_sync_compare_and_swapdi || HAVE_atomic_compare_and_swapdi)
!     cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
! 
! #ifndef HAVE_sync_compare_and_swapti
! #define HAVE_sync_compare_and_swapti 0
! #endif
! #ifndef HAVE_atomic_compare_and_swapti
! #define HAVE_atomic_compare_and_swapti 0
! #endif
!   if (HAVE_sync_compare_and_swapti || HAVE_atomic_compare_and_swapti)
!     cpp_define (pfile, "__GCC_HAVE_SYNC_COMPARE_AND_SWAP_16");
! 
  #ifdef DWARF2_UNWIND_INFO
    if (dwarf2out_do_cfi_asm ())
      cpp_define (pfile, "__GCC_HAVE_DWARF2_CFI_ASM");
--- 867,874 ----
    if (c_dialect_cxx () && TYPE_UNSIGNED (wchar_type_node))
      cpp_define (pfile, "__WCHAR_UNSIGNED__");
  
!   cpp_atomic_builtins (pfile);
!     
  #ifdef DWARF2_UNWIND_INFO
    if (dwarf2out_do_cfi_asm ())
      cpp_define (pfile, "__GCC_HAVE_DWARF2_CFI_ASM");
Index: libstdc++-v3/include/bits/atomic_base.h
===================================================================
*** libstdc++-v3/include/bits/atomic_base.h	(revision 181698)
--- libstdc++-v3/include/bits/atomic_base.h	(working copy)
*************** _GLIBCXX_BEGIN_NAMESPACE_VERSION
*** 91,108 ****
  
    /// Lock-free Property
  
- #define LOCKFREE_PROP(T) (__atomic_always_lock_free (sizeof (T), 0) ? 2 : 1)
  
! #define ATOMIC_BOOL_LOCK_FREE		LOCKFREE_PROP (bool)
! #define ATOMIC_CHAR_LOCK_FREE 		LOCKFREE_PROP (char)
! #define ATOMIC_CHAR16_T_LOCK_FREE	LOCKFREE_PROP (char16_t)
! #define ATOMIC_CHAR32_T_LOCK_FREE	LOCKFREE_PROP (char32_t)
! #define ATOMIC_WCHAR_T_LOCK_FREE	LOCKFREE_PROP (wchar_t)
! #define ATOMIC_SHORT_LOCK_FREE		LOCKFREE_PROP (short)
! #define ATOMIC_INT_LOCK_FREE		LOCKFREE_PROP (int)
! #define ATOMIC_LONG_LOCK_FREE		LOCKFREE_PROP (long)
! #define ATOMIC_LLONG_LOCK_FREE		LOCKFREE_PROP (long long)
! #define ATOMIC_POINTER_LOCK_FREE	LOCKFREE_PROP (void *)
  
    // Base types for atomics.
    template<typename _IntTp>
--- 91,107 ----
  
    /// Lock-free Property
  
  
! #define ATOMIC_BOOL_LOCK_FREE		__GCC_ATOMIC_BOOL_LOCK_FREE
! #define ATOMIC_CHAR_LOCK_FREE		__GCC_ATOMIC_CHAR_LOCK_FREE
! #define ATOMIC_WCHAR_T_LOCK_FREE	__GCC_ATOMIC_WCHAR_T_LOCK_FREE
! #define ATOMIC_CHAR16_T_LOCK_FREE	__GCC_ATOMIC_CHAR16_T_LOCK_FREE
! #define ATOMIC_CHAR32_T_LOCK_FREE	__GCC_ATOMIC_CHAR32_T_LOCK_FREE
! #define ATOMIC_SHORT_LOCK_FREE		__GCC_ATOMIC_SHORT_LOCK_FREE
! #define ATOMIC_INT_LOCK_FREE		__GCC_ATOMIC_INT_LOCK_FREE
! #define ATOMIC_LONG_LOCK_FREE		__GCC_ATOMIC_LONG_LOCK_FREE
! #define ATOMIC_LLONG_LOCK_FREE		__GCC_ATOMIC_LLONG_LOCK_FREE
! #define ATOMIC_POINTER_LOCK_FREE	__GCC_ATOMIC_POINTER_LOCK_FREE
  
    // Base types for atomics.
    template<typename _IntTp>
Index: libstdc++-v3/testsuite/29_atomics/headers/atomic/macros.cc
===================================================================
*** libstdc++-v3/testsuite/29_atomics/headers/atomic/macros.cc	(revision 181698)
--- libstdc++-v3/testsuite/29_atomics/headers/atomic/macros.cc	(working copy)
***************
*** 20,25 ****
--- 20,29 ----
  
  #include <atomic>
  
+ #ifndef ATOMIC_BOOL_LOCK_FREE 
+ # error "ATOMIC_BOOL_LOCK_FREE must be a macro"
+ #endif
+ 
  #ifndef ATOMIC_CHAR_LOCK_FREE 
  # error "ATOMIC_CHAR_LOCK_FREE must be a macro"
  #endif
***************
*** 52,57 ****
--- 56,65 ----
  # error "ATOMIC_LLONG_LOCK_FREE must be a macro"
  #endif
  
+ #ifndef ATOMIC_POINTER_LOCK_FREE 
+ # error "ATOMIC_POINTER_LOCK_FREE must be a macro"
+ #endif
+ 
  #ifndef ATOMIC_FLAG_INIT
      #error "ATOMIC_FLAG_INIT_must_be_a_macro"
  #endif
*************** extern void abort(void);
*** 65,99 ****
  
  int main ()
  {
!  if (ATOMIC_CHAR_LOCK_FREE != 0 && ATOMIC_CHAR_LOCK_FREE != 1
!      && ATOMIC_CHAR_LOCK_FREE != 2)
     abort ();
  
!  if (ATOMIC_CHAR16_T_LOCK_FREE != 0 && ATOMIC_CHAR16_T_LOCK_FREE != 1
!      && ATOMIC_CHAR16_T_LOCK_FREE != 2)
     abort ();
  
!  if (ATOMIC_CHAR32_T_LOCK_FREE != 0 && ATOMIC_CHAR32_T_LOCK_FREE != 1
!      && ATOMIC_CHAR32_T_LOCK_FREE != 2)
     abort ();
  
!  if (ATOMIC_WCHAR_T_LOCK_FREE != 0 && ATOMIC_WCHAR_T_LOCK_FREE != 1
!      && ATOMIC_WCHAR_T_LOCK_FREE != 2)
     abort ();
  
!  if (ATOMIC_SHORT_LOCK_FREE != 0 && ATOMIC_SHORT_LOCK_FREE != 1
!      && ATOMIC_SHORT_LOCK_FREE != 2)
     abort ();
  
!  if (ATOMIC_INT_LOCK_FREE != 0 && ATOMIC_INT_LOCK_FREE != 1
!      && ATOMIC_INT_LOCK_FREE != 2)
     abort ();
  
!  if (ATOMIC_LONG_LOCK_FREE != 0 && ATOMIC_LONG_LOCK_FREE != 1
!      && ATOMIC_LONG_LOCK_FREE != 2)
     abort ();
  
!  if (ATOMIC_LLONG_LOCK_FREE != 0 && ATOMIC_LLONG_LOCK_FREE != 1
!      && ATOMIC_LLONG_LOCK_FREE != 2)
     abort ();
  }
--- 73,115 ----
  
  int main ()
  {
! #if (ATOMIC_BOOL_LOCK_FREE != 1 && ATOMIC_BOOL_LOCK_FREE != 2)
!    abort ();
! #endif
! 
! #if (ATOMIC_CHAR_LOCK_FREE != 1 && ATOMIC_CHAR_LOCK_FREE != 2)
!    abort ();
! #endif
! 
! #if (ATOMIC_CHAR16_T_LOCK_FREE != 1 && ATOMIC_CHAR16_T_LOCK_FREE != 2)
     abort ();
+ #endif
  
! #if (ATOMIC_CHAR32_T_LOCK_FREE != 1 && ATOMIC_CHAR32_T_LOCK_FREE != 2)
     abort ();
+ #endif
  
! #if (ATOMIC_WCHAR_T_LOCK_FREE != 1 && ATOMIC_WCHAR_T_LOCK_FREE != 2)
     abort ();
+ #endif
  
! #if (ATOMIC_SHORT_LOCK_FREE != 1 && ATOMIC_SHORT_LOCK_FREE != 2)
     abort ();
+ #endif
  
! #if (ATOMIC_INT_LOCK_FREE != 1 && ATOMIC_INT_LOCK_FREE != 2)
     abort ();
+ #endif
  
! #if (ATOMIC_LONG_LOCK_FREE != 1 && ATOMIC_LONG_LOCK_FREE != 2)
     abort ();
+ #endif
  
! #if (ATOMIC_LLONG_LOCK_FREE != 1 && ATOMIC_LLONG_LOCK_FREE != 2)
     abort ();
+ #endif
  
! #if (ATOMIC_POINTER_LOCK_FREE != 1 && ATOMIC_POINTER_LOCK_FREE != 2)
     abort ();
+ #endif
  }
Richard Henderson Nov. 28, 2011, 7:45 p.m. UTC | #9
On 11/28/2011 11:29 AM, Andrew MacLeod wrote:
> 	c-family
> 	* c-cpp-builtin.c (cpp_atomic_builtins):New.  Emit all atomic
> 	predefines in one place.  Add LOCK_FREE predefines.
> 	(c_cpp_builtins): Move Legacy HAVE_SYNC predefines to
> 	new func.
> 
> 	libstdc++-v3
> 	* include/bits/atomic_base.h (ATOMIC_*_LOCK_FREE): Use new cpp
> 	predefined macros.
> 	* testsuite/29_atomics/headers/atomic/macros.cc: Add BOOL and POINTER
> 	macro checks.  Check for expected compile time values.

Ok.


r~
diff mbox

Patch

2011-11-21  Benjamin Kosnik  <bkoz@redhat.com>

	* acinclude.m4 (GLIBCXX_ENABLE_ATOMIC_BUILTINS): Remove
	size-specific macros. _GLIBCXX_ATOMIC_BUILTINS_1,
	_GLIBCXX_ATOMIC_BUILTINS_2, _GLIBCXX_ATOMIC_BUILTINS_4,
	_GLIBCXX_ATOMIC_BUILTINS_8. Use _GLIBCXX_ATOMIC_BUILTINS to
	indicate use of C++11 atomic builtins.
	* config.h.in: Regenerate.
	* configure: Regenerate.
	* include/Makefile.am (bits_sup_headers): Add atomic_lockfree_defines.h.
	* include/Makefile.in: Regenerate.
	* libsupc++/Makefile.am: Compile C++11 support with -std=gnu++0x.
	* libsupc++/Makefile.in: Regenerate.

	* include/bits/atomic_base.h: Move lock-free property macros...
	* libsupc++/atomic_lockfree_defines.h: ...here.
	* include/std/future: Use C++11 macros.
	* libsupc++/eh_ptr.cc: Same.
	* libsupc++/eh_throw.cc: Same.
	* libsupc++/exception: Same.
	* libsupc++/exception_ptr.h: Same.
	* libsupc++/guard.cc: Same.
	* libsupc++/nested_exception.cc: Same.
	* libsupc++/nested_exception.h: Same.
	* src/future.cc: Same.

	* include/ext/atomicity.h: Use _GLIBCXX_ATOMIC_BUILTINS.

	* doc/doxygen/user.cfg.in
	* doc/xml/manual/concurrency_extensions.xml

	* testsuite/18_support/exception_ptr/lifespan.cc
	* testsuite/lib/libstdc++.exp


diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index fee5c6f..9d08178 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -2683,12 +2683,6 @@  dnl
 dnl Note:
 dnl libgomp and libgfortran use a link test, see CHECK_SYNC_FETCH_AND_ADD.
 dnl
-dnl Defines:
-dnl  _GLIBCXX_ATOMIC_BUILTINS_1
-dnl  _GLIBCXX_ATOMIC_BUILTINS_2
-dnl  _GLIBCXX_ATOMIC_BUILTINS_4
-dnl  _GLIBCXX_ATOMIC_BUILTINS_8
-dnl
 AC_DEFUN([GLIBCXX_ENABLE_ATOMIC_BUILTINS], [
   AC_LANG_SAVE
   AC_LANG_CPLUSPLUS
@@ -2729,10 +2723,6 @@  AC_DEFUN([GLIBCXX_ENABLE_ATOMIC_BUILTINS], [
       [glibcxx_cv_atomic_bool=yes],
       [glibcxx_cv_atomic_bool=no])
   ])
-  if test $glibcxx_cv_atomic_bool = yes; then
-    AC_DEFINE(_GLIBCXX_ATOMIC_BUILTINS_1, 1,
-      [Define if builtin atomic operations for bool are supported on this host.])
-  fi
   AC_MSG_RESULT($glibcxx_cv_atomic_bool)
 
   AC_MSG_CHECKING([for atomic builtins for short])
@@ -2751,10 +2741,6 @@  AC_DEFUN([GLIBCXX_ENABLE_ATOMIC_BUILTINS], [
       [glibcxx_cv_atomic_short=yes],
       [glibcxx_cv_atomic_short=no])
   ])
-  if test $glibcxx_cv_atomic_short = yes; then
-    AC_DEFINE(_GLIBCXX_ATOMIC_BUILTINS_2, 1,
-      [Define if builtin atomic operations for short are supported on this host.])
-  fi
   AC_MSG_RESULT($glibcxx_cv_atomic_short)
 
   AC_MSG_CHECKING([for atomic builtins for int])
@@ -2773,10 +2759,6 @@  AC_DEFUN([GLIBCXX_ENABLE_ATOMIC_BUILTINS], [
       [glibcxx_cv_atomic_int=yes],
       [glibcxx_cv_atomic_int=no])
   ])
-  if test $glibcxx_cv_atomic_int = yes; then
-    AC_DEFINE(_GLIBCXX_ATOMIC_BUILTINS_4, 1,
-      [Define if builtin atomic operations for int are supported on this host.])
-  fi
   AC_MSG_RESULT($glibcxx_cv_atomic_int)
 
   AC_MSG_CHECKING([for atomic builtins for long long])
@@ -2795,10 +2777,6 @@  AC_DEFUN([GLIBCXX_ENABLE_ATOMIC_BUILTINS], [
       [glibcxx_cv_atomic_long_long=yes],
       [glibcxx_cv_atomic_long_long=no])
   ])
-  if test $glibcxx_cv_atomic_long_long = yes; then
-    AC_DEFINE(_GLIBCXX_ATOMIC_BUILTINS_8, 1,
-      [Define if builtin atomic operations for long long are supported on this host.])
-  fi
   AC_MSG_RESULT($glibcxx_cv_atomic_long_long)
 
   else
@@ -2832,8 +2810,6 @@  EOF
       if grep __sync_ conftest.s >/dev/null 2>&1 ; then
 	glibcxx_cv_atomic_bool=no
       else
-      AC_DEFINE(_GLIBCXX_ATOMIC_BUILTINS_1, 1,
-      [Define if builtin atomic operations for bool are supported on this host.])
 	glibcxx_cv_atomic_bool=yes
       fi
     fi
@@ -2862,8 +2838,6 @@  EOF
       if grep __sync_ conftest.s >/dev/null 2>&1 ; then
 	glibcxx_cv_atomic_short=no
       else
-      AC_DEFINE(_GLIBCXX_ATOMIC_BUILTINS_2, 1,
-      [Define if builtin atomic operations for short are supported on this host.])
 	glibcxx_cv_atomic_short=yes
       fi
     fi
@@ -2893,8 +2867,6 @@  EOF
       if grep __sync_ conftest.s >/dev/null 2>&1 ; then
 	glibcxx_cv_atomic_int=no
       else
-      AC_DEFINE(_GLIBCXX_ATOMIC_BUILTINS_4, 1,
-	[Define if builtin atomic operations for int are supported on this host.])
 	glibcxx_cv_atomic_int=yes
       fi
     fi
@@ -2923,8 +2895,6 @@  EOF
       if grep __sync_ conftest.s >/dev/null 2>&1 ; then
 	glibcxx_cv_atomic_long_long=no
       else
-      AC_DEFINE(_GLIBCXX_ATOMIC_BUILTINS_8, 1,
-      [Define if builtin atomic operations for long long are supported on this host.])
 	glibcxx_cv_atomic_long_long=yes
       fi
     fi
@@ -2938,6 +2908,8 @@  EOF
 
   # Set atomicity_dir to builtins if either of above tests pass.
   if test $glibcxx_cv_atomic_int = yes || test $glibcxx_cv_atomic_bool = yes ; then
+    AC_DEFINE(_GLIBCXX_ATOMIC_BUILTINS, 1,
+    [Define if the compiler supports C++11 atomics.])
     atomicity_dir=cpu/generic/atomicity_builtins
   fi
 
diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in
index 7215a7f..378ddab 100644
--- a/libstdc++-v3/config.h.in
+++ b/libstdc++-v3/config.h.in
@@ -689,19 +689,8 @@ 
 /* Version number of package */
 #undef VERSION
 
-/* Define if builtin atomic operations for bool are supported on this host. */
-#undef _GLIBCXX_ATOMIC_BUILTINS_1
-
-/* Define if builtin atomic operations for short are supported on this host.
-   */
-#undef _GLIBCXX_ATOMIC_BUILTINS_2
-
-/* Define if builtin atomic operations for int are supported on this host. */
-#undef _GLIBCXX_ATOMIC_BUILTINS_4
-
-/* Define if builtin atomic operations for long long are supported on this
-   host. */
-#undef _GLIBCXX_ATOMIC_BUILTINS_8
+/* Define if the compiler supports C++11 atomics. */
+#undef _GLIBCXX_ATOMIC_BUILTINS
 
 /* Define to use concept checking code from the boost libraries. */
 #undef _GLIBCXX_CONCEPT_CHECKS
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index fa755b4..223d95f 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -15147,11 +15147,6 @@  rm -f core conftest.err conftest.$ac_objext \
 
 fi
 
-  if test $glibcxx_cv_atomic_bool = yes; then
-
-$as_echo "#define _GLIBCXX_ATOMIC_BUILTINS_1 1" >>confdefs.h
-
-  fi
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_bool" >&5
 $as_echo "$glibcxx_cv_atomic_bool" >&6; }
 
@@ -15193,11 +15188,6 @@  rm -f core conftest.err conftest.$ac_objext \
 
 fi
 
-  if test $glibcxx_cv_atomic_short = yes; then
-
-$as_echo "#define _GLIBCXX_ATOMIC_BUILTINS_2 1" >>confdefs.h
-
-  fi
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_short" >&5
 $as_echo "$glibcxx_cv_atomic_short" >&6; }
 
@@ -15239,11 +15229,6 @@  rm -f core conftest.err conftest.$ac_objext \
 
 fi
 
-  if test $glibcxx_cv_atomic_int = yes; then
-
-$as_echo "#define _GLIBCXX_ATOMIC_BUILTINS_4 1" >>confdefs.h
-
-  fi
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_int" >&5
 $as_echo "$glibcxx_cv_atomic_int" >&6; }
 
@@ -15285,11 +15270,6 @@  rm -f core conftest.err conftest.$ac_objext \
 
 fi
 
-  if test $glibcxx_cv_atomic_long_long = yes; then
-
-$as_echo "#define _GLIBCXX_ATOMIC_BUILTINS_8 1" >>confdefs.h
-
-  fi
   { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_atomic_long_long" >&5
 $as_echo "$glibcxx_cv_atomic_long_long" >&6; }
 
@@ -15303,7 +15283,7 @@  $as_echo "$glibcxx_cv_atomic_long_long" >&6; }
   # Fake what AC_TRY_COMPILE does.
 
     cat > conftest.$ac_ext << EOF
-#line 15306 "configure"
+#line 15286 "configure"
 int main()
 {
   typedef bool atomic_type;
@@ -15329,9 +15309,6 @@  $as_echo_n "checking for atomic builtins for bool... " >&6; }
       if grep __sync_ conftest.s >/dev/null 2>&1 ; then
 	glibcxx_cv_atomic_bool=no
       else
-
-$as_echo "#define _GLIBCXX_ATOMIC_BUILTINS_1 1" >>confdefs.h
-
 	glibcxx_cv_atomic_bool=yes
       fi
     fi
@@ -15340,7 +15317,7 @@  $as_echo "$glibcxx_cv_atomic_bool" >&6; }
     rm -f conftest*
 
     cat > conftest.$ac_ext << EOF
-#line 15343 "configure"
+#line 15320 "configure"
 int main()
 {
   typedef short atomic_type;
@@ -15366,9 +15343,6 @@  $as_echo_n "checking for atomic builtins for short... " >&6; }
       if grep __sync_ conftest.s >/dev/null 2>&1 ; then
 	glibcxx_cv_atomic_short=no
       else
-
-$as_echo "#define _GLIBCXX_ATOMIC_BUILTINS_2 1" >>confdefs.h
-
 	glibcxx_cv_atomic_short=yes
       fi
     fi
@@ -15377,7 +15351,7 @@  $as_echo "$glibcxx_cv_atomic_short" >&6; }
     rm -f conftest*
 
     cat > conftest.$ac_ext << EOF
-#line 15380 "configure"
+#line 15354 "configure"
 int main()
 {
   // NB: _Atomic_word not necessarily int.
@@ -15404,9 +15378,6 @@  $as_echo_n "checking for atomic builtins for int... " >&6; }
       if grep __sync_ conftest.s >/dev/null 2>&1 ; then
 	glibcxx_cv_atomic_int=no
       else
-
-$as_echo "#define _GLIBCXX_ATOMIC_BUILTINS_4 1" >>confdefs.h
-
 	glibcxx_cv_atomic_int=yes
       fi
     fi
@@ -15415,7 +15386,7 @@  $as_echo "$glibcxx_cv_atomic_int" >&6; }
     rm -f conftest*
 
     cat > conftest.$ac_ext << EOF
-#line 15418 "configure"
+#line 15389 "configure"
 int main()
 {
   typedef long long atomic_type;
@@ -15441,9 +15412,6 @@  $as_echo_n "checking for atomic builtins for long long... " >&6; }
       if grep __sync_ conftest.s >/dev/null 2>&1 ; then
 	glibcxx_cv_atomic_long_long=no
       else
-
-$as_echo "#define _GLIBCXX_ATOMIC_BUILTINS_8 1" >>confdefs.h
-
 	glibcxx_cv_atomic_long_long=yes
       fi
     fi
@@ -15463,6 +15431,9 @@  ac_compiler_gnu=$ac_cv_c_compiler_gnu
 
   # Set atomicity_dir to builtins if either of above tests pass.
   if test $glibcxx_cv_atomic_int = yes || test $glibcxx_cv_atomic_bool = yes ; then
+
+$as_echo "#define _GLIBCXX_ATOMIC_BUILTINS 1" >>confdefs.h
+
     atomicity_dir=cpu/generic/atomicity_builtins
   fi
 
@@ -15491,7 +15462,7 @@  $as_echo "$as_me: WARNING: Performance of certain classes will degrade as a resu
   # unnecessary for this test.
 
     cat > conftest.$ac_ext << EOF
-#line 15494 "configure"
+#line 15465 "configure"
 int main()
 {
   _Decimal32 d1;
@@ -15533,7 +15504,7 @@  ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
   # unnecessary for this test.
 
     cat > conftest.$ac_ext << EOF
-#line 15536 "configure"
+#line 15507 "configure"
 template<typename T1, typename T2>
   struct same
   { typedef T2 type; };
@@ -15567,7 +15538,7 @@  $as_echo "$enable_int128" >&6; }
     rm -f conftest*
 
     cat > conftest.$ac_ext << EOF
-#line 15570 "configure"
+#line 15541 "configure"
 template<typename T1, typename T2>
   struct same
   { typedef T2 type; };
diff --git a/libstdc++-v3/doc/doxygen/user.cfg.in b/libstdc++-v3/doc/doxygen/user.cfg.in
index 0b01ceb..9178b0c 100644
--- a/libstdc++-v3/doc/doxygen/user.cfg.in
+++ b/libstdc++-v3/doc/doxygen/user.cfg.in
@@ -1645,10 +1645,6 @@  PREDEFINED             = __cplusplus \
 			 _GLIBCXX_USE_WCHAR_T \
 			 _GLIBCXX_USE_LONG_LONG \
 			 _GLIBCXX_USE_C99_STDINT_TR1 \
-			 _GLIBCXX_ATOMIC_BUILTINS_1 \
-			 _GLIBCXX_ATOMIC_BUILTINS_2 \
-			 _GLIBCXX_ATOMIC_BUILTINS_4 \
-			 _GLIBCXX_ATOMIC_BUILTINS_8 \
 			 _GLIBCXX_USE_SCHED_YIELD \
 			 _GLIBCXX_USE_NANOSLEEP \
 			 PB_DS_DATA_TRUE_INDICATOR \
diff --git a/libstdc++-v3/doc/xml/manual/concurrency_extensions.xml b/libstdc++-v3/doc/xml/manual/concurrency_extensions.xml
index 9092c8d..c87f41b 100644
--- a/libstdc++-v3/doc/xml/manual/concurrency_extensions.xml
+++ b/libstdc++-v3/doc/xml/manual/concurrency_extensions.xml
@@ -210,11 +210,19 @@  usage vary depending on the target hardware and the flags used during
 compile.
 </para>
 
+
+
+<para>
+<remark>
+Incomplete/inconsistent. This is only C++11.
+</remark>
+</para>
+
 <para>
 If builtins are possible for bool-sized integral types,
-<code>_GLIBCXX_ATOMIC_BUILTINS_1</code> will be defined.
+<code>ATOMIC_BOOL_LOCK_FREE</code> will be defined.
 If builtins are possible for int-sized integral types,
-<code>_GLIBCXX_ATOMIC_BUILTINS_4</code> will be defined.
+<code>ATOMIC_INT_LOCK_FREE</code> will be defined.
 </para>
 
 
diff --git a/libstdc++-v3/include/Makefile.am b/libstdc++-v3/include/Makefile.am
index 121a642..1e9b144 100644
--- a/libstdc++-v3/include/Makefile.am
+++ b/libstdc++-v3/include/Makefile.am
@@ -177,6 +177,7 @@  bits_headers = \
 
 bits_sup_srcdir = ${glibcxx_srcdir}/libsupc++
 bits_sup_headers = \
+	${bits_sup_srcdir}/atomic_lockfree_defines.h \
 	${bits_sup_srcdir}/cxxabi_forced.h \
 	${bits_sup_srcdir}/exception_defines.h \
 	${bits_sup_srcdir}/exception_ptr.h \
diff --git a/libstdc++-v3/include/Makefile.in b/libstdc++-v3/include/Makefile.in
index 70c0781..fec2d94 100644
--- a/libstdc++-v3/include/Makefile.in
+++ b/libstdc++-v3/include/Makefile.in
@@ -429,6 +429,7 @@  bits_headers = \
 
 bits_sup_srcdir = ${glibcxx_srcdir}/libsupc++
 bits_sup_headers = \
+	${bits_sup_srcdir}/atomic_lockfree_defines.h \
 	${bits_sup_srcdir}/cxxabi_forced.h \
 	${bits_sup_srcdir}/exception_defines.h \
 	${bits_sup_srcdir}/exception_ptr.h \
diff --git a/libstdc++-v3/include/bits/atomic_base.h b/libstdc++-v3/include/bits/atomic_base.h
index cf292a8..3f00cda 100644
--- a/libstdc++-v3/include/bits/atomic_base.h
+++ b/libstdc++-v3/include/bits/atomic_base.h
@@ -35,6 +35,7 @@ 
 #include <bits/c++config.h>
 #include <stdbool.h>
 #include <stdint.h>
+#include <bits/atomic_lockfree_defines.h>
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -70,15 +71,11 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   inline void
   atomic_thread_fence(memory_order __m) noexcept
-  {
-    __atomic_thread_fence (__m);
-  }
+  { __atomic_thread_fence(__m); }
 
   inline void
   atomic_signal_fence(memory_order __m) noexcept
-  {
-    __atomic_thread_fence (__m);
-  }
+  { __atomic_thread_fence(__m); }
 
   /// kill_dependency
   template<typename _Tp>
@@ -89,20 +86,6 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
       return __ret;
     }
 
-  /// Lock-free Property
-
-#define LOCKFREE_PROP(T) (__atomic_always_lock_free (sizeof (T), 0) ? 2 : 1)
-
-#define ATOMIC_BOOL_LOCK_FREE		LOCKFREE_PROP (bool)
-#define ATOMIC_CHAR_LOCK_FREE 		LOCKFREE_PROP (char)
-#define ATOMIC_CHAR16_T_LOCK_FREE	LOCKFREE_PROP (char16_t)
-#define ATOMIC_CHAR32_T_LOCK_FREE	LOCKFREE_PROP (char32_t)
-#define ATOMIC_WCHAR_T_LOCK_FREE	LOCKFREE_PROP (wchar_t)
-#define ATOMIC_SHORT_LOCK_FREE		LOCKFREE_PROP (short)
-#define ATOMIC_INT_LOCK_FREE		LOCKFREE_PROP (int)
-#define ATOMIC_LONG_LOCK_FREE		LOCKFREE_PROP (long)
-#define ATOMIC_LLONG_LOCK_FREE		LOCKFREE_PROP (long long)
-#define ATOMIC_POINTER_LOCK_FREE	LOCKFREE_PROP (void *)
 
   // Base types for atomics.
   template<typename _IntTp>
diff --git a/libstdc++-v3/include/ext/atomicity.h b/libstdc++-v3/include/ext/atomicity.h
index f0c7752..c63b1d4 100644
--- a/libstdc++-v3/include/ext/atomicity.h
+++ b/libstdc++-v3/include/ext/atomicity.h
@@ -1,6 +1,6 @@ 
 // Support for atomic operations -*- C++ -*-
 
-// Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010
+// Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2011
 // Free Software Foundation, Inc.
 //
 // This file is part of the GNU ISO C++ Library.  This library is free
@@ -42,7 +42,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // To abstract locking primitives across all thread policies, use:
   // __exchange_and_add_dispatch
   // __atomic_add_dispatch
-#ifdef _GLIBCXX_ATOMIC_BUILTINS_4
+#ifdef _GLIBCXX_ATOMIC_BUILTINS
   static inline _Atomic_word 
   __exchange_and_add(volatile _Atomic_word* __mem, int __val)
   { return __sync_fetch_and_add(__mem, __val); }
diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future
index bfd1ff9..e9c5d17 100644
--- a/libstdc++-v3/include/std/future
+++ b/libstdc++-v3/include/std/future
@@ -187,7 +187,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     async(_Fn&& __fn, _Args&&... __args);
 
 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) \
-  && defined(_GLIBCXX_ATOMIC_BUILTINS_4)
+  && defined(ATOMIC_INT_LOCK_FREE)
 
   /// Base class and enclosing scope.
   struct __future_base
@@ -1493,7 +1493,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
     }
 
 #endif // _GLIBCXX_HAS_GTHREADS && _GLIBCXX_USE_C99_STDINT_TR1
-       // && _GLIBCXX_ATOMIC_BUILTINS_4
+       // && ATOMIC_INT_LOCK_FREE
 
   // @} group futures
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/libsupc++/Makefile.am b/libstdc++-v3/libsupc++/Makefile.am
index c8e661d..fb5c26f 100644
--- a/libstdc++-v3/libsupc++/Makefile.am
+++ b/libstdc++-v3/libsupc++/Makefile.am
@@ -35,8 +35,8 @@  std_HEADERS = \
 	cxxabi.h exception initializer_list new typeinfo 
 
 bits_HEADERS = \
-	cxxabi_forced.h hash_bytes.h \
-	exception_defines.h exception_ptr.h nested_exception.h 
+	atomic_lockfree_defines.h cxxabi_forced.h \
+	exception_defines.h exception_ptr.h hash_bytes.h nested_exception.h 
 
 headers = $(std_HEADERS) $(bits_HEADERS)
 
@@ -136,6 +136,22 @@  cp-demangle.o: cp-demangle.c
 	$(C_COMPILE) -DIN_GLIBCPP_V3 -Wno-error -c $<
 
 
+# Use special rules for the C++0x sources so that the proper flags are passed.
+eh_ptr.lo: eh_ptr.cc
+	$(LTCXXCOMPILE) -std=gnu++0x -c $<
+eh_ptr.o: eh_ptr.cc
+	$(CXXCOMPILE) -std=gnu++0x -c $<
+
+eh_throw.lo: eh_throw.cc
+	$(LTCXXCOMPILE) -std=gnu++0x -c $<
+eh_throw.o: eh_throw.cc
+	$(CXXCOMPILE) -std=gnu++0x -c $<
+
+guard.lo: guard.cc
+	$(LTCXXCOMPILE) -std=gnu++0x -c $<
+guard.o: guard.cc
+	$(CXXCOMPILE) -std=gnu++0x -c $<
+
 nested_exception.lo: nested_exception.cc
 	$(LTCXXCOMPILE) -std=gnu++0x -c $<
 nested_exception.o: nested_exception.cc
diff --git a/libstdc++-v3/libsupc++/Makefile.in b/libstdc++-v3/libsupc++/Makefile.in
index 191bd28..2cc92ec 100644
--- a/libstdc++-v3/libsupc++/Makefile.in
+++ b/libstdc++-v3/libsupc++/Makefile.in
@@ -346,8 +346,8 @@  std_HEADERS = \
 	cxxabi.h exception initializer_list new typeinfo 
 
 bits_HEADERS = \
-	cxxabi_forced.h hash_bytes.h \
-	exception_defines.h exception_ptr.h nested_exception.h 
+	atomic_lockfree_defines.h cxxabi_forced.h \
+	exception_defines.h exception_ptr.h hash_bytes.h nested_exception.h 
 
 headers = $(std_HEADERS) $(bits_HEADERS)
 @GLIBCXX_HOSTED_TRUE@c_sources = \
@@ -770,6 +770,22 @@  cp-demangle.lo: cp-demangle.c
 cp-demangle.o: cp-demangle.c
 	$(C_COMPILE) -DIN_GLIBCPP_V3 -Wno-error -c $<
 
+# Use special rules for the C++0x sources so that the proper flags are passed.
+eh_ptr.lo: eh_ptr.cc
+	$(LTCXXCOMPILE) -std=gnu++0x -c $<
+eh_ptr.o: eh_ptr.cc
+	$(CXXCOMPILE) -std=gnu++0x -c $<
+
+eh_throw.lo: eh_throw.cc
+	$(LTCXXCOMPILE) -std=gnu++0x -c $<
+eh_throw.o: eh_throw.cc
+	$(CXXCOMPILE) -std=gnu++0x -c $<
+
+guard.lo: guard.cc
+	$(LTCXXCOMPILE) -std=gnu++0x -c $<
+guard.o: guard.cc
+	$(CXXCOMPILE) -std=gnu++0x -c $<
+
 nested_exception.lo: nested_exception.cc
 	$(LTCXXCOMPILE) -std=gnu++0x -c $<
 nested_exception.o: nested_exception.cc
diff --git a/libstdc++-v3/libsupc++/atomic_lockfree_defines.h b/libstdc++-v3/libsupc++/atomic_lockfree_defines.h
new file mode 100644
index 0000000..f879b1b
--- /dev/null
+++ b/libstdc++-v3/libsupc++/atomic_lockfree_defines.h
@@ -0,0 +1,66 @@ 
+// -*- C++ -*- header.
+
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// Under Section 7 of GPL version 3, you are granted additional
+// permissions described in the GCC Runtime Library Exception, version
+// 3.1, as published by the Free Software Foundation.
+
+// You should have received a copy of the GNU General Public License and
+// a copy of the GCC Runtime Library Exception along with this program;
+// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+// <http://www.gnu.org/licenses/>.
+
+/** @file bits/atomic_lockfree_defines.h
+ *  This is an internal header file, included by other library headers.
+ *  Do not attempt to use it directly. @headername{atomic}
+ */
+
+#ifndef _GLIBCXX_ATOMIC_LOCK_FREE_H
+#define _GLIBCXX_ATOMIC_LOCK_FREE_H 1
+
+#pragma GCC system_header
+
+/**
+ * @addtogroup atomics
+ * @{
+ */
+
+/**
+ * Lock-free property.
+ *
+ * 0 indicates that the types are never lock-free.
+ * 1 indicates that the types are sometimes lock-free.
+ * 2 indicates that the types are always lock-free.
+ */
+
+#define __LOCK_FREE_PROPERTY(T) (__atomic_always_lock_free(sizeof(T), 0) \
+				 ? 2 : __atomic_is_lock_free(sizeof(T)))
+
+#ifdef __GXX_EXPERIMENTAL_CXX0X__
+#define ATOMIC_BOOL_LOCK_FREE 		__LOCK_FREE_PROPERTY(bool)
+#define ATOMIC_CHAR_LOCK_FREE 		__LOCK_FREE_PROPERTY(char)
+#define ATOMIC_CHAR16_T_LOCK_FREE	__LOCK_FREE_PROPERTY(char16_t)
+#define ATOMIC_CHAR32_T_LOCK_FREE	__LOCK_FREE_PROPERTY(char32_t)
+#define ATOMIC_WCHAR_T_LOCK_FREE	__LOCK_FREE_PROPERTY(wchar_t)
+#define ATOMIC_SHORT_LOCK_FREE		__LOCK_FREE_PROPERTY(short)
+#define ATOMIC_INT_LOCK_FREE		__LOCK_FREE_PROPERTY(int)
+#define ATOMIC_LONG_LOCK_FREE		__LOCK_FREE_PROPERTY(long)
+#define ATOMIC_LLONG_LOCK_FREE		__LOCK_FREE_PROPERTY(long long)
+#define ATOMIC_POINTER_LOCK_FREE	__LOCK_FREE_PROPERTY(void*)
+#endif
+
+// @} group atomics
+
+#endif
diff --git a/libstdc++-v3/libsupc++/eh_ptr.cc b/libstdc++-v3/libsupc++/eh_ptr.cc
index 94c2842..cc916d7 100644
--- a/libstdc++-v3/libsupc++/eh_ptr.cc
+++ b/libstdc++-v3/libsupc++/eh_ptr.cc
@@ -1,5 +1,5 @@ 
 // -*- C++ -*- Implement the members of exception_ptr.
-// Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
+// Copyright (C) 2008, 2009, 2010, 2011 Free Software Foundation, Inc.
 //
 // This file is part of GCC.
 //
@@ -23,8 +23,9 @@ 
 // <http://www.gnu.org/licenses/>.
 
 #include <bits/c++config.h>
+#include <bits/atomic_lockfree_defines.h>
 
-#ifdef _GLIBCXX_ATOMIC_BUILTINS_4
+#ifdef ATOMIC_INT_LOCK_FREE
 
 #define _GLIBCXX_EH_PTR_COMPAT
 
diff --git a/libstdc++-v3/libsupc++/eh_throw.cc b/libstdc++-v3/libsupc++/eh_throw.cc
index 78cfc13..48f4c2d 100644
--- a/libstdc++-v3/libsupc++/eh_throw.cc
+++ b/libstdc++-v3/libsupc++/eh_throw.cc
@@ -43,7 +43,7 @@  __gxx_exception_cleanup (_Unwind_Reason_Code code, _Unwind_Exception *exc)
   if (code != _URC_FOREIGN_EXCEPTION_CAUGHT && code != _URC_NO_REASON)
     __terminate (header->exc.terminateHandler);
 
-#ifdef _GLIBCXX_ATOMIC_BUILTINS_4
+#ifdef ATOMIC_INT_LOCK_FREE
   if (__sync_sub_and_fetch (&header->referenceCount, 1) == 0)
     {
 #endif
@@ -51,7 +51,7 @@  __gxx_exception_cleanup (_Unwind_Reason_Code code, _Unwind_Exception *exc)
 	header->exc.exceptionDestructor (header + 1);
 
       __cxa_free_exception (header + 1);
-#ifdef _GLIBCXX_ATOMIC_BUILTINS_4
+#ifdef ATOMIC_INT_LOCK_FREE
     }
 #endif
 }
diff --git a/libstdc++-v3/libsupc++/exception b/libstdc++-v3/libsupc++/exception
index db75ad1..e7eaa45 100644
--- a/libstdc++-v3/libsupc++/exception
+++ b/libstdc++-v3/libsupc++/exception
@@ -37,6 +37,7 @@ 
 #pragma GCC visibility push(default)
 
 #include <bits/c++config.h>
+#include <bits/atomic_lockfree_defines.h>
 
 extern "C++" {
 
@@ -149,8 +150,7 @@  _GLIBCXX_END_NAMESPACE_VERSION
 
 #pragma GCC visibility pop
 
-#if (defined(__GXX_EXPERIMENTAL_CXX0X__) \
-     && defined(_GLIBCXX_ATOMIC_BUILTINS_4))
+#if defined(__GXX_EXPERIMENTAL_CXX0X__) && defined(ATOMIC_INT_LOCK_FREE)
 #include <bits/exception_ptr.h>
 #include <bits/nested_exception.h>
 #endif
diff --git a/libstdc++-v3/libsupc++/exception_ptr.h b/libstdc++-v3/libsupc++/exception_ptr.h
index 00b30fd..07bc15a 100644
--- a/libstdc++-v3/libsupc++/exception_ptr.h
+++ b/libstdc++-v3/libsupc++/exception_ptr.h
@@ -36,7 +36,7 @@ 
 #include <bits/c++config.h>
 #include <bits/exception_defines.h>
 
-#if !defined(_GLIBCXX_ATOMIC_BUILTINS_4)
+#ifndef ATOMIC_INT_LOCK_FREE
 #  error This platform does not support exception propagation.
 #endif
 
diff --git a/libstdc++-v3/libsupc++/guard.cc b/libstdc++-v3/libsupc++/guard.cc
index 21bca58..b9c7283 100644
--- a/libstdc++-v3/libsupc++/guard.cc
+++ b/libstdc++-v3/libsupc++/guard.cc
@@ -32,7 +32,7 @@ 
 #include <ext/atomicity.h>
 #include <ext/concurrence.h>
 #if defined(__GTHREADS) && defined(__GTHREAD_HAS_COND) \
-    && defined(_GLIBCXX_ATOMIC_BUILTINS_4) && defined(_GLIBCXX_HAVE_LINUX_FUTEX)
+  && defined(ATOMIC_INT_LOCK_FREE) && defined(_GLIBCXX_HAVE_LINUX_FUTEX)
 # include <climits>
 # include <syscall.h>
 # include <unistd.h>
diff --git a/libstdc++-v3/libsupc++/nested_exception.cc b/libstdc++-v3/libsupc++/nested_exception.cc
index ecbc4c8..2f7ee6a 100644
--- a/libstdc++-v3/libsupc++/nested_exception.cc
+++ b/libstdc++-v3/libsupc++/nested_exception.cc
@@ -25,7 +25,7 @@ 
 
 namespace std 
 {
-#ifdef _GLIBCXX_ATOMIC_BUILTINS_4
+#ifdef ATOMIC_INT_LOCK_FREE
   nested_exception::~nested_exception() = default;
 #endif
 } // namespace std
diff --git a/libstdc++-v3/libsupc++/nested_exception.h b/libstdc++-v3/libsupc++/nested_exception.h
index d4804bb..a61247b 100644
--- a/libstdc++-v3/libsupc++/nested_exception.h
+++ b/libstdc++-v3/libsupc++/nested_exception.h
@@ -38,7 +38,7 @@ 
 
 #include <bits/c++config.h>
 
-#if !defined(_GLIBCXX_ATOMIC_BUILTINS_4)
+#ifndef ATOMIC_INT_LOCK_FREE
 #  error This platform does not support exception propagation.
 #endif
 
diff --git a/libstdc++-v3/src/future.cc b/libstdc++-v3/src/future.cc
index 8569bf0..bb22718 100644
--- a/libstdc++-v3/src/future.cc
+++ b/libstdc++-v3/src/future.cc
@@ -78,7 +78,7 @@  _GLIBCXX_BEGIN_NAMESPACE_VERSION
   future_error::what() const noexcept { return _M_code.message().c_str(); }
 
 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) \
-  && defined(_GLIBCXX_ATOMIC_BUILTINS_4)
+  && defined(ATOMIC_INT_LOCK_FREE)
   __future_base::_Result_base::_Result_base() = default;
 
   __future_base::_Result_base::~_Result_base() = default;
diff --git a/libstdc++-v3/testsuite/18_support/exception_ptr/lifespan.cc b/libstdc++-v3/testsuite/18_support/exception_ptr/lifespan.cc
index 704f77e..b417ea6 100644
--- a/libstdc++-v3/testsuite/18_support/exception_ptr/lifespan.cc
+++ b/libstdc++-v3/testsuite/18_support/exception_ptr/lifespan.cc
@@ -150,11 +150,14 @@  void test06()
 
   may_destruct = false;
 
-  try {
-    test06_helper();
-  } catch(...) {
-    may_destruct = true;
-  }
+  try 
+    {
+      test06_helper();
+    } 
+  catch(...) 
+    {
+      may_destruct = true;
+    }
   may_destruct = false;
 }
 
@@ -167,11 +170,14 @@  void test99()
 
   may_destruct = false;
 
-  try {
-    throw destructing();
-  } catch(...) {
-    gep = current_exception();
-  }
+  try 
+    {
+      throw destructing();
+    } 
+  catch(...) 
+    {
+      gep = current_exception();
+    }
 }
 
 int main()
diff --git a/libstdc++-v3/testsuite/lib/libstdc++.exp b/libstdc++-v3/testsuite/lib/libstdc++.exp
index e419192..6e9b20b 100644
--- a/libstdc++-v3/testsuite/lib/libstdc++.exp
+++ b/libstdc++-v3/testsuite/lib/libstdc++.exp
@@ -1219,14 +1219,14 @@  proc check_v3_target_atomic_builtins { } {
 	set src atomic_builtins[pid].cc
 
 	set f [open $src "w"]
-	puts $f "#include <bits/c++config.h>"
-	puts $f "#ifndef _GLIBCXX_ATOMIC_BUILTINS_4"
-	puts $f "#  error No atomic builtins"
+	puts $f "#include <bits/atomic_lockfree_defines.h>"
+	puts $f "#ifndef ATOMIC_INT_LOCK_FREE"
+	puts $f "#  error No atomic int"
 	puts $f "#endif"
 	close $f
 
 	set cxxflags_saved $cxxflags
-	set cxxflags "$cxxflags $DEFAULT_CXXFLAGS -Werror"
+	set cxxflags "$cxxflags $DEFAULT_CXXFLAGS -Werror -std=gnu++0x"
 
 	set lines [v3_target_compile $src /dev/null preprocess ""]
 	set cxxflags $cxxflags_saved