On 31/05/24 11:07 -0300, Alexandre Oliva wrote:

A proprietary embedded operating system that uses clang as its primary
compiler ships headers that require __clang__ to be defined.  Defining
that macro causes libstdc++ to adopt workarounds that work for clang
but that break for GCC.

So, introduce a _GLIBCXX_CLANG macro, and a convention to test for it
rather than for __clang__, so that a GCC variant that adds -D__clang__
to satisfy system headers can also -D_GLIBCXX_CLANG=0 to avoid
workarounds that are not meant for GCC.

I've left fast_float and ryu files alone, their tests for __clang__
don't seem to be harmful for GCC, they don't include bits/c++config,
and patching such third-party files would just make trouble for
updating them without visible benefit.

Regstrapping on x86_64-linux-gnu.  Ok to install?

PS: I went for mechanical replacement s/__clang__/_GLIBCXX_CLANG/g which
made c++config slightly more complicated, but I'm open to making
_GLIBCXX_CLANG be defined unconditionally, using nonzero tests for it
elsewhere, if that's preferred.  I figured this would be easier to
validate: I only had to check that the modified headers used other
c++config-defined macros.

I think I prefer your approach to defining it unconditionally to zero
or one.

Comments inline below ...

for  libstdc++-v3/ChangeLog

        * include/bits/c++config (_GLIBCXX_CLANG): Define or undefine.
        * include/bits/locale_facets_nonio.tcc: Test for it.
        * include/bits/stl_bvector.h: Likewise.
        * include/c_compatibility/stdatomic.h: Likewise.
        * include/experimental/bits/simd.h: Likewise.
        * include/experimental/bits/simd_builtin.h: Likewise.
        * include/experimental/bits/simd_detail.h: Likewise.
        * include/experimental/bits/simd_x86.h: Likewise.
        * include/experimental/simd: Likewise.
        * include/std/complex: Likewise.
        * include/std/ranges: Likewise.
        * include/std/variant: Likewise.
        * include/pstl/pstl_config.h: Likewise, when defined(__GLIBCXX__).
---
libstdc++-v3/include/bits/c++config                |   13 ++++++++++++-
libstdc++-v3/include/bits/locale_facets_nonio.tcc  |    2 +-
libstdc++-v3/include/bits/stl_bvector.h            |    2 +-
libstdc++-v3/include/c_compatibility/stdatomic.h   |    2 +-
libstdc++-v3/include/experimental/bits/simd.h      |   14 +++++++-------
.../include/experimental/bits/simd_builtin.h       |    4 ++--
.../include/experimental/bits/simd_detail.h        |    8 ++++----
libstdc++-v3/include/experimental/bits/simd_x86.h  |   12 ++++++------
libstdc++-v3/include/experimental/simd             |    2 +-
libstdc++-v3/include/pstl/pstl_config.h            |    4 ++--
libstdc++-v3/include/std/complex                   |    4 ++--
libstdc++-v3/include/std/ranges                    |    8 ++++----
libstdc++-v3/include/std/variant                   |    2 +-
13 files changed, 44 insertions(+), 33 deletions(-)

diff --git a/libstdc++-v3/include/bits/c++config 
b/libstdc++-v3/include/bits/c++config
index b57e3f338e92a..6dca2d9467aa5 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -481,9 +481,20 @@ _GLIBCXX_END_NAMESPACE_VERSION
// Define if compatibility should be provided for -mlong-double-64.
#undef _GLIBCXX_LONG_DOUBLE_COMPAT

+// Use an alternate macro to test for clang, so as to provide an easy
+// workaround for systems (such as vxworks) whose headers require
+// __clang__ to be defined, even when compiling with GCC.
+#if !defined _GLIBCXX_CLANG && defined __clang__
+# define _GLIBCXX_CLANG __clang__
+// Turn -D_GLIBCXX_CLANG=0 into -U_GLIBCXX_CLANG, so that
+// _GLIBCXX_CLANG can be tested as defined, just like __clang__.
+#elif !_GLIBCXX_CLANG
+# undef _GLIBCXX_CLANG
+#endif
+
// Define if compatibility should be provided for alternative 128-bit long
// double formats. Not possible for Clang until __ibm128 is supported.
-#ifndef __clang__
+#ifndef _GLIBCXX_CLANG
#undef _GLIBCXX_LONG_DOUBLE_ALT128_COMPAT
#endif

diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.tcc 
b/libstdc++-v3/include/bits/locale_facets_nonio.tcc
index 8f67be5a6147b..72136f42f0866 100644
--- a/libstdc++-v3/include/bits/locale_facets_nonio.tcc
+++ b/libstdc++-v3/include/bits/locale_facets_nonio.tcc
@@ -1465,7 +1465,7 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
      ctype<_CharT> const& __ctype = use_facet<ctype<_CharT> >(__loc);
      __err = ios_base::goodbit;
      bool __use_state = false;
-#if __GNUC__ >= 5 && !defined(__clang__)
+#if __GNUC__ >= 5 && !defined(_GLIBCXX_CLANG)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpmf-conversions"
      // Nasty hack.  The C++ standard mandates that get invokes the do_get
diff --git a/libstdc++-v3/include/bits/stl_bvector.h 
b/libstdc++-v3/include/bits/stl_bvector.h
index d567e26f4e430..52153cadf8f70 100644
--- a/libstdc++-v3/include/bits/stl_bvector.h
+++ b/libstdc++-v3/include/bits/stl_bvector.h
@@ -185,7 +185,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CONTAINER
    void
    _M_assume_normalized() const
    {
-#if __has_attribute(__assume__) && !defined(__clang__)
+#if __has_attribute(__assume__) && !defined(_GLIBCXX_CLANG)
      unsigned int __ofst = _M_offset;
      __attribute__ ((__assume__ (__ofst < unsigned(_S_word_bit))));
#endif
diff --git a/libstdc++-v3/include/c_compatibility/stdatomic.h 
b/libstdc++-v3/include/c_compatibility/stdatomic.h
index 52daa16c9b1ed..5403b52a036d1 100644
--- a/libstdc++-v3/include/c_compatibility/stdatomic.h
+++ b/libstdc++-v3/include/c_compatibility/stdatomic.h
@@ -125,7 +125,7 @@ using std::atomic_flag_clear_explicit;
using std::atomic_thread_fence;
using std::atomic_signal_fence;

-#elif defined __clang__
+#elif defined _GLIBCXX_CLANG
# include_next <stdatomic.h>
#endif // __cpp_lib_stdatomic_h
#endif // _GLIBCXX_STDATOMIC_H
diff --git a/libstdc++-v3/include/experimental/bits/simd.h 
b/libstdc++-v3/include/experimental/bits/simd.h
index 7c52462571902..ea034138fd720 100644
--- a/libstdc++-v3/include/experimental/bits/simd.h
+++ b/libstdc++-v3/include/experimental/bits/simd.h
@@ -606,7 +606,7 @@ template <size_t _Bytes>
    static_assert(_Bytes > 0);
    if constexpr (_Bytes == sizeof(int))
      return int();
-  #ifdef __clang__
+  #ifdef _GLIBCXX_CLANG

I'd like to hear from Matthias to know he's OK with the simd changes.


    else if constexpr (_Bytes == sizeof(char))
      return char();
  #else
@@ -615,7 +615,7 @@ template <size_t _Bytes>
  #endif
    else if constexpr (_Bytes == sizeof(short))
      return short();
-  #ifndef __clang__
+  #ifndef _GLIBCXX_CLANG
    else if constexpr (_Bytes == sizeof(long))
      return long();
  #endif
@@ -1720,7 +1720,7 @@ template <typename _To, typename _From>
          __builtin_memcpy(&__r, &__v, sizeof(_To));
          return __r;
        }
