Re: [PATCH] Fix ODR violations in code using

2019-07-06 Thread Jonathan Wakely

On 05/07/19 19:44 +0100, Jonathan Wakely wrote:

On 05/07/19 20:23 +0200, Daniel Krügler wrote:

Am Fr., 5. Juli 2019 um 18:13 Uhr schrieb Jonathan Wakely :



[..]

I decided against the simplification in the second patch, and
committed the attached one which is closer to the first patch I sent
(preserving the __atomic_add and __exchange_and_add functions even
when they just call the built-ins).

Tested x86_64-linux, powerpc64-linux, powerpc-aix. Committed to trunk.


Unrelated to the actual patch, I noticed some explicit "throw()" forms
used as exception specifications - shouldn't these be replaced by
either explicit "noexcept" or at least by a library macro that expands
to one or the other?


Yes, they should be _GLIBCXX_NOTHROW.


(I'm sorry, if such unrelated questions are
considered as inappropriate for this list).


Entirely appropriate, thanks!



Here's a patch to fix that and the dumb mistake I made in
__atomic_add_dispatch. I'll commit after testing finishes.




commit 1542776ebab8848109d125d05a548fca5efb513a
Author: Jonathan Wakely 
Date:   Sat Jul 6 21:24:51 2019 +0100

Fix recent regression in __atomic_add_dispatch

* include/ext/atomicity.h (__exchange_and_add, __atomic_add): Replace
throw() with _GLIBCXX_NOTHROW.
(__atomic_add_dispatch): Return after performing atomic increment.

diff --git a/libstdc++-v3/include/ext/atomicity.h b/libstdc++-v3/include/ext/atomicity.h
index 73225b3de20..333c8843e14 100644
--- a/libstdc++-v3/include/ext/atomicity.h
+++ b/libstdc++-v3/include/ext/atomicity.h
@@ -55,10 +55,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   { __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); }
 #else
   _Atomic_word
-  __exchange_and_add(volatile _Atomic_word*, int) throw ();
+  __exchange_and_add(volatile _Atomic_word*, int) _GLIBCXX_NOTHROW;
 
   void
-  __atomic_add(volatile _Atomic_word*, int) throw ();
+  __atomic_add(volatile _Atomic_word*, int) _GLIBCXX_NOTHROW;
 #endif
 
   inline _Atomic_word
@@ -92,7 +92,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   {
 #ifdef __GTHREADS
 if (__gthread_active_p())
-  __atomic_add(__mem, __val);
+  {
+	__atomic_add(__mem, __val);
+	return;
+  }
 #endif
 __atomic_add_single(__mem, __val);
   }


Re: [PATCH] Fix ODR violations in code using

2019-07-05 Thread Jonathan Wakely

On 05/07/19 20:23 +0200, Daniel Krügler wrote:

Am Fr., 5. Juli 2019 um 18:13 Uhr schrieb Jonathan Wakely :



[..]

I decided against the simplification in the second patch, and
committed the attached one which is closer to the first patch I sent
(preserving the __atomic_add and __exchange_and_add functions even
when they just call the built-ins).

Tested x86_64-linux, powerpc64-linux, powerpc-aix. Committed to trunk.


Unrelated to the actual patch, I noticed some explicit "throw()" forms
used as exception specifications - shouldn't these be replaced by
either explicit "noexcept" or at least by a library macro that expands
to one or the other?


Yes, they should be _GLIBCXX_NOTHROW.


(I'm sorry, if such unrelated questions are
considered as inappropriate for this list).


Entirely appropriate, thanks!



Re: [PATCH] Fix ODR violations in code using

2019-07-05 Thread Daniel Krügler
Am Fr., 5. Juli 2019 um 18:13 Uhr schrieb Jonathan Wakely :
>
[..]
> I decided against the simplification in the second patch, and
> committed the attached one which is closer to the first patch I sent
> (preserving the __atomic_add and __exchange_and_add functions even
> when they just call the built-ins).
>
> Tested x86_64-linux, powerpc64-linux, powerpc-aix. Committed to trunk.

