Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 12 Mar 2026 23:46:29 +0000
From:      Dimitry Andric <dim@FreeBSD.org>
To:        ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org
Subject:   git: 37ed2bf6371b - main - devel/gcc-arm-embedded: fix build with clang 21
Message-ID:  <69b35055.22cc6.74ea6c82@gitrepo.freebsd.org>

index | next in thread | raw e-mail

The branch main has been updated by dim:

URL: https://cgit.FreeBSD.org/ports/commit/?id=37ed2bf6371b0b273013a710ee32f6addf768a62

commit 37ed2bf6371b0b273013a710ee32f6addf768a62
Author:     Dimitry Andric <dim@FreeBSD.org>
AuthorDate: 2026-02-13 21:28:34 +0000
Commit:     Dimitry Andric <dim@FreeBSD.org>
CommitDate: 2026-03-12 23:46:18 +0000

    devel/gcc-arm-embedded: fix build with clang 21
    
    With clang 21 devel/gcc-arm-embedded fails to build, with errors similar
    to:
    
          /wrkdirs/usr/ports/devel/gcc-arm-embedded/work-default/src/binutils-gdb/binutils/readelf.c:23278:37: error: pointer comparison always evaluates to false [-Werror,-Wtautological-compare]
           23278 |           || inote.namedata + inote.namesz < inote.namedata)
                 |                                            ^
    
    and later many instances of:
    
        In file included from <built-in>:1:
        In file included from /wrkdirs/usr/ports/devel/gcc-arm-embedded/work-default/src/binutils-gdb--gdb/gdb/defs.h:63:
        /wrkdirs/usr/ports/devel/gcc-arm-embedded/work-default/src/binutils-gdb--gdb/gdb/../gdbsupport/enum-flags.h:97:34: error: non-type
              template argument is not a constant expression
           97 |     integer_for_size<sizeof (T), static_cast<bool>(T (-1) < T (0))>::type
              |                                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        /wrkdirs/usr/ports/devel/gcc-arm-embedded/work-default/src/binutils-gdb--gdb/gdb/../gdbsupport/enum-flags.h:134:20: note: in
              instantiation of template class 'enum_underlying_type<ui_out_flag>' requested here
          134 |   typedef typename enum_underlying_type<enum_type>::type underlying_type;
              |                    ^
        /wrkdirs/usr/ports/devel/gcc-arm-embedded/work-default/src/binutils-gdb--gdb/gdb/ui-out.h:385:16: note: in instantiation of template
              class 'enum_flags<ui_out_flag>' requested here
          385 |   ui_out_flags m_flags;
              |                ^
        /wrkdirs/usr/ports/devel/gcc-arm-embedded/work-default/src/binutils-gdb--gdb/gdb/../gdbsupport/enum-flags.h:97:52: note: integer value
              -1 is outside the valid range of values [0, 15] for the enumeration type 'ui_out_flag'
           97 |     integer_for_size<sizeof (T), static_cast<bool>(T (-1) < T (0))>::type
              |                                                    ^
    
    The readelf error is due to it assuming pointer wrapping, which is
    undefined behavior. This can be worked around by casting the pointers to
    uintptr_t, or by adding -fno-strict-overflow to the CFLAGS (but if you
    are messing with the CFLAGS, you might as well disable -Werror).
    
    The enum errors are because it is no longer allowed to cast integer
    values to enum values, if they fall outside of the valid range. Upstream
    fixed this in
    <https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commit;h=4a0b2cb7210>,
    which applies with a small bit of editing.
    
    PR:             293168
    Approved by:    maintainer timeout (2 weeks)
    MFH:            2026Q1
---
 ...s-gdb--gdb_gdb_unittests_enum-flags-selftests.c |  36 +++++
 ...patch-binutils-gdb--gdb_gdbsupport_enum-flags.h | 156 +++++++++++++++++++++
 .../patch-binutils-gdb--gdb_include_diagnostics.h  |  25 ++++
 .../files/patch-binutils-gdb_binutils_readelf.c    |  11 ++
 ...nutils-gdb_gdb_unittests_enum-flags-selftests.c |  36 +++++
 .../patch-binutils-gdb_gdbsupport_enum-flags.h     | 156 +++++++++++++++++++++
 .../files/patch-binutils-gdb_include_diagnostics.h |  25 ++++
 7 files changed, 445 insertions(+)