-#if _GLIBCXX_SIMD_X86INTRIN && !defined __clang__
+#if _GLIBCXX_SIMD_X86INTRIN && !defined _GLIBCXX_CLANG
    else if constexpr (__have_avx && sizeof(_From) == 16 && sizeof(_To) == 32)
      return reinterpret_cast<_To>(__builtin_ia32_ps256_ps(
        reinterpret_cast<__vector_type_t<float, 4>>(__v)));
@@ -1975,7 +1975,7 @@ template <typename _TW>

// }}}
// __andnot{{{
-#if _GLIBCXX_SIMD_X86INTRIN && !defined __clang__
+#if _GLIBCXX_SIMD_X86INTRIN && !defined _GLIBCXX_CLANG
static constexpr struct
{
  _GLIBCXX_SIMD_INTRINSIC __v4sf
@@ -2035,7 +2035,7 @@ static constexpr struct
  operator()(__v8di __a, __v8di __b) const noexcept
  { return _mm512_andnot_si512(__a, __b); }
} _S_x86_andnot;
-#endif // _GLIBCXX_SIMD_X86INTRIN && !__clang__
+#endif // _GLIBCXX_SIMD_X86INTRIN && !_GLIBCXX_CLANG

template <typename _TW>
  _GLIBCXX_SIMD_INTRINSIC constexpr _TW
@@ -2046,7 +2046,7 @@ template <typename _TW>
        using _TVT = conditional_t<__is_simd_wrapper_v<_TW>, _TW,
                                   _VectorTraitsImpl<_TW>>;
        using _Tp = typename _TVT::value_type;
-#if _GLIBCXX_SIMD_X86INTRIN && !defined __clang__
+#if _GLIBCXX_SIMD_X86INTRIN && !defined _GLIBCXX_CLANG
        if constexpr (sizeof(_TW) >= 16)
          {
            const auto __ai = __to_intrin(__a);
@@ -2095,7 +2095,7 @@ template <typename _T0, typename _T1, typename _Fun, 
size_t... _Is>
    using _Tp = remove_reference_t<decltype(declval<_T0>()[0])>;
    using _RV [[maybe_unused]] = __vector_type_t<_Tp, sizeof...(_Is)>;
#if __has_builtin(__builtin_shufflevector)
-#ifdef __clang__
+#ifdef _GLIBCXX_CLANG
    // Clang requires _T0 == _T1
    if constexpr (sizeof(__x) > sizeof(__y) and _N1 == 1)
      return __vec_shuffle(__x, _T0{__y[0]}, __seq, __idx_perm);
diff --git a/libstdc++-v3/include/experimental/bits/simd_builtin.h 
b/libstdc++-v3/include/experimental/bits/simd_builtin.h
index 505f8083794e7..4abc750cfa1c2 100644
--- a/libstdc++-v3/include/experimental/bits/simd_builtin.h
+++ b/libstdc++-v3/include/experimental/bits/simd_builtin.h
@@ -1177,7 +1177,7 @@ struct _CommonImplBuiltin
      constexpr size_t _Bytes = _ReqBytes == 0 ? sizeof(__x) : _ReqBytes;
      static_assert(sizeof(__x) >= _Bytes);

-#if !defined __clang__ && _GLIBCXX_SIMD_WORKAROUND_PR90424
+#if !defined _GLIBCXX_CLANG && _GLIBCXX_SIMD_WORKAROUND_PR90424
      if constexpr (__is_vector_type_v<_TV>)
        _S_memcpy<_Bytes>(reinterpret_cast<char*>(__addr), reinterpret_cast<const 
char*>(&__x));
      else
@@ -2022,7 +2022,7 @@ template <typename _Abi, typename>
              return __vector_bitcast<float, 2>(_S_plus_minus(__x4, __y));
          }
#endif
-#if !defined __clang__ && __GCC_IEC_559 == 0
+#if !defined _GLIBCXX_CLANG && __GCC_IEC_559 == 0
        if (__builtin_is_constant_evaluated()
              || (__builtin_constant_p(__x) && __builtin_constant_p(__y)))
          return (__x + __y) - __y;