Unrelated to the actual patch, I noticed some explicit "throw()" forms
used as exception specifications - shouldn't these be replaced by
either explicit "noexcept" or at least by a library macro that expands
to one or the other? (I'm sorry, if such unrelated questions are
considered as inappropriate for this list).

- Daniel


Re: [PATCH] Fix ODR violations in code using

2019-07-05 Thread Jonathan Wakely

On 21/06/19 18:13 +0100, Jonathan Wakely wrote:

On 21/06/19 18:08 +0100, Jonathan Wakely wrote:

On 21/06/19 13:01 -0400, Nathan Sidwell wrote:

On 6/21/19 12:01 PM, Jonathan Wakely wrote:

Nathan noticed that the 'static inline' functions in 
cause ODR violations when used from inline functions or templates (see
[basic.def.odr] p12 bullet (12.2)). His modules branch now diagnoses
those violations, so we need a fix.

Looking at the history (r114044 by Paolo) I believe the idea was indeed
to allow different definitions to be used in different TUs. I think
__attribute__((__always_inline__)) is a better match for that than
'static inline', and doesn't violate the ODR (at least, not if all TUs
have the same values for __GTHREADS and _GLIBCXX_ATOMIC_BUILTINS).

These functions still violate this rule in [dcl.inline]:

C++17: "If a function with external linkage is declared inline in one
translation unit, it shall be declared inline in all translation units
in which it appears; no diagnostic is required."

C++2a WP: "If a function or variable with external or module linkage
is declared inline in one translation unit, there shall be a reachable
inline declaration in all translation units in which it is declared;
no diagnostic is required."

But that doesn't seem to be diagnosable by today's implementations.

Does this change seem reasonable?


yes, thanks!


Actually, I think I prefer this version. This produces identical code
to the always_inline version, but without the indirection to
additional inline functions, i.e. just inline the relevant code into
the _dispatch functions.

Tests are still running but no failures so far, as expected.


Oops, I spoke too soon:

FAIL: tr1/2_general_utilities/shared_ptr/thread/default_weaktoshared.cc (test 
for excess errors)
UNRESOLVED: tr1/2_general_utilities/shared_ptr/thread/default_weaktoshared.cc 
compilation failed to produce executable
FAIL: tr1/2_general_utilities/shared_ptr/thread/mutex_weaktoshared.cc (test for 
excess errors)
UNRESOLVED: tr1/2_general_utilities/shared_ptr/thread/mutex_weaktoshared.cc 
compilation failed to produce executable

Those tests explicitly use the __atomic_add function that the patch
removes. But those would be easy to adjust.


I decided against the simplification in the second patch, and
committed the attached one which is closer to the first patch I sent
(preserving the __atomic_add and __exchange_and_add functions even
when they just call the built-ins).

Tested x86_64-linux, powerpc64-linux, powerpc-aix. Committed to trunk.

commit 0d26b6506f20dcb1c956338baba0c26f623e25f2
Author: Jonathan Wakely 
Date:   Fri Jul 5 15:15:46 2019 +0100

Fix ODR violations in code using 

Because the inline versions of __exchange_and_add and __atomic_add are
also marked static, they cannot be used from templates or other inline
functions without ODR violations. This change gives them external
linkage, but adds the always_inline attribute.

* include/ext/atomicity.h [_GLIBCXX_ATOMIC_BUILTINS] (__atomic_add)
(__exchange_and_add): Replace static specifier with always_inline
attribute.
(__exchange_and_add_single, __atomic_add_single): Likewise.
(__exchange_and_add_dispatch, __atomic_add_dispatch): Likewise. Also
combine !__gthread_active_p() and !__GTHREADS branches.

