Skip site navigation (1)Skip section navigation (2)



index | | raw e-mail

diff --git a/devel/gdb/files/patch-gdb-15-branchpoint-0753-gb050b744be4 b/devel/gdb/files/patch-gdb-15-branchpoint-0753-gb050b744be4
new file mode 100644
index 000000000000..e1b5e6b50c30
--- /dev/null
+++ b/devel/gdb/files/patch-gdb-15-branchpoint-0753-gb050b744be4
@@ -0,0 +1,94 @@
+commit b050b744be4c35cb6743e2e4d55935fdff56a01b
+Author: Simon Marchi <simon.marchi@efficios.com>
+Date:   2024-05-30T16:28:20-04:00
+
+    gdb, gdbsupport: use `using` in enum flags code
+    
+    I think that `using` is easier to read than `typedef`, and it's the
+    modern C++ thing anyway.
+    
+    Change-Id: Iccb62dc3869cddfb6a684ef3023dcd5b799f3ab2
+
+diff --git gdb/unittests/enum-flags-selftests.c gdb/unittests/enum-flags-selftests.c
+index b55d8c31406..154a473dd48 100644
+--- gdb/unittests/enum-flags-selftests.c
++++ gdb/unittests/enum-flags-selftests.c
+@@ -85,7 +85,7 @@ static EF ef ATTRIBUTE_UNUSED;
+ #define CHECK_VALID(VALID, EXPR_TYPE, EXPR)		\
+   CHECK_VALID_EXPR_6 (EF, RE, EF2, RE2, UEF, URE, VALID, EXPR_TYPE, EXPR)
+ 
+-typedef std::underlying_type<RE>::type und;
++using und = std::underlying_type<RE>::type;
+ 
+ /* Test construction / conversion from/to different types.  */
+ 
+@@ -253,7 +253,7 @@ CHECK_VALID (true,  int,  true ? RE2 () : EF ())
+ 
+ /* Same, but with an unsigned enum.  */
+ 
+-typedef unsigned int uns;
++using uns = unsigned int;
+ 
+ CHECK_VALID (true,  uns,  true ? EF () : UEF ())
+ CHECK_VALID (true,  uns,  true ? UEF () : EF ())
+diff --git gdbsupport/enum-flags.h gdbsupport/enum-flags.h
+index 56e0c524f00..764d5219663 100644
+--- gdbsupport/enum-flags.h
++++ gdbsupport/enum-flags.h
+@@ -55,7 +55,7 @@
+    enum_flags wrapper class for ENUM, and enables the global operator
+    overloads for ENUM.  */
+ #define DEF_ENUM_FLAGS_TYPE(enum_type, flags_type)	\
+-  typedef enum_flags<enum_type> flags_type;		\
++  using flags_type = enum_flags<enum_type>;		\
+   void is_enum_flags_enum_type (enum_type *)
+ 
+ /* To enable the global enum_flags operators for enum, declare an
+@@ -76,24 +76,24 @@
+ /* 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<int size, bool sign> class integer_for_size { using type = void; };
++template<> struct integer_for_size<1, 0> { using type = uint8_t; };
++template<> struct integer_for_size<2, 0> { using type = uint16_t; };
++template<> struct integer_for_size<4, 0> { using type = uint32_t; };
++template<> struct integer_for_size<8, 0> { using type = uint64_t; };
++template<> struct integer_for_size<1, 1> { using type = int8_t; };
++template<> struct integer_for_size<2, 1> { using type = int16_t; };
++template<> struct integer_for_size<4, 1> { using type = int32_t; };
++template<> struct integer_for_size<8, 1> { using type = int64_t; };
+ 
+ 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;
++  using type
++    = typename integer_for_size<sizeof (T),
++				static_cast<bool>(T (-1) < T (0))>::type;
+   DIAGNOSTIC_POP
+ };
+ 
+@@ -128,8 +128,8 @@ template <typename E>
+ class enum_flags
+ {
+ public:
+-  typedef E enum_type;
+-  typedef typename enum_underlying_type<enum_type>::type underlying_type;
++  using enum_type = E;
++  using underlying_type = typename enum_underlying_type<enum_type>::type;
+ 
+   /* For to_string.  Maps one enumerator of E to a string.  */
+   struct string_mapping
diff --git a/devel/gdb/files/patch-gdb-15-branchpoint-0754-gba96d2e697a b/devel/gdb/files/patch-gdb-15-branchpoint-0754-gba96d2e697a
new file mode 100644
index 000000000000..b06849eb6328
--- /dev/null
+++ b/devel/gdb/files/patch-gdb-15-branchpoint-0754-gba96d2e697a
@@ -0,0 +1,460 @@
+commit ba96d2e697a35517c5ee6b6c20a2fe9a055f7e5f
+Author: Simon Marchi <simon.marchi@efficios.com>
+Date:   2024-05-30T16:28:21-04:00
+
+    gdb: change names of enumerations in enum flags selftest
+    
+    When reading this test (in the context of PR 31331), I had trouble
+    understanding the tests, because of the abbreviated names.  I would
+    prefer if the names were a bit more explicit, like this.
+    
+    Change-Id: I85669b238a9d5dacf673a7bbfc1ca18f80d2b2cf
+
+diff --git gdb/unittests/enum-flags-selftests.c gdb/unittests/enum-flags-selftests.c
+index 154a473dd48..dddb1e26202 100644
+--- gdb/unittests/enum-flags-selftests.c
++++ gdb/unittests/enum-flags-selftests.c
+@@ -29,49 +29,49 @@ namespace enum_flags_tests {
+    make it simpler to use.  They could be named differently.  */
+ 
+ /* A "real enum".  */
+-enum RE
+-  {
+-    RE_FLAG1 = 1 << 1,
+-    RE_FLAG2 = 1 << 2,
+-  };
++enum RawEnum
++{
++  RawEnum_Flag1 = 1 << 1,
++  RawEnum_Flag2 = 1 << 2,
++};
+ 
+ /* Another "real enum".  */
+-enum RE2
+-  {
+-    RE2_FLAG1 = 1 << 1,
+-    RE2_FLAG2 = 1 << 2,
+-  };
++enum RawEnum2
++{
++  RawEnum2_Flag1 = 1 << 1,
++  RawEnum2_Flag2 = 1 << 2,
++};
+ 
+ /* An unsigned "real enum".  */
+-enum URE : unsigned
+-  {
+-    URE_FLAG1 = 1 << 1,
+-    URE_FLAG2 = 1 << 2,
+-    URE_FLAG3 = 0xffffffff,
+-  };
++enum UnsignedRawEnum : unsigned
++{
++  UnsignedRawEnum_Flag1 = 1 << 1,
++  UnsignedRawEnum_Flag2 = 1 << 2,
++  UnsignedRawEnum_Flag3 = 0xffffffff,
++};
+ 
+ /* A non-flags enum.  */
+-enum NF
+-  {
+-    NF_FLAG1 = 1 << 1,
+-    NF_FLAG2 = 1 << 2,
+-  };
++enum NonFlagsEnum
++{
++  NonFlagsEnum_Flag1 = 1 << 1,
++  NonFlagsEnum_Flag2 = 1 << 2,
++};
+ 
+ /* The corresponding "enum flags" types.  */
+-DEF_ENUM_FLAGS_TYPE (RE, EF);
+-DEF_ENUM_FLAGS_TYPE (RE2, EF2);
+-DEF_ENUM_FLAGS_TYPE (URE, UEF);
++DEF_ENUM_FLAGS_TYPE (RawEnum,         EnumFlag);
++DEF_ENUM_FLAGS_TYPE (RawEnum2,        EnumFlag2);
++DEF_ENUM_FLAGS_TYPE (UnsignedRawEnum, UnsignedEnumFlag);
+ 
+ /* So that std::vectors of types that have enum_flags fields can
+    reallocate efficiently memcpy.  */
+-static_assert (std::is_trivially_copyable<EF>::value);
++static_assert (std::is_trivially_copyable<EnumFlag>::value);
+ 
+ /* A couple globals used as lvalues in the CHECK_VALID expressions
+    below.  Their names (and types) match the uppercase type names
+    exposed by CHECK_VALID just to make the expressions easier to
+    follow.  */
+-static RE re ATTRIBUTE_UNUSED;
+-static EF ef ATTRIBUTE_UNUSED;
++static RawEnum re ATTRIBUTE_UNUSED;
++static EnumFlag ef ATTRIBUTE_UNUSED;
+ 
+ /* First, compile-time tests that:
+ 
+@@ -82,30 +82,32 @@ static EF ef ATTRIBUTE_UNUSED;
+      types do compile and that they return the correct type.
+ */
+ 
+-#define CHECK_VALID(VALID, EXPR_TYPE, EXPR)		\
+-  CHECK_VALID_EXPR_6 (EF, RE, EF2, RE2, UEF, URE, VALID, EXPR_TYPE, EXPR)
++#define CHECK_VALID(VALID, EXPR_TYPE, EXPR)                                \
++  CHECK_VALID_EXPR_6 (EnumFlag, RawEnum, EnumFlag2, RawEnum2,              \
++		      UnsignedEnumFlag, UnsignedRawEnum, VALID, EXPR_TYPE, \
++		      EXPR)
+ 
+-using und = std::underlying_type<RE>::type;
++using und = std::underlying_type<RawEnum>::type;
+ 
+ /* Test construction / conversion from/to different types.  */
+ 
+ /* RE/EF -> underlying (explicit) */
+-CHECK_VALID (true,  und,  und (RE ()))
+-CHECK_VALID (true,  und,  und (EF ()))
++CHECK_VALID (true, und, und (RawEnum ()))
++CHECK_VALID (true, und, und (EnumFlag ()))
+ 
+ /* RE/EF -> int (explicit) */
+-CHECK_VALID (true,  int,  int (RE ()))
+-CHECK_VALID (true,  int,  int (EF ()))
++CHECK_VALID (true, int, int (RawEnum ()))
++CHECK_VALID (true, int, int (EnumFlag ()))
+ 
+ /* other -> RE */
+ 
+ /* You can construct a raw enum value from an int explicitly to punch
+    a hole in the type system if need to.  */
+-CHECK_VALID (true,  RE,   RE (1))
+-CHECK_VALID (true,  RE,   RE (RE2 ()))
+-CHECK_VALID (false, void, RE (EF2 ()))
+-CHECK_VALID (true,  RE,   RE (RE ()))
+-CHECK_VALID (false, void, RE (EF ()))
++CHECK_VALID (true,  RawEnum, RawEnum (1))
++CHECK_VALID (true,  RawEnum, RawEnum (RawEnum2 ()))
++CHECK_VALID (false, void,    RawEnum (EnumFlag2 ()))
++CHECK_VALID (true,  RawEnum, RawEnum (RawEnum ()))
++CHECK_VALID (false, void,    RawEnum (EnumFlag ()))
+ 
+ /* other -> EF.  */
+ 
+@@ -113,125 +115,125 @@ CHECK_VALID (false, void, RE (EF ()))
+    enum.  Unlike with raw enums, you can't construct an enum flags
+    from an integer nor from an unrelated enum type explicitly.  Add an
+    intermediate conversion via the raw enum if you really need it.  */
+-CHECK_VALID (false, void, EF (1))
+-CHECK_VALID (false, void, EF (1u))
+-CHECK_VALID (false, void, EF (RE2 ()))
+-CHECK_VALID (false, void, EF (EF2 ()))
+-CHECK_VALID (true,  EF,   EF (RE ()))
+-CHECK_VALID (true,  EF,   EF (EF ()))
++CHECK_VALID (false, void,     EnumFlag (1))
++CHECK_VALID (false, void,     EnumFlag (1u))
++CHECK_VALID (false, void,     EnumFlag (RawEnum2 ()))
++CHECK_VALID (false, void,     EnumFlag (EnumFlag2 ()))
++CHECK_VALID (true,  EnumFlag, EnumFlag (RawEnum ()))
++CHECK_VALID (true,  EnumFlag, EnumFlag (EnumFlag ()))
+ 
+ /* Test operators.  */
+ 
+ /* operator OP (raw_enum, int) */
+ 
+-CHECK_VALID (false, void, RE () | 1)
+-CHECK_VALID (false, void, RE () & 1)
+-CHECK_VALID (false, void, RE () ^ 1)
++CHECK_VALID (false, void, RawEnum () | 1)
++CHECK_VALID (false, void, RawEnum () & 1)
++CHECK_VALID (false, void, RawEnum () ^ 1)
+ 
+ /* operator OP (int, raw_enum) */
+ 
+-CHECK_VALID (false, void, 1 | RE ())
+-CHECK_VALID (false, void, 1 & RE ())
+-CHECK_VALID (false, void, 1 ^ RE ())
++CHECK_VALID (false, void, 1 | RawEnum ())
++CHECK_VALID (false, void, 1 & RawEnum ())
++CHECK_VALID (false, void, 1 ^ RawEnum ())
+ 
+ /* operator OP (enum_flags, int) */
+ 
+-CHECK_VALID (false, void, EF () | 1)
+-CHECK_VALID (false, void, EF () & 1)
+-CHECK_VALID (false, void, EF () ^ 1)
++CHECK_VALID (false, void, EnumFlag () | 1)
++CHECK_VALID (false, void, EnumFlag () & 1)
++CHECK_VALID (false, void, EnumFlag () ^ 1)
+ 
+ /* operator OP (int, enum_flags) */
+ 
+-CHECK_VALID (false, void, 1 | EF ())
+-CHECK_VALID (false, void, 1 & EF ())
+-CHECK_VALID (false, void, 1 ^ EF ())
++CHECK_VALID (false, void, 1 | EnumFlag ())
++CHECK_VALID (false, void, 1 & EnumFlag ())
++CHECK_VALID (false, void, 1 ^ EnumFlag ())
+ 
+ /* operator OP (raw_enum, raw_enum) */
+ 
+-CHECK_VALID (false, void, RE () | RE2 ())
+-CHECK_VALID (false, void, RE () & RE2 ())
+-CHECK_VALID (false, void, RE () ^ RE2 ())
+-CHECK_VALID (true,  RE,   RE () | RE ())
+-CHECK_VALID (true,  RE,   RE () & RE ())
+-CHECK_VALID (true,  RE,   RE () ^ RE ())
++CHECK_VALID (false, void,    RawEnum () | RawEnum2 ())
++CHECK_VALID (false, void,    RawEnum () & RawEnum2 ())
++CHECK_VALID (false, void,    RawEnum () ^ RawEnum2 ())
++CHECK_VALID (true,  RawEnum, RawEnum () | RawEnum ())
++CHECK_VALID (true,  RawEnum, RawEnum () & RawEnum ())
++CHECK_VALID (true,  RawEnum, RawEnum () ^ RawEnum ())
+ 
+ /* operator OP (enum_flags, raw_enum) */
+ 
+-CHECK_VALID (false, void, EF () | RE2 ())
+-CHECK_VALID (false, void, EF () & RE2 ())
+-CHECK_VALID (false, void, EF () ^ RE2 ())
+-CHECK_VALID (true,  EF,   EF () | RE ())
+-CHECK_VALID (true,  EF,   EF () & RE ())
+-CHECK_VALID (true,  EF,   EF () ^ RE ())
++CHECK_VALID (false, void,     EnumFlag () | RawEnum2 ())
++CHECK_VALID (false, void,     EnumFlag () & RawEnum2 ())
++CHECK_VALID (false, void,     EnumFlag () ^ RawEnum2 ())
++CHECK_VALID (true,  EnumFlag, EnumFlag () | RawEnum ())
++CHECK_VALID (true,  EnumFlag, EnumFlag () & RawEnum ())
++CHECK_VALID (true,  EnumFlag, EnumFlag () ^ RawEnum ())
+ 
+ /* operator OP= (raw_enum, raw_enum), rvalue ref on the lhs. */
+ 
+-CHECK_VALID (false, void, RE () |= RE2 ())
+-CHECK_VALID (false, void, RE () &= RE2 ())
+-CHECK_VALID (false, void, RE () ^= RE2 ())
+-CHECK_VALID (false, void, RE () |= RE ())
+-CHECK_VALID (false, void, RE () &= RE ())
+-CHECK_VALID (false, void, RE () ^= RE ())
++CHECK_VALID (false, void, RawEnum () |= RawEnum2 ())
++CHECK_VALID (false, void, RawEnum () &= RawEnum2 ())
++CHECK_VALID (false, void, RawEnum () ^= RawEnum2 ())
++CHECK_VALID (false, void, RawEnum () |= RawEnum ())
++CHECK_VALID (false, void, RawEnum () &= RawEnum ())
++CHECK_VALID (false, void, RawEnum () ^= RawEnum ())
+ 
+ /* operator OP= (raw_enum, raw_enum), lvalue ref on the lhs. */
+ 
+-CHECK_VALID (false, void, re |= RE2 ())
+-CHECK_VALID (false, void, re &= RE2 ())
+-CHECK_VALID (false, void, re ^= RE2 ())
+-CHECK_VALID (true,  RE&,  re |= RE ())
+-CHECK_VALID (true,  RE&,  re &= RE ())
+-CHECK_VALID (true,  RE&,  re ^= RE ())
++CHECK_VALID (false, void,     re |= RawEnum2 ())
++CHECK_VALID (false, void,     re &= RawEnum2 ())
++CHECK_VALID (false, void,     re ^= RawEnum2 ())
++CHECK_VALID (true,  RawEnum&, re |= RawEnum ())
++CHECK_VALID (true,  RawEnum&, re &= RawEnum ())
++CHECK_VALID (true,  RawEnum&, re ^= RawEnum ())
+ 
+ /* operator OP= (enum_flags, raw_enum), rvalue ref on the lhs.  */
+ 
+-CHECK_VALID (false, void, EF () |= RE2 ())
+-CHECK_VALID (false, void, EF () &= RE2 ())
+-CHECK_VALID (false, void, EF () ^= RE2 ())
+-CHECK_VALID (false, void, EF () |= RE ())
+-CHECK_VALID (false, void, EF () &= RE ())
+-CHECK_VALID (false, void, EF () ^= RE ())
++CHECK_VALID (false, void, EnumFlag () |= RawEnum2 ())
++CHECK_VALID (false, void, EnumFlag () &= RawEnum2 ())
++CHECK_VALID (false, void, EnumFlag () ^= RawEnum2 ())
++CHECK_VALID (false, void, EnumFlag () |= RawEnum ())
++CHECK_VALID (false, void, EnumFlag () &= RawEnum ())
++CHECK_VALID (false, void, EnumFlag () ^= RawEnum ())
+ 
+ /* operator OP= (enum_flags, raw_enum), lvalue ref on the lhs.  */
+ 
+-CHECK_VALID (false, void, ef |= RE2 ())
+-CHECK_VALID (false, void, ef &= RE2 ())
+-CHECK_VALID (false, void, ef ^= RE2 ())
+-CHECK_VALID (true,  EF&,  ef |= EF ())
+-CHECK_VALID (true,  EF&,  ef &= EF ())
+-CHECK_VALID (true,  EF&,  ef ^= EF ())
++CHECK_VALID (false, void,      ef |= RawEnum2 ())
++CHECK_VALID (false, void,      ef &= RawEnum2 ())
++CHECK_VALID (false, void,      ef ^= RawEnum2 ())
++CHECK_VALID (true,  EnumFlag&, ef |= EnumFlag ())
++CHECK_VALID (true,  EnumFlag&, ef &= EnumFlag ())
++CHECK_VALID (true,  EnumFlag&, ef ^= EnumFlag ())
+ 
+ /* operator OP= (enum_flags, enum_flags), rvalue ref on the lhs.  */
+ 
+-CHECK_VALID (false, void, EF () |= EF2 ())
+-CHECK_VALID (false, void, EF () &= EF2 ())
+-CHECK_VALID (false, void, EF () ^= EF2 ())
+-CHECK_VALID (false, void, EF () |= EF ())
+-CHECK_VALID (false, void, EF () &= EF ())
+-CHECK_VALID (false, void, EF () ^= EF ())
++CHECK_VALID (false, void, EnumFlag () |= EnumFlag2 ())
++CHECK_VALID (false, void, EnumFlag () &= EnumFlag2 ())
++CHECK_VALID (false, void, EnumFlag () ^= EnumFlag2 ())
++CHECK_VALID (false, void, EnumFlag () |= EnumFlag ())
++CHECK_VALID (false, void, EnumFlag () &= EnumFlag ())
++CHECK_VALID (false, void, EnumFlag () ^= EnumFlag ())
+ 
+ /* operator OP= (enum_flags, enum_flags), lvalue ref on the lhs.  */
+ 
+-CHECK_VALID (false, void, ef |= EF2 ())
+-CHECK_VALID (false, void, ef &= EF2 ())
+-CHECK_VALID (false, void, ef ^= EF2 ())
+-CHECK_VALID (true,  EF&,  ef |= EF ())
+-CHECK_VALID (true,  EF&,  ef &= EF ())
+-CHECK_VALID (true,  EF&,  ef ^= EF ())
++CHECK_VALID (false, void, ef |= EnumFlag2 ())
++CHECK_VALID (false, void, ef &= EnumFlag2 ())
++CHECK_VALID (false, void, ef ^= EnumFlag2 ())
++CHECK_VALID (true,  EnumFlag&,  ef |= EnumFlag ())
++CHECK_VALID (true,  EnumFlag&,  ef &= EnumFlag ())
++CHECK_VALID (true,  EnumFlag&,  ef ^= EnumFlag ())
+ 
+ /* operator~ (raw_enum) */
+ 
+-CHECK_VALID (false,  void,   ~RE ())
+-CHECK_VALID (true,   URE,    ~URE ())
++CHECK_VALID (false, void,            ~RawEnum ())
++CHECK_VALID (true,  UnsignedRawEnum, ~UnsignedRawEnum ())
+ 
+ /* operator~ (enum_flags) */
+ 
+-CHECK_VALID (false,  void,   ~EF ())
+-CHECK_VALID (true,   UEF,    ~UEF ())
++CHECK_VALID (false, void,             ~EnumFlag ())
++CHECK_VALID (true,  UnsignedEnumFlag, ~UnsignedEnumFlag ())
+ 
+ /* Check ternary operator.  This exercises implicit conversions.  */
+ 
+-CHECK_VALID (true,  EF,   true ? EF () : RE ())
+-CHECK_VALID (true,  EF,   true ? RE () : EF ())
++CHECK_VALID (true, EnumFlag, true ? EnumFlag () : RawEnum ())
++CHECK_VALID (true, EnumFlag, true ? RawEnum ()  : EnumFlag ())
+ 
+ /* 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
+@@ -246,19 +248,19 @@ CHECK_VALID (true,  EF,   true ? RE () : EF ())
+    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 ())
++CHECK_VALID (true, int, true ? EnumFlag ()  : EnumFlag2 ())
++CHECK_VALID (true, int, true ? EnumFlag2 () : EnumFlag ())
++CHECK_VALID (true, int, true ? EnumFlag ()  : RawEnum2 ())
++CHECK_VALID (true, int, true ? RawEnum2 ()  : EnumFlag ())
+ 
+ /* Same, but with an unsigned enum.  */
+ 
+ using uns = unsigned int;
+ 
+-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 ())
++CHECK_VALID (true, uns, true ? EnumFlag ()         : UnsignedEnumFlag ())
++CHECK_VALID (true, uns, true ? UnsignedEnumFlag () : EnumFlag ())
++CHECK_VALID (true, uns, true ? EnumFlag ()         : UnsignedRawEnum ())
++CHECK_VALID (true, uns, true ? UnsignedRawEnum ()  : EnumFlag ())
+ 
+ /* Unfortunately this can't work due to the way C++ computes the
+    return type of the ternary conditional operator.  int isn't
+@@ -270,39 +272,39 @@ CHECK_VALID (true,  uns,  true ? URE () : EF ())
+      error: operands to ?: have different types ‘enum_flags<RE>’ and ‘int’
+    Confirmed to work with gcc 4.9, 5.3 and clang 3.7.
+ */
+-CHECK_VALID (false, void, true ? EF () : 0)
+-CHECK_VALID (false, void, true ? 0 : EF ())
++CHECK_VALID (false, void, true ? EnumFlag () : 0)
++CHECK_VALID (false, void, true ? 0           : EnumFlag ())
+ 
+ /* Check that the ++/--/<</>>/<<=/>>= operators are deleted.  */
+ 
+-CHECK_VALID (false, void, RE ()++)
+-CHECK_VALID (false, void, ++RE ())
+-CHECK_VALID (false, void, --RE ())
+-CHECK_VALID (false, void, RE ()--)
++CHECK_VALID (false, void, RawEnum ()++)
++CHECK_VALID (false, void, ++RawEnum ())
++CHECK_VALID (false, void, --RawEnum ())
++CHECK_VALID (false, void, RawEnum ()--)
+ 
+-CHECK_VALID (false, void, RE () << 1)
+-CHECK_VALID (false, void, RE () >> 1)
+-CHECK_VALID (false, void, EF () << 1)
+-CHECK_VALID (false, void, EF () >> 1)
++CHECK_VALID (false, void, RawEnum () << 1)
++CHECK_VALID (false, void, RawEnum () >> 1)
++CHECK_VALID (false, void, EnumFlag () << 1)
++CHECK_VALID (false, void, EnumFlag () >> 1)
+ 
+-CHECK_VALID (false, void, RE () <<= 1)
+-CHECK_VALID (false, void, RE () >>= 1)
+-CHECK_VALID (false, void, EF () <<= 1)
+-CHECK_VALID (false, void, EF () >>= 1)
++CHECK_VALID (false, void, RawEnum () <<= 1)
++CHECK_VALID (false, void, RawEnum () >>= 1)
++CHECK_VALID (false, void, EnumFlag () <<= 1)
++CHECK_VALID (false, void, EnumFlag () >>= 1)
+ 
+ /* Test comparison operators.  */
+ 
+-CHECK_VALID (false, void, EF () == EF2 ())
+-CHECK_VALID (false, void, EF () == RE2 ())
+-CHECK_VALID (false, void, RE () == EF2 ())
++CHECK_VALID (false, void, EnumFlag () == EnumFlag2 ())
++CHECK_VALID (false, void, EnumFlag () == RawEnum2 ())
++CHECK_VALID (false, void, RawEnum ()  == EnumFlag2 ())
+ 
+-CHECK_VALID (true,  bool, EF (RE (1)) == EF (RE (1)))
+-CHECK_VALID (true,  bool, EF (RE (1)) == RE (1))
+-CHECK_VALID (true,  bool, RE (1)      == EF (RE (1)))
++CHECK_VALID (true,  bool, EnumFlag (RawEnum (1)) == EnumFlag (RawEnum (1)))
++CHECK_VALID (true,  bool, EnumFlag (RawEnum (1)) == RawEnum (1))
++CHECK_VALID (true,  bool, RawEnum (1)            == EnumFlag (RawEnum (1)))
+ 
+-CHECK_VALID (false, void, EF () != EF2 ())
+-CHECK_VALID (false, void, EF () != RE2 ())
+-CHECK_VALID (false, void, RE () != EF2 ())
++CHECK_VALID (false, void, EnumFlag () != EnumFlag2 ())
++CHECK_VALID (false, void, EnumFlag () != RawEnum2 ())
++CHECK_VALID (false, void, RawEnum ()  != EnumFlag2 ())
+ 
+ /* Disable -Wenum-compare due to:
+ 
+@@ -323,23 +325,23 @@ CHECK_VALID (false, void, RE () != EF2 ())
+ # pragma GCC diagnostic push
+ # pragma GCC diagnostic ignored "-Wenum-compare"
+ #endif
+-CHECK_VALID (true,  bool, RE () == RE2 ())
+-CHECK_VALID (true,  bool, RE () != RE2 ())
++CHECK_VALID (true,  bool, RawEnum () == RawEnum2 ())
++CHECK_VALID (true,  bool, RawEnum () != RawEnum2 ())
+ #if defined __GNUC__
+ # pragma GCC diagnostic pop
+ #endif
+ 
+-CHECK_VALID (true,  bool, EF (RE (1)) != EF (RE (2)))
+-CHECK_VALID (true,  bool, EF (RE (1)) != RE (2))
+-CHECK_VALID (true,  bool, RE (1)      != EF (RE (2)))
++CHECK_VALID (true,  bool, EnumFlag (RawEnum (1)) != EnumFlag (RawEnum (2)))
++CHECK_VALID (true,  bool, EnumFlag (RawEnum (1)) != RawEnum (2))
++CHECK_VALID (true,  bool, RawEnum (1)            != EnumFlag (RawEnum (2)))
+ 
+-CHECK_VALID (true,  bool, EF () == 0)
++CHECK_VALID (true,  bool, EnumFlag () == 0)
+ 
+ /* Check we didn't disable/delete comparison between non-flags enums
+    and unrelated types by mistake.  */
+-CHECK_VALID (true,  bool, NF (1) == NF (1))
+-CHECK_VALID (true,  bool, NF (1) == int (1))
+-CHECK_VALID (true,  bool, NF (1) == char (1))
++CHECK_VALID (true,  bool, NonFlagsEnum (1) == NonFlagsEnum (1))
++CHECK_VALID (true,  bool, NonFlagsEnum (1) == int (1))
++CHECK_VALID (true,  bool, NonFlagsEnum (1) == char (1))
+ 
+ /* -------------------------------------------------------------------- */
+ 
diff --git a/devel/gdb/files/patch-gdb-15-branchpoint-1903-g4a0b2cb7210 b/devel/gdb/files/patch-gdb-15-branchpoint-1903-g4a0b2cb7210
new file mode 100644
index 000000000000..003c8d5dec33
--- /dev/null
+++ b/devel/gdb/files/patch-gdb-15-branchpoint-1903-g4a0b2cb7210
@@ -0,0 +1,317 @@
+commit 4a0b2cb7210c65c8c9f4a56345749bb7294fbfbf
+Author: Carlos Galvez <carlosgalvezp@gmail.com>
+Date:   2024-12-21T22:25:40+01:00
+
+    Fix -Wenum-constexpr-conversion in enum-flags.h
+    
+    This fixes PR 31331:
+    https://sourceware.org/bugzilla/show_bug.cgi?id=31331
+    
+    Currently, enum-flags.h is suppressing the warning
+    -Wenum-constexpr-conversion coming from recent versions of Clang.
+    This warning is intended to be made a compiler error
+    (non-downgradeable) in future versions of Clang:
+    
+    https://github.com/llvm/llvm-project/issues/59036
+    
+    The rationale is that casting a value of an integral type into an
+    enumeration is Undefined Behavior if the value does not fit in the
+    range of values of the enum:
+    https://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1766
+    
+    Undefined Behavior is not allowed in constant expressions, leading to
+    an ill-formed program.
+    
+    In this case, in enum-flags.h, we are casting the value -1 to an enum
+    of a positive range only, which is UB as per the Standard and thus not
+    allowed in a constexpr context.
+    
+    The purpose of doing this instead of using std::underlying_type is
+    because, for C-style enums, std::underlying_type typically returns
+    "unsigned int". However, when operating with it arithmetically, the
+    enum is promoted to *signed* int, which is what we want to avoid.
+    
+    This patch solves this issue as follows:
+    
+    * Use std::underlying_type and remove the custom enum_underlying_type.
+    
+    * Ensure that operator~ is called always on an unsigned integer. We do
+      this by casting the input enum into std::size_t, which can fit any
+      unsigned integer. We have the guarantee that the cast is safe,
+      because we have checked that the underlying type is unsigned. If the
+      enum had negative values, the underlying type would be signed.
+    
+      This solves the issue with C-style enums, but also solves a hidden
+      issue: enums with underlying type of std::uint8_t or std::uint16_t are
+      *also* promoted to signed int. Now they are all explicitly casted
+      to the largest unsigned int type and operator~ is safe to use.
+    
+    * There is one more thing that needs fix. Currently, operator~ is
+      implemented as follows:
+    
+      return (enum_type) ~underlying(e);
+    
+      After applying ~underlying(e), the result is a very large value,
+      which we then cast to "enum_type". This cast is Undefined Behavior
+      if the large value does not fit in the range of the enum. For
+      C++ enums (scoped and/or with explicit underlying type), the range
+      of the enum is the entire range of the underlying type, so the cast
+      is safe. However, for C-style enums, the range is the smallest
+      bit-field that can hold all the values of the enumeration. So the
+      range is a lot smaller and casting a large value to the enum would
+      invoke Undefined Behavior.
+    
+      To solve this problem, we create a new trait
+      EnumHasFixedUnderlyingType, to ensure operator~ may only be called
+      on C++-style enums. This behavior is roughly the same as what we
+      had on trunk, but relying on different properties of the enums.
+    
+    * Once this is implemented, the following tests fail to compile:
+    
+      CHECK_VALID (true,  int,  true ? EF () : EF2 ())
+    
+      This is because it expects the enums to be promoted to signed int,
+      instead of unsigned int (which is the true underlying type).
+    
+      I propose to remove these tests altogether, because:
+    
+      - The comment nearby say they are not very important.
+      - Comparing 2 enums of different type like that is strange, relies
+        on integer promotions and thus hurts readability. As per comments
+        in the related PR, we likely don't want this type of code in gdb
+        code anyway, so there's no point in testing it.
+      - Most importantly, this type of comparison will be ill-formed in
+        C++26 for regular enums, so enum_flags does not need to emulate
+        that.
+    
+    Since this is the only place where the warning was suppressed, remove
+    also the corresponding macro in include/diagnostics.h.
+    
+    The change has been tested by running the entire gdb test suite
+    (make check) and comparing the results (testsuite/gdb.sum) against
+    trunk. No noticeable differences have been observed.
+    
+    Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31331
+    Tested-by: Keith Seitz <keiths@redhat.com>
+    Approved-By: Tom Tromey <tom@tromey.com>
+
+diff --git gdb/unittests/enum-flags-selftests.c gdb/unittests/enum-flags-selftests.c
+index dddb1e26202..f192da37b41 100644
+--- gdb/unittests/enum-flags-selftests.c
++++ gdb/unittests/enum-flags-selftests.c
+@@ -235,33 +235,6 @@ CHECK_VALID (true,  UnsignedEnumFlag, ~UnsignedEnumFlag ())
+ CHECK_VALID (true, EnumFlag, true ? EnumFlag () : RawEnum ())
+ CHECK_VALID (true, EnumFlag, true ? RawEnum ()  : EnumFlag ())
+ 
+-/* 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 ? EnumFlag ()  : EnumFlag2 ())
+-CHECK_VALID (true, int, true ? EnumFlag2 () : EnumFlag ())
+-CHECK_VALID (true, int, true ? EnumFlag ()  : RawEnum2 ())
+-CHECK_VALID (true, int, true ? RawEnum2 ()  : EnumFlag ())
+-
+-/* Same, but with an unsigned enum.  */
+-
+-using uns = unsigned int;
+-
+-CHECK_VALID (true, uns, true ? EnumFlag ()         : UnsignedEnumFlag ())
+-CHECK_VALID (true, uns, true ? UnsignedEnumFlag () : EnumFlag ())
+-CHECK_VALID (true, uns, true ? EnumFlag ()         : UnsignedRawEnum ())
+-CHECK_VALID (true, uns, true ? UnsignedRawEnum ()  : EnumFlag ())
+-
+ /* 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 gdbsupport/enum-flags.h gdbsupport/enum-flags.h
+index d3291e95d7e..71109bb8c99 100644
+--- gdbsupport/enum-flags.h
++++ gdbsupport/enum-flags.h
+@@ -73,30 +73,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 { using type = void; };
+-template<> struct integer_for_size<1, 0> { using type = uint8_t; };
+-template<> struct integer_for_size<2, 0> { using type = uint16_t; };
+-template<> struct integer_for_size<4, 0> { using type = uint32_t; };
+-template<> struct integer_for_size<8, 0> { using type = uint64_t; };
+-template<> struct integer_for_size<1, 1> { using type = int8_t; };
+-template<> struct integer_for_size<2, 1> { using type = int16_t; };
+-template<> struct integer_for_size<4, 1> { using type = int32_t; };
+-template<> struct integer_for_size<8, 1> { using type = int64_t; };
+-
+-template<typename T>
+-struct enum_underlying_type
+-{
+-  DIAGNOSTIC_PUSH
+-  DIAGNOSTIC_IGNORE_ENUM_CONSTEXPR_CONVERSION
+-  using type
+-    = typename integer_for_size<sizeof (T),
+-				static_cast<bool>(T (-1) < T (0))>::type;
+-  DIAGNOSTIC_POP
+-};
+-
+ namespace enum_flags_detail
+ {
+ 
+@@ -117,10 +93,61 @@ struct zero_type;
+ /* 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>>;
+ 
+ }
+ 
+@@ -129,7 +156,7 @@ class enum_flags
+ {
+ public:
+   using enum_type = E;
+-  using underlying_type = typename enum_underlying_type<enum_type>::type;
++  using underlying_type = typename std::underlying_type<enum_type>::type;
+ 
+   /* For to_string.  Maps one enumerator of E to a string.  */
+   struct string_mapping
+@@ -392,33 +419,41 @@ ENUM_FLAGS_GEN_COMP (operator!=, !=)
+ 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 include/diagnostics.h include/diagnostics.h
+index 97e30ab807f..2a1d9b92fad 100644
+--- include/diagnostics.h
++++ 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 \
+@@ -159,8 +154,4 @@
+ # define DIAGNOSTIC_ERROR_SWITCH
+ #endif
+ 
+-#ifndef DIAGNOSTIC_IGNORE_ENUM_CONSTEXPR_CONVERSION
+-# define DIAGNOSTIC_IGNORE_ENUM_CONSTEXPR_CONVERSION
+-#endif
+-
+ #endif /* DIAGNOSTICS_H */


home | help