diff --git a/libstdc++-v3/include/experimental/bits/simd_detail.h 
b/libstdc++-v3/include/experimental/bits/simd_detail.h
index 51e130bd36a5e..9ddf912a62b03 100644
--- a/libstdc++-v3/include/experimental/bits/simd_detail.h
+++ b/libstdc++-v3/include/experimental/bits/simd_detail.h
@@ -262,7 +262,7 @@
#endif
//}}}

-#ifdef __clang__
+#ifdef _GLIBCXX_CLANG
#define _GLIBCXX_SIMD_NORMAL_MATH
#define _GLIBCXX_SIMD_ALWAYS_INLINE_LAMBDA
#else
@@ -277,7 +277,7 @@
#define _GLIBCXX_SIMD_IS_UNLIKELY(__x) __builtin_expect(__x, 0)
#define _GLIBCXX_SIMD_IS_LIKELY(__x) __builtin_expect(__x, 1)

-#if _GLIBCXX_SIMD_HAVE_SVE || __STRICT_ANSI__ || defined __clang__
+#if _GLIBCXX_SIMD_HAVE_SVE || __STRICT_ANSI__ || defined _GLIBCXX_CLANG
#define _GLIBCXX_SIMD_CONSTEXPR
#define _GLIBCXX_SIMD_USE_CONSTEXPR_API const
#else
@@ -285,7 +285,7 @@
#define _GLIBCXX_SIMD_USE_CONSTEXPR_API constexpr
#endif

-#if defined __clang__
+#if defined _GLIBCXX_CLANG
#define _GLIBCXX_SIMD_USE_CONSTEXPR const
#else
#define _GLIBCXX_SIMD_USE_CONSTEXPR constexpr
@@ -330,7 +330,7 @@
#endif

// integer division not optimized
-#ifndef __clang__
+#ifndef _GLIBCXX_CLANG
#define _GLIBCXX_SIMD_WORKAROUND_PR90993 1
#endif

diff --git a/libstdc++-v3/include/experimental/bits/simd_x86.h 
b/libstdc++-v3/include/experimental/bits/simd_x86.h
index 517c4b4a5bec7..4ab933b573c61 100644
--- a/libstdc++-v3/include/experimental/bits/simd_x86.h
+++ b/libstdc++-v3/include/experimental/bits/simd_x86.h
@@ -363,7 +363,7 @@ template <typename _Tp>

// }}}

-#ifdef __clang__
+#ifdef _GLIBCXX_CLANG
template <size_t _Np, typename _Tp, typename _Kp>
  _GLIBCXX_SIMD_INTRINSIC constexpr auto
  __movm(_Kp __k) noexcept
@@ -408,7 +408,7 @@ template <size_t _Np, typename _Tp, typename _Kp>
    else
      __assert_unreachable<_Tp>();
  }
-#endif // __clang__
+#endif // _GLIBCXX_CLANG

#ifdef _GLIBCXX_SIMD_WORKAROUND_PR85048
#include "simd_x86_conversions.h"
@@ -674,7 +674,7 @@ struct _CommonImplX86 : _CommonImplBuiltin
      using _Tp = typename _VectorTraits<_TV>::value_type;
      static_assert(sizeof(_TV) >= 16);
      static_assert(sizeof(_Tp) <= 8);
-#ifdef __clang__
+#ifdef _GLIBCXX_CLANG
      return __movm<_VectorTraits<_TV>::_S_full_size, _Tp>(__k) ? __b : __a;
#else
      using _IntT
@@ -3505,9 +3505,9 @@ template <typename _Abi, typename>
            // optimize masked unary increment and decrement as masked sub +/-1
            constexpr int __pm_one
              = is_same_v<_Op<void>, __increment<void>> ? -1 : 1;
-#ifdef __clang__
+#ifdef _GLIBCXX_CLANG
            return __movm<_Np, _Tp>(__k._M_data) ? __v._M_data - __pm_one : 