diff --git a/libstdc++-v3/include/ext/atomicity.h b/libstdc++-v3/include/ext/atomicity.h
index 0783a58e01a..73225b3de20 100644
--- a/libstdc++-v3/include/ext/atomicity.h
+++ b/libstdc++-v3/include/ext/atomicity.h
@@ -44,24 +44,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // __exchange_and_add_dispatch
   // __atomic_add_dispatch
 #ifdef _GLIBCXX_ATOMIC_BUILTINS
-  static inline _Atomic_word 
+  inline _Atomic_word
+  __attribute__((__always_inline__))
   __exchange_and_add(volatile _Atomic_word* __mem, int __val)
   { return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); }
 
-  static inline void
+  inline void
+  __attribute__((__always_inline__))
   __atomic_add(volatile _Atomic_word* __mem, int __val)
   { __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); }
 #else
   _Atomic_word
-  __attribute__ ((__unused__))
   __exchange_and_add(volatile _Atomic_word*, int) throw ();
 
   void
-  __attribute__ ((__unused__))
   __atomic_add(volatile _Atomic_word*, int) throw ();
 #endif
 
-  static inline _Atomic_word
+  inline _Atomic_word
+  __attribute__((__always_inline__))
   __exchange_and_add_single(_Atomic_word* __mem, int __val)
   {
 _Atomic_word __result = *__mem;
@@ -69,36 +70,31 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 return __result;
   }
 
-  static inline void
+  inline void
+  __attribute__((__always_inline__))
   __atomic_add_single(_Atomic_word* __mem, int __val)
   { *__mem += __val; }
 
-  static inline _Atomic_word
-  __attribute__ ((__unused__))
+  inline _Atomic_word
+  __attribute__ ((__always_inline__))
   __exchange_and_add_dispatch(_Atomic_word* __mem, int __val)
   

Re: [PATCH] Fix ODR violations in code using

2019-06-21 Thread Jonathan Wakely

On 21/06/19 18:08 +0100, Jonathan Wakely wrote:

On 21/06/19 13:01 -0400, Nathan Sidwell wrote:

On 6/21/19 12:01 PM, Jonathan Wakely wrote:

Nathan noticed that the 'static inline' functions in 
cause ODR violations when used from inline functions or templates (see
[basic.def.odr] p12 bullet (12.2)). His modules branch now diagnoses
those violations, so we need a fix.

Looking at the history (r114044 by Paolo) I believe the idea was indeed
to allow different definitions to be used in different TUs. I think
__attribute__((__always_inline__)) is a better match for that than
'static inline', and doesn't violate the ODR (at least, not if all TUs
have the same values for __GTHREADS and _GLIBCXX_ATOMIC_BUILTINS).

These functions still violate this rule in [dcl.inline]:

C++17: "If a function with external linkage is declared inline in one
translation unit, it shall be declared inline in all translation units
in which it appears; no diagnostic is required."

C++2a WP: "If a function or variable with external or module linkage
is declared inline in one translation unit, there shall be a reachable
inline declaration in all translation units in which it is declared;
no diagnostic is required."

But that doesn't seem to be diagnosable by today's implementations.

Does this change seem reasonable?


yes, thanks!


Actually, I think I prefer this version. This produces identical code
to the always_inline version, but without the indirection to
additional inline functions, i.e. just inline the relevant code into
the _dispatch functions.

Tests are still running but no failures so far, as expected.


Oops, I spoke too soon:

FAIL: tr1/2_general_utilities/shared_ptr/thread/default_weaktoshared.cc (test 
for excess errors)
UNRESOLVED: tr1/2_general_utilities/shared_ptr/thread/default_weaktoshared.cc 
compilation failed to produce executable
FAIL: tr1/2_general_utilities/shared_ptr/thread/mutex_weaktoshared.cc (test for 
excess errors)
UNRESOLVED: tr1/2_general_utilities/shared_ptr/thread/mutex_weaktoshared.cc 
compilation failed to produce executable

Those tests explicitly use the __atomic_add function that the patch
removes. But those would be easy to adjust.




Re: [PATCH] Fix ODR violations in code using

2019-06-21 Thread Jonathan Wakely