diff --git a/devel/gcc-arm-embedded/files/patch-binutils-gdb--gdb_gdb_unittests_enum-flags-selftests.c b/devel/gcc-arm-embedded/files/patch-binutils-gdb--gdb_gdb_unittests_enum-flags-selftests.c
new file mode 100644
index 000000000000..3819039c420b
--- /dev/null
+++ b/devel/gcc-arm-embedded/files/patch-binutils-gdb--gdb_gdb_unittests_enum-flags-selftests.c
@@ -0,0 +1,36 @@
+--- binutils-gdb--gdb/gdb/unittests/enum-flags-selftests.c.orig	2024-11-30 00:01:16 UTC
++++ binutils-gdb--gdb/gdb/unittests/enum-flags-selftests.c
+@@ -233,33 +233,6 @@ CHECK_VALID (true,  EF,   true ? RE () : EF ())
+ CHECK_VALID (true,  EF,   true ? EF () : RE ())
+ CHECK_VALID (true,  EF,   true ? RE () : EF ())
+ 
+-/* These are valid, but it's not a big deal since you won't be able to
+-   assign the resulting integer to an enum or an enum_flags without a
+-   cast.
+-
+-   The latter two tests are disabled on older GCCs because they
+-   incorrectly fail with gcc 4.8 and 4.9 at least.  Running the test
+-   outside a SFINAE context shows:
+-
+-    invalid user-defined conversion from ‘EF’ to ‘RE2’
+-
+-   They've been confirmed to compile/pass with gcc 5.3, gcc 7.1 and
+-   clang 3.7.  */
+-
+-CHECK_VALID (true,  int,  true ? EF () : EF2 ())
+-CHECK_VALID (true,  int,  true ? EF2 () : EF ())
+-CHECK_VALID (true,  int,  true ? EF () : RE2 ())
+-CHECK_VALID (true,  int,  true ? RE2 () : EF ())
+-
+-/* Same, but with an unsigned enum.  */
+-
+-typedef unsigned int uns;
+-
+-CHECK_VALID (true,  uns,  true ? EF () : UEF ())
+-CHECK_VALID (true,  uns,  true ? UEF () : EF ())
+-CHECK_VALID (true,  uns,  true ? EF () : URE ())
+-CHECK_VALID (true,  uns,  true ? URE () : EF ())
+-
+ /* Unfortunately this can't work due to the way C++ computes the
+    return type of the ternary conditional operator.  int isn't
+    implicitly convertible to the raw enum type, so the type of the
diff --git a/devel/gcc-arm-embedded/files/patch-binutils-gdb--gdb_gdbsupport_enum-flags.h b/devel/gcc-arm-embedded/files/patch-binutils-gdb--gdb_gdbsupport_enum-flags.h
new file mode 100644
index 000000000000..de82593c10f0
--- /dev/null
+++ b/devel/gcc-arm-embedded/files/patch-binutils-gdb--gdb_gdbsupport_enum-flags.h
@@ -0,0 +1,156 @@
+--- binutils-gdb--gdb/gdbsupport/enum-flags.h.orig	2024-11-30 00:01:16 UTC
++++ binutils-gdb--gdb/gdbsupport/enum-flags.h
+@@ -75,30 +75,6 @@
+    namespace.  The compiler finds the corresponding
+    is_enum_flags_enum_type function via ADL.  */
+ 
+-/* Note that std::underlying_type<enum_type> is not what we want here,
+-   since that returns unsigned int even when the enum decays to signed
+-   int.  */
+-template<int size, bool sign> class integer_for_size { typedef void type; };
+-template<> struct integer_for_size<1, 0> { typedef uint8_t type; };
+-template<> struct integer_for_size<2, 0> { typedef uint16_t type; };
+-template<> struct integer_for_size<4, 0> { typedef uint32_t type; };
+-template<> struct integer_for_size<8, 0> { typedef uint64_t type; };
+-template<> struct integer_for_size<1, 1> { typedef int8_t type; };
+-template<> struct integer_for_size<2, 1> { typedef int16_t type; };
+-template<> struct integer_for_size<4, 1> { typedef int32_t type; };
+-template<> struct integer_for_size<8, 1> { typedef int64_t type; };
+-
+-template<typename T>
+-struct enum_underlying_type
+-{
+-  DIAGNOSTIC_PUSH
+-  DIAGNOSTIC_IGNORE_ENUM_CONSTEXPR_CONVERSION
+-  typedef typename
+-    integer_for_size<sizeof (T), static_cast<bool>(T (-1) < T (0))>::type
+-    type;
+-  DIAGNOSTIC_POP
+-};
+-
+ namespace enum_flags_detail
+ {
+ 
+@@ -119,11 +95,62 @@ using EnumIsUnsigned
+ /* gdb::Requires trait helpers.  */
+ template <typename enum_type>
+ using EnumIsUnsigned
+-  = std::is_unsigned<typename enum_underlying_type<enum_type>::type>;
++  = std::is_unsigned<typename std::underlying_type<enum_type>::type>;
++
++/* Helper to detect whether an enum has a fixed underlying type. This can be
++   achieved by using a scoped enum (in which case the type is "int") or
++   an explicit underlying type. C-style enums that are unscoped or do not
++   have an explicit underlying type have an implementation-defined underlying
++   type.
++
++   https://timsong-cpp.github.io/cppwp/n4659/dcl.enum#5
++
++   We need this trait in order to ensure that operator~ below does NOT
++   operate on old-style enums. This is because we apply operator~ on
++   the value and then cast the result to the enum_type. This is however
++   Undefined Behavior if the result does not fit in the range of possible
++   values for the enum. For enums with fixed underlying type, the entire
++   range of the integer is available. However, for old-style enums, the range
++   is only the smallest bit-field that can hold all the values of the
++   enumeration, typically much smaller than the underlying integer:
++
++   https://timsong-cpp.github.io/cppwp/n4659/expr.static.cast#10
++   https://timsong-cpp.github.io/cppwp/n4659/dcl.enum#8
++
++   To implement this, we leverage the fact that, since C++17, enums with
++   fixed underlying type can be list-initialized from an integer:
++   https://timsong-cpp.github.io/cppwp/n4659/dcl.init.list#3.7
++
++   Old-style enums cannot be initialized like that, leading to ill-formed
++   code.
++
++   We then use this together with SFINAE to create the desired trait.
++
++*/
++template <typename enum_type, typename = void>
++struct EnumHasFixedUnderlyingType : std::false_type
++{
++  static_assert(std::is_enum<enum_type>::value);
++};
++
++/* Specialization that is active only if enum_type can be
++   list-initialized from an integer (0).  Only enums with fixed
++   underlying type satisfy this property in C++17.  */
+ template <typename enum_type>
+-using EnumIsSigned
+-  = std::is_signed<typename enum_underlying_type<enum_type>::type>;
++struct EnumHasFixedUnderlyingType<enum_type, std::void_t<decltype(enum_type{0})>> : std::true_type
++{
++  static_assert(std::is_enum<enum_type>::value);
++};
+ 
++template <typename enum_type>
++using EnumIsSafeForBitwiseComplement = std::conjunction<
++  EnumIsUnsigned<enum_type>,
++  EnumHasFixedUnderlyingType<enum_type>
++>;
++
++template <typename enum_type>
++using EnumIsUnsafeForBitwiseComplement = std::negation<EnumIsSafeForBitwiseComplement<enum_type>>;
++
+ }
+ 
+ template <typename E>
+@@ -131,7 +158,7 @@ class enum_flags (public)
+ {
+ public:
+   typedef E enum_type;
+-  typedef typename enum_underlying_type<enum_type>::type underlying_type;
++  typedef typename std::underlying_type<enum_type>::type underlying_type;
+ 
+   /* For to_string.  Maps one enumerator of E to a string.  */
+   struct string_mapping
+@@ -394,33 +421,41 @@ template <typename enum_type,
+ template <typename enum_type,
+ 	  typename = is_enum_flags_enum_type_t<enum_type>,
+ 	  typename
+-	    = gdb::Requires<enum_flags_detail::EnumIsUnsigned<enum_type>>>
++	    = gdb::Requires<enum_flags_detail::EnumIsSafeForBitwiseComplement<enum_type>>>
+ constexpr enum_type
+ operator~ (enum_type e)
+ {
+   using underlying = typename enum_flags<enum_type>::underlying_type;
+-  return (enum_type) ~underlying (e);
++  /* Cast to ULONGEST first, to prevent integer promotions from enums
++     with fixed underlying type std::uint8_t or std::uint16_t to
++     signed int.  This ensures we apply the bitwise complement on an
++     unsigned type.  */
++  return (enum_type)(underlying) ~ULONGEST (e);
+ }
+ 
+ template <typename enum_type,
+ 	  typename = is_enum_flags_enum_type_t<enum_type>,
+-	  typename = gdb::Requires<enum_flags_detail::EnumIsSigned<enum_type>>>
++	  typename = gdb::Requires<enum_flags_detail::EnumIsUnsafeForBitwiseComplement<enum_type>>>
+ constexpr void operator~ (enum_type e) = delete;
+ 
+ template <typename enum_type,
+ 	  typename = is_enum_flags_enum_type_t<enum_type>,
+ 	  typename
+-	    = gdb::Requires<enum_flags_detail::EnumIsUnsigned<enum_type>>>
++	    = gdb::Requires<enum_flags_detail::EnumIsSafeForBitwiseComplement<enum_type>>>
+ constexpr enum_flags<enum_type>
+ operator~ (enum_flags<enum_type> e)
+ {
+   using underlying = typename enum_flags<enum_type>::underlying_type;
+-  return (enum_type) ~underlying (e);
++  /* Cast to ULONGEST first, to prevent integer promotions from enums
++     with fixed underlying type std::uint8_t or std::uint16_t to
++     signed int.  This ensures we apply the bitwise complement on an
++     unsigned type.  */
++  return (enum_type)(underlying) ~ULONGEST (e);
+ }
+ 
+ template <typename enum_type,
+ 	  typename = is_enum_flags_enum_type_t<enum_type>,
+-	  typename = gdb::Requires<enum_flags_detail::EnumIsSigned<enum_type>>>
++	  typename = gdb::Requires<enum_flags_detail::EnumIsUnsafeForBitwiseComplement<enum_type>>>
+ constexpr void operator~ (enum_flags<enum_type> e) = delete;
+ 
+ /* Delete operator<< and operator>>.  */
diff --git a/devel/gcc-arm-embedded/files/patch-binutils-gdb--gdb_include_diagnostics.h b/devel/gcc-arm-embedded/files/patch-binutils-gdb--gdb_include_diagnostics.h
new file mode 100644
index 000000000000..109e6c4fe8c5
--- /dev/null
+++ b/devel/gcc-arm-embedded/files/patch-binutils-gdb--gdb_include_diagnostics.h
@@ -0,0 +1,25 @@
+--- binutils-gdb--gdb/include/diagnostics.h.orig	2024-11-30 00:01:16 UTC
++++ binutils-gdb--gdb/include/diagnostics.h
+@@ -76,11 +76,6 @@
+ # define DIAGNOSTIC_ERROR_SWITCH \
+   DIAGNOSTIC_ERROR ("-Wswitch")
+ 
+-# if __has_warning ("-Wenum-constexpr-conversion")
+-#  define DIAGNOSTIC_IGNORE_ENUM_CONSTEXPR_CONVERSION \
+-   DIAGNOSTIC_IGNORE ("-Wenum-constexpr-conversion")
+-# endif
+-
+ #elif defined (__GNUC__) /* GCC */
+ 
+ # define DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS \
+@@ -157,10 +152,6 @@
+ 
+ #ifndef DIAGNOSTIC_ERROR_SWITCH
+ # define DIAGNOSTIC_ERROR_SWITCH
+-#endif
+-
+-#ifndef DIAGNOSTIC_IGNORE_ENUM_CONSTEXPR_CONVERSION
+-# define DIAGNOSTIC_IGNORE_ENUM_CONSTEXPR_CONVERSION
+ #endif
+ 
+ #endif /* DIAGNOSTICS_H */
diff --git a/devel/gcc-arm-embedded/files/patch-binutils-gdb_binutils_readelf.c b/devel/gcc-arm-embedded/files/patch-binutils-gdb_binutils_readelf.c
new file mode 100644
index 000000000000..15329156a357
--- /dev/null
+++ b/devel/gcc-arm-embedded/files/patch-binutils-gdb_binutils_readelf.c
@@ -0,0 +1,11 @@
+--- binutils-gdb/binutils/readelf.c.orig	2024-11-20 17:30:17 UTC
++++ binutils-gdb/binutils/readelf.c
+@@ -23275,7 +23275,7 @@ process_v850_notes (Filedata * filedata, uint64_t offs
+ 
+       /* Prevent out-of-bounds indexing.  */
+       if (   inote.namedata + inote.namesz > end
+-	  || inote.namedata + inote.namesz < inote.namedata)
++	  || (uintptr_t)inote.namedata + inote.namesz < (uintptr_t)inote.namedata)
+         {
+           warn (_("corrupt namesz found in note at offset %#zx\n"),
+                 (char *) external - (char *) pnotes);
diff --git a/devel/gcc-arm-embedded/files/patch-binutils-gdb_gdb_unittests_enum-flags-selftests.c b/devel/gcc-arm-embedded/files/patch-binutils-gdb_gdb_unittests_enum-flags-selftests.c
new file mode 100644
index 000000000000..d402a5ebbf08
--- /dev/null
+++ b/devel/gcc-arm-embedded/files/patch-binutils-gdb_gdb_unittests_enum-flags-selftests.c
@@ -0,0 +1,36 @@
+--- binutils-gdb/gdb/unittests/enum-flags-selftests.c.orig	2024-11-20 17:30:17 UTC
++++ binutils-gdb/gdb/unittests/enum-flags-selftests.c
+@@ -233,33 +233,6 @@ CHECK_VALID (true,  EF,   true ? RE () : EF ())
+ CHECK_VALID (true,  EF,   true ? EF () : RE ())
+ CHECK_VALID (true,  EF,   true ? RE () : EF ())
+ 
+-/* These are valid, but it's not a big deal since you won't be able to
+-   assign the resulting integer to an enum or an enum_flags without a
+-   cast.
+-
+-   The latter two tests are disabled on older GCCs because they
+-   incorrectly fail with gcc 4.8 and 4.9 at least.  Running the test
+-   outside a SFINAE context shows:
+-
+-    invalid user-defined conversion from ‘EF’ to ‘RE2’
+-
+-   They've been confirmed to compile/pass with gcc 5.3, gcc 7.1 and
+-   clang 3.7.  */
+-
+-CHECK_VALID (true,  int,  true ? EF () : EF2 ())
+-CHECK_VALID (true,  int,  true ? EF2 () : EF ())
+-CHECK_VALID (true,  int,  true ? EF () : RE2 ())
+-CHECK_VALID (true,  int,  true ? RE2 () : EF ())
+-
+-/* Same, but with an unsigned enum.  */
+-
+-typedef unsigned int uns;
+-
+-CHECK_VALID (true,  uns,  true ? EF () : UEF ())
+-CHECK_VALID (true,  uns,  true ? UEF () : EF ())
+-CHECK_VALID (true,  uns,  true ? EF () : URE ())
+-CHECK_VALID (true,  uns,  true ? URE () : EF ())
+-
+ /* Unfortunately this can't work due to the way C++ computes the
+    return type of the ternary conditional operator.  int isn't
+    implicitly convertible to the raw enum type, so the type of the
diff --git a/devel/gcc-arm-embedded/files/patch-binutils-gdb_gdbsupport_enum-flags.h b/devel/gcc-arm-embedded/files/patch-binutils-gdb_gdbsupport_enum-flags.h
new file mode 100644
index 000000000000..8608c93cea35
--- /dev/null
+++ b/devel/gcc-arm-embedded/files/patch-binutils-gdb_gdbsupport_enum-flags.h
@@ -0,0 +1,156 @@
+--- binutils-gdb/gdbsupport/enum-flags.h.orig	2024-11-20 17:30:17 UTC
++++ binutils-gdb/gdbsupport/enum-flags.h
+@@ -75,30 +75,6 @@
+    namespace.  The compiler finds the corresponding
+    is_enum_flags_enum_type function via ADL.  */
+ 
+-/* Note that std::underlying_type<enum_type> is not what we want here,
+-   since that returns unsigned int even when the enum decays to signed
+-   int.  */
+-template<int size, bool sign> class integer_for_size { typedef void type; };
+-template<> struct integer_for_size<1, 0> { typedef uint8_t type; };
+-template<> struct integer_for_size<2, 0> { typedef uint16_t type; };
+-template<> struct integer_for_size<4, 0> { typedef uint32_t type; };
+-template<> struct integer_for_size<8, 0> { typedef uint64_t type; };
+-template<> struct integer_for_size<1, 1> { typedef int8_t type; };
+-template<> struct integer_for_size<2, 1> { typedef int16_t type; };
+-template<> struct integer_for_size<4, 1> { typedef int32_t type; };
+-template<> struct integer_for_size<8, 1> { typedef int64_t type; };
+-
+-template<typename T>
+-struct enum_underlying_type
+-{
+-  DIAGNOSTIC_PUSH
+-  DIAGNOSTIC_IGNORE_ENUM_CONSTEXPR_CONVERSION
+-  typedef typename
+-    integer_for_size<sizeof (T), static_cast<bool>(T (-1) < T (0))>::type
+-    type;
+-  DIAGNOSTIC_POP
+-};
+-
+ namespace enum_flags_detail
+ {
+ 
+@@ -119,11 +95,62 @@ using EnumIsUnsigned
+ /* gdb::Requires trait helpers.  */
+ template <typename enum_type>
+ using EnumIsUnsigned
+-  = std::is_unsigned<typename enum_underlying_type<enum_type>::type>;
++  = std::is_unsigned<typename std::underlying_type<enum_type>::type>;
++
++/* Helper to detect whether an enum has a fixed underlying type. This can be
++   achieved by using a scoped enum (in which case the type is "int") or
++   an explicit underlying type. C-style enums that are unscoped or do not
++   have an explicit underlying type have an implementation-defined underlying
++   type.
++
++   https://timsong-cpp.github.io/cppwp/n4659/dcl.enum#5
++
++   We need this trait in order to ensure that operator~ below does NOT
++   operate on old-style enums. This is because we apply operator~ on
++   the value and then cast the result to the enum_type. This is however
++   Undefined Behavior if the result does not fit in the range of possible
++   values for the enum. For enums with fixed underlying type, the entire
++   range of the integer is available. However, for old-style enums, the range
++   is only the smallest bit-field that can hold all the values of the
++   enumeration, typically much smaller than the underlying integer:
++
++   https://timsong-cpp.github.io/cppwp/n4659/expr.static.cast#10
++   https://timsong-cpp.github.io/cppwp/n4659/dcl.enum#8
++
++   To implement this, we leverage the fact that, since C++17, enums with
++   fixed underlying type can be list-initialized from an integer:
++   https://timsong-cpp.github.io/cppwp/n4659/dcl.init.list#3.7
++
++   Old-style enums cannot be initialized like that, leading to ill-formed
++   code.
++
++   We then use this together with SFINAE to create the desired trait.
++
++*/
++template <typename enum_type, typename = void>
++struct EnumHasFixedUnderlyingType : std::false_type
++{
++  static_assert(std::is_enum<enum_type>::value);
++};
++
++/* Specialization that is active only if enum_type can be
++   list-initialized from an integer (0).  Only enums with fixed
++   underlying type satisfy this property in C++17.  */
+ template <typename enum_type>
+-using EnumIsSigned
+-  = std::is_signed<typename enum_underlying_type<enum_type>::type>;
++struct EnumHasFixedUnderlyingType<enum_type, std::void_t<decltype(enum_type{0})>> : std::true_type
++{
++  static_assert(std::is_enum<enum_type>::value);
++};
+ 
++template <typename enum_type>
++using EnumIsSafeForBitwiseComplement = std::conjunction<
++  EnumIsUnsigned<enum_type>,
++  EnumHasFixedUnderlyingType<enum_type>
++>;
++
++template <typename enum_type>
++using EnumIsUnsafeForBitwiseComplement = std::negation<EnumIsSafeForBitwiseComplement<enum_type>>;
++
+ }
+ 
+ template <typename E>
+@@ -131,7 +158,7 @@ class enum_flags (public)
+ {
+ public:
+   typedef E enum_type;
+-  typedef typename enum_underlying_type<enum_type>::type underlying_type;
++  typedef typename std::underlying_type<enum_type>::type underlying_type;
+ 
+   /* For to_string.  Maps one enumerator of E to a string.  */
+   struct string_mapping
+@@ -394,33 +421,41 @@ template <typename enum_type,
+ template <typename enum_type,
+ 	  typename = is_enum_flags_enum_type_t<enum_type>,
+ 	  typename
+-	    = gdb::Requires<enum_flags_detail::EnumIsUnsigned<enum_type>>>
++	    = gdb::Requires<enum_flags_detail::EnumIsSafeForBitwiseComplement<enum_type>>>
+ constexpr enum_type
+ operator~ (enum_type e)
+ {
+   using underlying = typename enum_flags<enum_type>::underlying_type;
+-  return (enum_type) ~underlying (e);
++  /* Cast to ULONGEST first, to prevent integer promotions from enums
++     with fixed underlying type std::uint8_t or std::uint16_t to
++     signed int.  This ensures we apply the bitwise complement on an
++     unsigned type.  */
++  return (enum_type)(underlying) ~ULONGEST (e);
+ }
+ 
+ template <typename enum_type,
+ 	  typename = is_enum_flags_enum_type_t<enum_type>,
+-	  typename = gdb::Requires<enum_flags_detail::EnumIsSigned<enum_type>>>
++	  typename = gdb::Requires<enum_flags_detail::EnumIsUnsafeForBitwiseComplement<enum_type>>>
+ constexpr void operator~ (enum_type e) = delete;
+ 
+ template <typename enum_type,
+ 	  typename = is_enum_flags_enum_type_t<enum_type>,
+ 	  typename
+-	    = gdb::Requires<enum_flags_detail::EnumIsUnsigned<enum_type>>>
++	    = gdb::Requires<enum_flags_detail::EnumIsSafeForBitwiseComplement<enum_type>>>
+ constexpr enum_flags<enum_type>
+ operator~ (enum_flags<enum_type> e)
+ {
+   using underlying = typename enum_flags<enum_type>::underlying_type;
+-  return (enum_type) ~underlying (e);
++  /* Cast to ULONGEST first, to prevent integer promotions from enums
++     with fixed underlying type std::uint8_t or std::uint16_t to
++     signed int.  This ensures we apply the bitwise complement on an
++     unsigned type.  */
++  return (enum_type)(underlying) ~ULONGEST (e);
+ }
+ 
+ template <typename enum_type,
+ 	  typename = is_enum_flags_enum_type_t<enum_type>,
+-	  typename = gdb::Requires<enum_flags_detail::EnumIsSigned<enum_type>>>
++	  typename = gdb::Requires<enum_flags_detail::EnumIsUnsafeForBitwiseComplement<enum_type>>>
+ constexpr void operator~ (enum_flags<enum_type> e) = delete;
+ 
+ /* Delete operator<< and operator>>.  */
diff --git a/devel/gcc-arm-embedded/files/patch-binutils-gdb_include_diagnostics.h b/devel/gcc-arm-embedded/files/patch-binutils-gdb_include_diagnostics.h
new file mode 100644
index 000000000000..6176e26fc03c
--- /dev/null
+++ b/devel/gcc-arm-embedded/files/patch-binutils-gdb_include_diagnostics.h
@@ -0,0 +1,25 @@
+--- binutils-gdb/include/diagnostics.h.orig	2024-11-20 17:30:17 UTC
++++ binutils-gdb/include/diagnostics.h
+@@ -76,11 +76,6 @@
+ # define DIAGNOSTIC_ERROR_SWITCH \
+   DIAGNOSTIC_ERROR ("-Wswitch")
+ 
+-# if __has_warning ("-Wenum-constexpr-conversion")
+-#  define DIAGNOSTIC_IGNORE_ENUM_CONSTEXPR_CONVERSION \
+-   DIAGNOSTIC_IGNORE ("-Wenum-constexpr-conversion")
+-# endif
+-
+ #elif defined (__GNUC__) /* GCC */
+ 
+ # define DIAGNOSTIC_IGNORE_DEPRECATED_DECLARATIONS \
+@@ -157,10 +152,6 @@
+ 
+ #ifndef DIAGNOSTIC_ERROR_SWITCH
+ # define DIAGNOSTIC_ERROR_SWITCH
+-#endif
+-
+-#ifndef DIAGNOSTIC_IGNORE_ENUM_CONSTEXPR_CONVERSION
+-# define DIAGNOSTIC_IGNORE_ENUM_CONSTEXPR_CONVERSION
+ #endif
+ 
+ #endif /* DIAGNOSTICS_H */


home | help

Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69b35055.22cc6.74ea6c82>