__v._M_data;
-#else // __clang__
+#else // _GLIBCXX_CLANG
            using _TV = __vector_type_t<_Tp, _Np>;
            constexpr size_t __bytes = sizeof(__v) < 16 ? 16 : sizeof(__v);
            constexpr size_t __width = __bytes / sizeof(_Tp);
@@ -3561,7 +3561,7 @@ template <typename _Abi, typename>
#undef _GLIBCXX_SIMD_MASK_SUB_512
#undef _GLIBCXX_SIMD_MASK_SUB
              }
-#endif // __clang__
+#endif // _GLIBCXX_CLANG
          }
        else
          return _Base::template _S_masked_unary<_Op>(__k, __v);
diff --git a/libstdc++-v3/include/experimental/simd 
b/libstdc++-v3/include/experimental/simd
index f45ad4ed2e6cc..d2d081e0d1a2a 100644
--- a/libstdc++-v3/include/experimental/simd
+++ b/libstdc++-v3/include/experimental/simd
@@ -59,7 +59,7 @@
#pragma GCC diagnostic push
// Many [[gnu::vector_size(N)]] types might lead to a -Wpsabi warning which is
// irrelevant as those functions never appear on ABI borders
-#ifndef __clang__
+#ifndef _GLIBCXX_CLANG
#pragma GCC diagnostic ignored "-Wpsabi"
#endif

diff --git a/libstdc++-v3/include/pstl/pstl_config.h 
b/libstdc++-v3/include/pstl/pstl_config.h
index ccb9dd32838d3..fcac557077bb6 100644
--- a/libstdc++-v3/include/pstl/pstl_config.h
+++ b/libstdc++-v3/include/pstl/pstl_config.h
@@ -53,7 +53,7 @@
// the actual GCC version on the system.
#define _PSTL_GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + 
__GNUC_PATCHLEVEL__)

-#if defined(__clang__)
+#if defined(__GLIBCXX__) ? defined(_GLIBCXX_CLANG) : defined(__clang__)

This file is also imported from upstream, like Ryu and fast_float.

I don't think having a "spurious" definition of _PSTL_CLANG_VERSION
here actually matters. It's only used in a header in the testsuite,
and only seems to matter for Clang 9 and older. Maybe we don't need to
care about that?

So don't change anything here at all. If we do need to change it, then
testing __GLIBCXX__ is redundant, because this copy of the file is
always used as part of libstdc++, which defines __GLIBCXX__.

So either don't change this line at all, or just do a simple
s/__clang__/_GLIBCXX_CLANG/

// according to clang documentation, version can be vendor specific
#    define _PSTL_CLANG_VERSION (__clang_major__ * 10000 + __clang_minor__ * 
100 + __clang_patchlevel__)
#endif
@@ -62,7 +62,7 @@
#if (defined(_OPENMP) && _OPENMP >= 201307) || \

This condition will be true when using g++ with -fopenmp (but not
without -fopenmp which I think means we don't want the pragmas to be
enabled unconditionally when gaslighting with -D__clang__).

    (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1600) || \
    (!defined(__INTEL_COMPILER) && _PSTL_GCC_VERSION >= 40900) || \
-    defined(__clang__)
+    defined(_PSTL_CLANG_VERSION)

If think this could just use defined(_GLIBCXX_CLANG), no?
That would mean there's only one change in this file.

Does the vxworks toolchain need to support the PSTL headers?

If not, we could just ignore this file, so the local changes don't
need to be re-applied when we import a new version of the header from
upstream.


#    define _PSTL_PRAGMA_SIMD _PSTL_PRAGMA(omp simd)
#    define _PSTL_PRAGMA_DECLARE_SIMD _PSTL_PRAGMA(omp declare simd)
#    define _PSTL_PRAGMA_SIMD_REDUCTION(PRM) _PSTL_PRAGMA(omp simd 
reduction(PRM))
diff --git a/libstdc++-v3/include/std/complex b/libstdc++-v3/include/std/complex
index 415c735665c3e..be810b6d05d25 100644
--- a/libstdc++-v3/include/std/complex
+++ b/libstdc++-v3/include/std/complex
@@ -47,7 +47,7 @@
// Get rid of a macro possibly defined in <complex.h>
#undef complex