On 21/06/19 13:01 -0400, Nathan Sidwell wrote:

On 6/21/19 12:01 PM, Jonathan Wakely wrote:

Nathan noticed that the 'static inline' functions in 
cause ODR violations when used from inline functions or templates (see
[basic.def.odr] p12 bullet (12.2)). His modules branch now diagnoses
those violations, so we need a fix.

Looking at the history (r114044 by Paolo) I believe the idea was indeed
to allow different definitions to be used in different TUs. I think
__attribute__((__always_inline__)) is a better match for that than
'static inline', and doesn't violate the ODR (at least, not if all TUs
have the same values for __GTHREADS and _GLIBCXX_ATOMIC_BUILTINS).

These functions still violate this rule in [dcl.inline]:

C++17: "If a function with external linkage is declared inline in one
translation unit, it shall be declared inline in all translation units
in which it appears; no diagnostic is required."

C++2a WP: "If a function or variable with external or module linkage
is declared inline in one translation unit, there shall be a reachable
inline declaration in all translation units in which it is declared;
no diagnostic is required."

But that doesn't seem to be diagnosable by today's implementations.

Does this change seem reasonable?


yes, thanks!


Actually, I think I prefer this version. This produces identical code
to the always_inline version, but without the indirection to
additional inline functions, i.e. just inline the relevant code into
the _dispatch functions.

Tests are still running but no failures so far, as expected.


commit 56040dad3b55a98f6e5090d04cb49945c40df39c
Author: Jonathan Wakely 
Date:   Fri Jun 21 17:52:23 2019 +0100

Simplify

diff --git a/libstdc++-v3/include/ext/atomicity.h b/libstdc++-v3/include/ext/atomicity.h
index 0783a58e01a..30453c92315 100644
--- a/libstdc++-v3/include/ext/atomicity.h
+++ b/libstdc++-v3/include/ext/atomicity.h
@@ -43,62 +43,49 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   // To abstract locking primitives across all thread policies, use:
   // __exchange_and_add_dispatch
   // __atomic_add_dispatch
-#ifdef _GLIBCXX_ATOMIC_BUILTINS
-  static inline _Atomic_word 
-  __exchange_and_add(volatile _Atomic_word* __mem, int __val)
-  { return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); }
-
-  static inline void
-  __atomic_add(volatile _Atomic_word* __mem, int __val)
-  { __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); }
-#else
+#ifndef _GLIBCXX_ATOMIC_BUILTINS
   _Atomic_word
-  __attribute__ ((__unused__))
   __exchange_and_add(volatile _Atomic_word*, int) throw ();
 
   void
-  __attribute__ ((__unused__))
   __atomic_add(volatile _Atomic_word*, int) throw ();
 #endif
 
-  static inline _Atomic_word
-  __exchange_and_add_single(_Atomic_word* __mem, int __val)
+  inline _Atomic_word
+  __attribute__ ((__always_inline__))
+  __exchange_and_add_dispatch(_Atomic_word* __mem, int __val)
   {
+#ifdef __GTHREADS
+if (__gthread_active_p())
+  {
+#ifdef _GLIBCXX_ATOMIC_BUILTINS
+	return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL);
+#else
+	return __exchange_and_add(__mem, __val);
+#endif
+  }
+#endif
 _Atomic_word __result = *__mem;
 *__mem += __val;
 return __result;
   }
 
