mirror of git://gcc.gnu.org/git/gcc.git
libstdc++: Fix warnings from std::make_unsigned<_Atomic_word> [PR122172]
GCC gives a -Wignored-attributes warning when a class template is instantiated with a type that has an aligned(n) attribute. Specifically, cris-elf uses 'typedef int __attribute_((__aligned(4))) _Atomic_word;' and so compiling libstdc++ headers gives: warning: ignoring attributes on template argument ‘int’ [-Wignored-attributes] This commit reduces four occurrences of make_unsigned<_Atomic_word> into two, one in bits/shared_ptr_base.h and one in ext/atomicity.h, and uses diagnostic pragmas around the two remaining uses to avoid the warnings. Because the unsigned type might have lost the alignment of _Atomic_word that is needed for atomic ops (at least on cris-elf), the unsigned type should only be used for plain non-atomic arithmetic. To prevent misuse, it's defined as a private type in _Sp_counted_base, and is defined and then undefined as a macro in ext/atomicity.h, so that it's not usable after __exchange_and_add_single and __atomic_add_single have been defined. We also get a warning from instantiating __int_traits<_Atomic_word> in shared_ptr_base.h which can be avoided by calculating the maximum signed value from the maximum unsigned value. libstdc++-v3/ChangeLog: PR libstdc++/122172 * include/bits/shared_ptr_base.h (_Sp_counted_base): Define _Unsigned_count_type for make_unsigned<_Atomic_word>. Replace __int_traits<_Atomic_word> with equivalent expression. * include/ext/atomicity.h (_GLIBCXX_UNSIGNED_ATOMIC_WORD): Define macro for unsigned type to use for arithmetic. (__exchange_and_add_single, __atomic_add_single): Use it. Reviewed-by: Hans-Peter Nilsson <hp@axis.com>
This commit is contained in:
parent
52ee235811
commit
385984f555
|
@ -230,25 +230,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
long
|
||||
_M_get_use_count() const noexcept
|
||||
{
|
||||
// No memory barrier is used here so there is no synchronization
|
||||
// with other threads.
|
||||
auto __count = __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED);
|
||||
|
||||
// If long is wider than _Atomic_word then we can treat _Atomic_word
|
||||
// as unsigned, and so double its usable range. If the widths are the
|
||||
// same then casting to unsigned and then to long is a no-op.
|
||||
using _Up = typename make_unsigned<_Atomic_word>::type;
|
||||
|
||||
// No memory barrier is used here so there is no synchronization
|
||||
// with other threads.
|
||||
return (_Up) __atomic_load_n(&_M_use_count, __ATOMIC_RELAXED);
|
||||
return static_cast<_Unsigned_count_type>(__count);
|
||||
}
|
||||
|
||||
private:
|
||||
_Sp_counted_base(_Sp_counted_base const&) = delete;
|
||||
_Sp_counted_base& operator=(_Sp_counted_base const&) = delete;
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wignored-attributes"
|
||||
// This is only to be used for arithmetic, not for atomic ops.
|
||||
using _Unsigned_count_type = make_unsigned<_Atomic_word>::type;
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// Called when incrementing _M_use_count to cause a trap on overflow.
|
||||
// This should be passed the value of the counter before the increment.
|
||||
static void
|
||||
_S_chk(_Atomic_word __count)
|
||||
{
|
||||
constexpr _Atomic_word __max_atomic_word = _Unsigned_count_type(-1)/2;
|
||||
|
||||
// __max is the maximum allowed value for the shared reference count.
|
||||
// All valid reference count values need to fit into [0,LONG_MAX)
|
||||
// because users can observe the count via shared_ptr::use_count().
|
||||
|
@ -266,8 +274,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
// would not fit in [0,LONG_MAX) after casting to an unsigned type,
|
||||
// which would cause use_count() to return bogus values.
|
||||
constexpr _Atomic_word __max
|
||||
= sizeof(long) > sizeof(_Atomic_word)
|
||||
? -1 : __gnu_cxx::__int_traits<_Atomic_word>::__max;
|
||||
= sizeof(long) > sizeof(_Atomic_word) ? -1 : __max_atomic_word;
|
||||
|
||||
if (__count == __max) [[__unlikely__]]
|
||||
__builtin_trap();
|
||||
|
@ -300,8 +307,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
inline long
|
||||
_Sp_counted_base<_S_single>::_M_get_use_count() const noexcept
|
||||
{
|
||||
using _Up = typename make_unsigned<_Atomic_word>::type;
|
||||
return (_Up) _M_use_count;
|
||||
return static_cast<_Unsigned_count_type>(_M_use_count);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -90,20 +90,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
_Atomic_word_fits_in_long[sizeof(_Atomic_word) <= sizeof(long) ? 1 : -1];
|
||||
#endif
|
||||
|
||||
// Targets where _Atomic_word uses __attribute__((__aligned__(n))) will get
|
||||
// a warning for make_unsigned<_Atomic_word>. That warning can be ignored,
|
||||
// because we only need an unsigned type, we don't care about its alignment.
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wignored-attributes"
|
||||
|
||||
// We need an unsigned type that can be used for the arithmetic below.
|
||||
// This type must not be use for atomic ops because it might not be
|
||||
// sufficiently aligned. Define it as a macro that we #undef below,
|
||||
// to prevent misuse elsewhere in the library.
|
||||
#if __cplusplus >= 201103L
|
||||
# define _GLIBCXX_UNSIGNED_ATOMIC_WORD std::make_unsigned<_Atomic_word>::type
|
||||
#else
|
||||
// For most targets make_unsigned_t<_Atomic_word> is unsigned int,
|
||||
// but 64-bit sparc uses long for _Atomic_word, so needs unsigned long.
|
||||
// Sign-extending to unsigned long works for both cases, so use that.
|
||||
# define _GLIBCXX_UNSIGNED_ATOMIC_WORD unsigned long
|
||||
#endif
|
||||
|
||||
inline _Atomic_word
|
||||
__attribute__((__always_inline__))
|
||||
__exchange_and_add_single(_Atomic_word* __mem, int __val)
|
||||
{
|
||||
_Atomic_word __result = *__mem;
|
||||
// Do the addition with an unsigned type so that overflow is well defined.
|
||||
#if __cplusplus >= 201103L
|
||||
std::make_unsigned<_Atomic_word>::type __u;
|
||||
#else
|
||||
// For most targets make_unsigned_t<_Atomic_word> is unsigned int,
|
||||
// but 64-bit sparc uses long for _Atomic_word.
|
||||
// Sign-extending to unsigned long works for both cases.
|
||||
unsigned long __u;
|
||||
#endif
|
||||
_GLIBCXX_UNSIGNED_ATOMIC_WORD __u;
|
||||
__u = __result;
|
||||
__u += __val;
|
||||
*__mem = __u;
|
||||
|
@ -114,15 +126,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
__attribute__((__always_inline__))
|
||||
__atomic_add_single(_Atomic_word* __mem, int __val)
|
||||
{
|
||||
#if __cplusplus >= 201103L
|
||||
std::make_unsigned<_Atomic_word>::type __u;
|
||||
#else
|
||||
unsigned long __u; // see above
|
||||
#endif
|
||||
_GLIBCXX_UNSIGNED_ATOMIC_WORD __u;
|
||||
__u = *__mem;
|
||||
__u += __val;
|
||||
*__mem = __u;
|
||||
}
|
||||
#undef _GLIBCXX_UNSIGNED_ATOMIC_WORD
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
inline _Atomic_word
|
||||
__attribute__ ((__always_inline__))
|
||||
|
|
Loading…
Reference in New Issue