-#ifdef __clang__
+#ifdef _GLIBCXX_CLANG
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc99-extensions"
#endif
@@ -2646,7 +2646,7 @@ _GLIBCXX_END_NAMESPACE_VERSION

#endif  // C++11

-#ifdef __clang__
+#ifdef _GLIBCXX_CLANG
#pragma clang diagnostic pop
#endif

diff --git a/libstdc++-v3/include/std/ranges b/libstdc++-v3/include/std/ranges
index b1e827c9a7241..3f335b95a0864 100644
--- a/libstdc++-v3/include/std/ranges
+++ b/libstdc++-v3/include/std/ranges
@@ -4687,7 +4687,7 @@ namespace views::__adaptor
  class zip_view<_Vs...>::_Iterator
    : public __detail::__zip_view_iter_cat<_Const, _Vs...>
  {
-#ifdef __clang__ // LLVM-61763 workaround
+#ifdef _GLIBCXX_CLANG // LLVM-61763 workaround

This one doesn't matter, since making these members public for a "fake
clang" doesn't really hurt anything. For consistency maybe it makes
sense to use _GLIBCXX_CLANG anyway.

Ditto for the rest of this file.

  public:
#endif
    tuple<iterator_t<__detail::__maybe_const_t<_Const, _Vs>>...> _M_current;
@@ -4710,7 +4710,7 @@ namespace views::__adaptor
        return input_iterator_tag{};
    }

-#ifndef __clang__ // LLVM-61763 workaround
+#ifndef _GLIBCXX_CLANG // LLVM-61763 workaround
    template<move_constructible _Fp, input_range... _Ws>
      requires (view<_Ws> && ...) && (sizeof...(_Ws) > 0) && is_object_v<_Fp>
        && regular_invocable<_Fp&, range_reference_t<_Ws>...>
@@ -5387,7 +5387,7 @@ namespace views::__adaptor
  template<bool _Const>
  class adjacent_view<_Vp, _Nm>::_Iterator
  {
-#ifdef __clang__ // LLVM-61763 workaround
+#ifdef _GLIBCXX_CLANG // LLVM-61763 workaround
  public:
#endif
    using _Base = __detail::__maybe_const_t<_Const, _Vp>;
@@ -5430,7 +5430,7 @@ namespace views::__adaptor

    friend class adjacent_view;

-#ifndef __clang__ // LLVM-61763 workaround
+#ifndef _GLIBCXX_CLANG // LLVM-61763 workaround
    template<forward_range _Wp, move_constructible _Fp, size_t _Mm>
      requires view<_Wp> && (_Mm > 0) && is_object_v<_Fp>
        && regular_invocable<__detail::__unarize<_Fp&, _Mm>, 
range_reference_t<_Wp>>
diff --git a/libstdc++-v3/include/std/variant b/libstdc++-v3/include/std/variant
index 371cbb90f54a6..51aaa62085170 100644
--- a/libstdc++-v3/include/std/variant
+++ b/libstdc++-v3/include/std/variant
@@ -1758,7 +1758,7 @@ namespace __detail::__variant
          }, __rhs);
      }

-#if defined(__clang__) && __clang_major__ <= 7
+#if defined(_GLIBCXX_CLANG) && __clang_major__ <= 7

I think we could drop this kluge entirely, clang 7 is old now, we
generally only support the most recent 3 or 4 clang versions.

    public:
      using _Base::_M_u; // See https://bugs.llvm.org/show_bug.cgi?id=31852
#endif

--
Alexandre Oliva, happy hacker            https://FSFLA.org/blogs/lxo/
  Free Software Activist                   GNU Toolchain Engineer
More tolerance and less prejudice are key for inclusion and diversity
Excluding neuro-others for not behaving ""normal"" is *not* inclusive

Reply via email to