-  static inline void
-  __atomic_add_single(_Atomic_word* __mem, int __val)
-  { *__mem += __val; }
-
-  static inline _Atomic_word
-  __attribute__ ((__unused__))
-  __exchange_and_add_dispatch(_Atomic_word* __mem, int __val)
-  {
-#ifdef __GTHREADS
-if (__gthread_active_p())
-  return __exchange_and_add(__mem, __val);
-else
-  return __exchange_and_add_single(__mem, __val);
-#else
-return __exchange_and_add_single(__mem, __val);
-#endif
-  }
-
-  static inline void
-  __attribute__ ((__unused__))
+  inline void
+  __attribute__ ((__always_inline__))
   __atomic_add_dispatch(_Atomic_word* __mem, int __val)
   {
 #ifdef __GTHREADS
 if (__gthread_active_p())
-  __atomic_add(__mem, __val);
-else
-  __atomic_add_single(__mem, __val);
+  {
+#ifdef _GLIBCXX_ATOMIC_BUILTINS
+	__atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL);
 #else
-__atomic_add_single(__mem, __val);
+	__atomic_add(__mem, __val);
 #endif
+  }
+else
+#endif
+*__mem += __val;
   }
 
 _GLIBCXX_END_NAMESPACE_VERSION
diff --git a/libstdc++-v3/src/c++98/mt_allocator.cc b/libstdc++-v3/src/c++98/mt_allocator.cc
index f842c6f9cfd..9b26f3dc993 100644
--- a/libstdc++-v3/src/c++98/mt_allocator.cc
+++ b/libstdc++-v3/src/c++98/mt_allocator.cc
@@ -302,7 +302,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	if (__reclaimed > 1024)
 	  {
 	__bin._M_used[__thread_id] -= __reclaimed;
-	__atomic_add(&__reclaimed_base[__thread_id], -__reclaimed);
+	__atomic_fetch_add(&__reclaimed_base[__thread_id], -__reclaimed,
+			   __ATOMIC_ACQ_REL);
 	  }
 
 	if (__remove >= __net_used)
@@ -332,7 +333,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	if (__block->_M_thread_id == __thread_id)
 	  --__bin._M_used[__thread_id];
 	else
-	  

Re: [PATCH] Fix ODR violations in code using

2019-06-21 Thread Nathan Sidwell

On 6/21/19 12:01 PM, Jonathan Wakely wrote:

Nathan noticed that the 'static inline' functions in 
cause ODR violations when used from inline functions or templates (see
[basic.def.odr] p12 bullet (12.2)). His modules branch now diagnoses
those violations, so we need a fix.

Looking at the history (r114044 by Paolo) I believe the idea was indeed
to allow different definitions to be used in different TUs. I think
__attribute__((__always_inline__)) is a better match for that than
'static inline', and doesn't violate the ODR (at least, not if all TUs
have the same values for __GTHREADS and _GLIBCXX_ATOMIC_BUILTINS).

These functions still violate this rule in [dcl.inline]:

C++17: "If a function with external linkage is declared inline in one
translation unit, it shall be declared inline in all translation units
in which it appears; no diagnostic is required."

C++2a WP: "If a function or variable with external or module linkage
is declared inline in one translation unit, there shall be a reachable
inline declaration in all translation units in which it is declared;
no diagnostic is required."

But that doesn't seem to be diagnosable by today's implementations.

Does this change seem reasonable?


yes, thanks!

nathan

--
Nathan Sidwell


[PATCH] Fix ODR violations in code using

2019-06-21 Thread Jonathan Wakely

Nathan noticed that the 'static inline' functions in 
cause ODR violations when used from inline functions or templates (see
[basic.def.odr] p12 bullet (12.2)). His modules branch now diagnoses
those violations, so we need a fix.

Looking at the history (r114044 by Paolo) I believe the idea was indeed
to allow different definitions to be used in different TUs. I think
__attribute__((__always_inline__)) is a better match for that than
'static inline', and doesn't violate the ODR (at least, not if all TUs
have the same values for __GTHREADS and _GLIBCXX_ATOMIC_BUILTINS).

These functions still violate this rule in [dcl.inline]:

C++17: "If a function with external linkage is declared inline in one
translation unit, it shall be declared inline in all translation units
in which it appears; no diagnostic is required."

C++2a WP: "If a function or variable with external or module linkage
is declared inline in one translation unit, there shall be a reachable
inline declaration in all translation units in which it is declared;
no diagnostic is required."

But that doesn't seem to be diagnosable by today's implementations.

Does this change seem reasonable?

It does change the size of a few files, e.g. for x86_64 some are
bigger and some are smaller, overall slightly smaller:

  text data bss dec hex filename

  54008 35257601680 src/c++11/cow-locale_init.o
  54028 35257621682 src/c++11/cow-locale_init.o 
[always_inline]

 22772 2056   0   2482860fc src/c++11/cow-shim_facets.o
 22710 2056   0   2476660be src/c++11/cow-shim_facets.o 
[always_inline]

 49458 2184   0   51642c9ba src/c++11/cow-sstream-inst.o
 49482 2184   0   51666c9d2 src/c++11/cow-sstream-inst.o 
[always_inline]

  74618   074691d2d src/c++11/cow-stdexcept.o
  74648   074721d30 src/c++11/cow-stdexcept.o 
[always_inline]

 167538  32   167934199 src/c++11/cow-string-inst.o
 167568  32   16796419c src/c++11/cow-string-inst.o 
[always_inline]

 170098  32   170494299 src/c++11/cow-wstring-inst.o
 170088  32   170484298 src/c++11/cow-wstring-inst.o 
[always_inline]

 20342 2072   0   22414578e src/c++11/cxx11-shim_facets.o
 20276 2072   0   22348574c src/c++11/cxx11-shim_facets.o 
[always_inline]

  2929  240   83177 c69 src/c++11/future.o
  2945  240   83193 c79 src/c++11/future.o [always_inline]

  6789  120   069091afd src/c++11/ios-inst.o
  6750  120   068701ad6 src/c++11/ios-inst.o [always_inline]

  2364   57   82429 97d src/c++11/ios.o
  2362   57   82427 97b src/c++11/ios.o [always_inline]

 94493 2712 192   97397   17c75 src/c++11/locale-inst.o
 94498 2712 192   97402   17c7a src/c++11/locale-inst.o [always_inline]

 93094 2712 192   95998   176fe src/c++11/wlocale-inst.o
 93113 2712 192   96017   17711 src/c++11/wlocale-inst.o [always_inline]

 20189  208   0   203974fad src/c++17/cow-fs_dir.o
 20118  208   0   203264f66 src/c++17/cow-fs_dir.o [always_inline]

 550778   0   55085d72d src/c++17/cow-fs_ops.o
 551038   0   55111d747 src/c++17/cow-fs_ops.o [always_inline]

 40200  304   0   405049e38 src/c++17/cow-fs_path.o
 40204  304   0   405089e3c src/c++17/cow-fs_path.o [always_inline]

 18672  208   0   1888049c0 src/c++17/fs_dir.o
 18628  208   0   188364994 src/c++17/fs_dir.o [always_inline]

 60604  160   0   60764ed5c src/c++17/fs_ops.o
 60606  160   0   60766ed5e src/c++17/fs_ops.o [always_inline]

 39568  304   0   398729bc0 src/c++17/fs_path.o
 39561  304   0   398659bb9 src/c++17/fs_path.o [always_inline]

  36538   03661 e4d src/c++98/ios_init.o
  36568   03664 e50 src/c++98/ios_init.o [always_inline]

  6878  184  8471461bea src/c++98/locale.o
  6896  184  8471641bfc src/c++98/locale.o [always_inline]

  6693  7685368   12829321d src/c++98/locale_init.o
  6710  7685368   12846322e src/c++98/locale_init.o [always_inline]

  72228   072301c3e src/c++98/localename.o
  72238   072311c3f src/c++98/localename.o [always_inline]

  4036  144 20843881124 src/c++98/pool_allocator.o
  4044  144 2084396112c src/c++98/pool_allocator.o 
[always_inline]

  1955  584   02539 9eb src/c++98/stdexcept.o
  1957  584   02541 9ed src/c++98/stdexcept.o [always_inline]

 25199  208   0   25407633f src/filesystem/cow-dir.o
 25248  208   0   254566370 src/filesystem/cow-dir.o [always_inline]

 711348   0   71142   115e6