Home | History | Annotate | Line # | Download | only in gdbsupport
      1  1.1.1.3  christos /* Copyright (C) 2015-2024 Free Software Foundation, Inc.
      2      1.1  christos 
      3      1.1  christos    This file is part of GDB.
      4      1.1  christos 
      5      1.1  christos    This program is free software; you can redistribute it and/or modify
      6      1.1  christos    it under the terms of the GNU General Public License as published by
      7      1.1  christos    the Free Software Foundation; either version 3 of the License, or
      8      1.1  christos    (at your option) any later version.
      9      1.1  christos 
     10      1.1  christos    This program is distributed in the hope that it will be useful,
     11      1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     12      1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13      1.1  christos    GNU General Public License for more details.
     14      1.1  christos 
     15      1.1  christos    You should have received a copy of the GNU General Public License
     16      1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     17      1.1  christos 
     18      1.1  christos #ifndef COMMON_ENUM_FLAGS_H
     19      1.1  christos #define COMMON_ENUM_FLAGS_H
     20      1.1  christos 
     21  1.1.1.2  christos #include "traits.h"
     22  1.1.1.2  christos 
     23      1.1  christos /* Type-safe wrapper for enum flags.  enum flags are enums where the
     24      1.1  christos    values are bits that are meant to be ORed together.
     25      1.1  christos 
     26      1.1  christos    This allows writing code like the below, while with raw enums this
     27      1.1  christos    would fail to compile without casts to enum type at the assignments
     28      1.1  christos    to 'f':
     29      1.1  christos 
     30      1.1  christos     enum some_flag
     31      1.1  christos     {
     32      1.1  christos        flag_val1 = 1 << 1,
     33      1.1  christos        flag_val2 = 1 << 2,
     34      1.1  christos        flag_val3 = 1 << 3,
     35      1.1  christos        flag_val4 = 1 << 4,
     36      1.1  christos     };
     37      1.1  christos     DEF_ENUM_FLAGS_TYPE(enum some_flag, some_flags);
     38      1.1  christos 
     39      1.1  christos     some_flags f = flag_val1 | flag_val2;
     40      1.1  christos     f |= flag_val3;
     41      1.1  christos 
     42      1.1  christos    It's also possible to assign literal zero to an enum flags variable
     43      1.1  christos    (meaning, no flags), dispensing adding an awkward explicit "no
     44      1.1  christos    value" value to the enumeration.  For example:
     45      1.1  christos 
     46      1.1  christos     some_flags f = 0;
     47      1.1  christos     f |= flag_val3 | flag_val4;
     48      1.1  christos 
     49      1.1  christos    Note that literal integers other than zero fail to compile:
     50      1.1  christos 
     51      1.1  christos     some_flags f = 1; // error
     52      1.1  christos */
     53      1.1  christos 
     54      1.1  christos #ifdef __cplusplus
     55      1.1  christos 
     56  1.1.1.2  christos /* Use this to mark an enum as flags enum.  It defines FLAGS_TYPE as
     57      1.1  christos    enum_flags wrapper class for ENUM, and enables the global operator
     58      1.1  christos    overloads for ENUM.  */
     59      1.1  christos #define DEF_ENUM_FLAGS_TYPE(enum_type, flags_type)	\
     60      1.1  christos   typedef enum_flags<enum_type> flags_type;		\
     61  1.1.1.2  christos   void is_enum_flags_enum_type (enum_type *)
     62      1.1  christos 
     63  1.1.1.2  christos /* To enable the global enum_flags operators for enum, declare an
     64  1.1.1.2  christos    "is_enum_flags_enum_type" overload that has exactly one parameter,
     65  1.1.1.2  christos    of type a pointer to that enum class.  E.g.,:
     66  1.1.1.2  christos 
     67  1.1.1.2  christos      void is_enum_flags_enum_type (enum some_flag *);
     68  1.1.1.2  christos 
     69  1.1.1.2  christos    The function does not need to be defined, only declared.
     70  1.1.1.2  christos    DEF_ENUM_FLAGS_TYPE declares this.
     71  1.1.1.2  christos 
     72  1.1.1.2  christos    A function declaration is preferred over a traits type, because the
     73  1.1.1.2  christos    former allows calling the DEF_ENUM_FLAGS_TYPE macro inside a
     74  1.1.1.2  christos    namespace to define the corresponding enum flags type in that
     75  1.1.1.2  christos    namespace.  The compiler finds the corresponding
     76  1.1.1.2  christos    is_enum_flags_enum_type function via ADL.  */
     77  1.1.1.2  christos 
     78  1.1.1.2  christos /* Note that std::underlying_type<enum_type> is not what we want here,
     79  1.1.1.2  christos    since that returns unsigned int even when the enum decays to signed
     80  1.1.1.2  christos    int.  */
     81      1.1  christos template<int size, bool sign> class integer_for_size { typedef void type; };
     82      1.1  christos template<> struct integer_for_size<1, 0> { typedef uint8_t type; };
     83      1.1  christos template<> struct integer_for_size<2, 0> { typedef uint16_t type; };
     84      1.1  christos template<> struct integer_for_size<4, 0> { typedef uint32_t type; };
     85      1.1  christos template<> struct integer_for_size<8, 0> { typedef uint64_t type; };
     86      1.1  christos template<> struct integer_for_size<1, 1> { typedef int8_t type; };
     87      1.1  christos template<> struct integer_for_size<2, 1> { typedef int16_t type; };
     88      1.1  christos template<> struct integer_for_size<4, 1> { typedef int32_t type; };
     89      1.1  christos template<> struct integer_for_size<8, 1> { typedef int64_t type; };
     90      1.1  christos 
     91      1.1  christos template<typename T>
     92      1.1  christos struct enum_underlying_type
     93      1.1  christos {
     94  1.1.1.2  christos   DIAGNOSTIC_PUSH
     95  1.1.1.2  christos   DIAGNOSTIC_IGNORE_ENUM_CONSTEXPR_CONVERSION
     96      1.1  christos   typedef typename
     97      1.1  christos     integer_for_size<sizeof (T), static_cast<bool>(T (-1) < T (0))>::type
     98      1.1  christos     type;
     99  1.1.1.2  christos   DIAGNOSTIC_POP
    100      1.1  christos };
    101      1.1  christos 
    102  1.1.1.2  christos namespace enum_flags_detail
    103      1.1  christos {
    104      1.1  christos 
    105  1.1.1.2  christos /* Private type used to support initializing flag types with zero:
    106      1.1  christos 
    107  1.1.1.2  christos    foo_flags f = 0;
    108      1.1  christos 
    109  1.1.1.2  christos    but not other integers:
    110      1.1  christos 
    111  1.1.1.2  christos    foo_flags f = 1;
    112      1.1  christos 
    113  1.1.1.2  christos    The way this works is that we define an implicit constructor that
    114  1.1.1.2  christos    takes a pointer to this private type.  Since nothing can
    115  1.1.1.2  christos    instantiate an object of this type, the only possible pointer to
    116  1.1.1.2  christos    pass to the constructor is the NULL pointer, or, zero.  */
    117  1.1.1.2  christos struct zero_type;
    118      1.1  christos 
    119  1.1.1.2  christos /* gdb::Requires trait helpers.  */
    120  1.1.1.2  christos template <typename enum_type>
    121  1.1.1.2  christos using EnumIsUnsigned
    122  1.1.1.2  christos   = std::is_unsigned<typename enum_underlying_type<enum_type>::type>;
    123  1.1.1.2  christos template <typename enum_type>
    124  1.1.1.2  christos using EnumIsSigned
    125  1.1.1.2  christos   = std::is_signed<typename enum_underlying_type<enum_type>::type>;
    126  1.1.1.2  christos 
    127  1.1.1.2  christos }
    128  1.1.1.2  christos 
    129  1.1.1.2  christos template <typename E>
    130  1.1.1.2  christos class enum_flags
    131  1.1.1.2  christos {
    132  1.1.1.2  christos public:
    133  1.1.1.2  christos   typedef E enum_type;
    134  1.1.1.2  christos   typedef typename enum_underlying_type<enum_type>::type underlying_type;
    135      1.1  christos 
    136  1.1.1.3  christos   /* For to_string.  Maps one enumerator of E to a string.  */
    137  1.1.1.3  christos   struct string_mapping
    138  1.1.1.3  christos   {
    139  1.1.1.3  christos     E flag;
    140  1.1.1.3  christos     const char *str;
    141  1.1.1.3  christos   };
    142  1.1.1.3  christos 
    143  1.1.1.3  christos   /* Convenience for to_string implementations, to build a
    144  1.1.1.3  christos      string_mapping array.  */
    145  1.1.1.3  christos #define MAP_ENUM_FLAG(ENUM_FLAG) { ENUM_FLAG, #ENUM_FLAG }
    146  1.1.1.3  christos 
    147      1.1  christos public:
    148      1.1  christos   /* Allow default construction.  */
    149  1.1.1.2  christos   constexpr enum_flags ()
    150      1.1  christos     : m_enum_value ((enum_type) 0)
    151      1.1  christos   {}
    152      1.1  christos 
    153  1.1.1.2  christos   /* The default move/copy ctor/assignment do the right thing.  */
    154  1.1.1.2  christos 
    155      1.1  christos   /* If you get an error saying these two overloads are ambiguous,
    156      1.1  christos      then you tried to mix values of different enum types.  */
    157  1.1.1.2  christos   constexpr enum_flags (enum_type e)
    158      1.1  christos     : m_enum_value (e)
    159      1.1  christos   {}
    160  1.1.1.2  christos   constexpr enum_flags (enum_flags_detail::zero_type *zero)
    161      1.1  christos     : m_enum_value ((enum_type) 0)
    162      1.1  christos   {}
    163      1.1  christos 
    164  1.1.1.2  christos   enum_flags &operator&= (enum_flags e) &
    165      1.1  christos   {
    166  1.1.1.2  christos     m_enum_value = (enum_type) (m_enum_value & e.m_enum_value);
    167      1.1  christos     return *this;
    168      1.1  christos   }
    169  1.1.1.2  christos   enum_flags &operator|= (enum_flags e) &
    170      1.1  christos   {
    171  1.1.1.2  christos     m_enum_value = (enum_type) (m_enum_value | e.m_enum_value);
    172      1.1  christos     return *this;
    173      1.1  christos   }
    174  1.1.1.2  christos   enum_flags &operator^= (enum_flags e) &
    175      1.1  christos   {
    176  1.1.1.2  christos     m_enum_value = (enum_type) (m_enum_value ^ e.m_enum_value);
    177      1.1  christos     return *this;
    178      1.1  christos   }
    179      1.1  christos 
    180  1.1.1.2  christos   /* Delete rval versions.  */
    181  1.1.1.2  christos   void operator&= (enum_flags e) && = delete;
    182  1.1.1.2  christos   void operator|= (enum_flags e) && = delete;
    183  1.1.1.2  christos   void operator^= (enum_flags e) && = delete;
    184  1.1.1.2  christos 
    185  1.1.1.2  christos   /* Like raw enums, allow conversion to the underlying type.  */
    186  1.1.1.2  christos   constexpr operator underlying_type () const
    187      1.1  christos   {
    188      1.1  christos     return m_enum_value;
    189      1.1  christos   }
    190      1.1  christos 
    191  1.1.1.2  christos   /* Get the underlying value as a raw enum.  */
    192  1.1.1.2  christos   constexpr enum_type raw () const
    193      1.1  christos   {
    194  1.1.1.2  christos     return m_enum_value;
    195      1.1  christos   }
    196      1.1  christos 
    197  1.1.1.2  christos   /* Binary operations involving some unrelated type (which would be a
    198  1.1.1.2  christos      bug) are implemented as non-members, and deleted.  */
    199  1.1.1.2  christos 
    200  1.1.1.3  christos   /* Convert this object to a std::string, using MAPPING as
    201  1.1.1.3  christos      enumerator-to-string mapping array.  This is not meant to be
    202  1.1.1.3  christos      called directly.  Instead, enum_flags specializations should have
    203  1.1.1.3  christos      their own to_string function wrapping this one, thus hiding the
    204  1.1.1.3  christos      mapping array from callers.
    205  1.1.1.3  christos 
    206  1.1.1.3  christos      Note: this is defined outside the template class so it can use
    207  1.1.1.3  christos      the global operators for enum_type, which are only defined after
    208  1.1.1.3  christos      the template class.  */
    209  1.1.1.3  christos   template<size_t N>
    210  1.1.1.3  christos   std::string to_string (const string_mapping (&mapping)[N]) const;
    211  1.1.1.3  christos 
    212      1.1  christos private:
    213      1.1  christos   /* Stored as enum_type because GDB knows to print the bit flags
    214      1.1  christos      neatly if the enum values look like bit flags.  */
    215      1.1  christos   enum_type m_enum_value;
    216      1.1  christos };
    217      1.1  christos 
    218  1.1.1.2  christos template <typename E>
    219  1.1.1.2  christos using is_enum_flags_enum_type_t
    220  1.1.1.2  christos   = decltype (is_enum_flags_enum_type (std::declval<E *> ()));
    221  1.1.1.2  christos 
    222      1.1  christos /* Global operator overloads.  */
    223      1.1  christos 
    224  1.1.1.2  christos /* Generate binary operators.  */
    225      1.1  christos 
    226  1.1.1.2  christos #define ENUM_FLAGS_GEN_BINOP(OPERATOR_OP, OP)				\
    227  1.1.1.2  christos 									\
    228  1.1.1.2  christos   /* Raw enum on both LHS/RHS.  Returns raw enum type.  */		\
    229  1.1.1.2  christos   template <typename enum_type,						\
    230  1.1.1.2  christos 	    typename = is_enum_flags_enum_type_t<enum_type>>		\
    231  1.1.1.2  christos   constexpr enum_type							\
    232  1.1.1.2  christos   OPERATOR_OP (enum_type e1, enum_type e2)				\
    233  1.1.1.2  christos   {									\
    234  1.1.1.2  christos     using underlying = typename enum_flags<enum_type>::underlying_type;	\
    235  1.1.1.2  christos     return (enum_type) (underlying (e1) OP underlying (e2));		\
    236  1.1.1.2  christos   }									\
    237  1.1.1.2  christos 									\
    238  1.1.1.2  christos   /* enum_flags on the LHS.  */						\
    239  1.1.1.2  christos   template <typename enum_type,						\
    240  1.1.1.2  christos 	    typename = is_enum_flags_enum_type_t<enum_type>>		\
    241  1.1.1.2  christos   constexpr enum_flags<enum_type>					\
    242  1.1.1.2  christos   OPERATOR_OP (enum_flags<enum_type> e1, enum_type e2)			\
    243  1.1.1.2  christos   { return e1.raw () OP e2; }						\
    244  1.1.1.2  christos 									\
    245  1.1.1.2  christos   /* enum_flags on the RHS.  */						\
    246  1.1.1.2  christos   template <typename enum_type,						\
    247  1.1.1.2  christos 	    typename = is_enum_flags_enum_type_t<enum_type>>		\
    248  1.1.1.2  christos   constexpr enum_flags<enum_type>					\
    249  1.1.1.2  christos   OPERATOR_OP (enum_type e1, enum_flags<enum_type> e2)			\
    250  1.1.1.2  christos   { return e1 OP e2.raw (); }						\
    251  1.1.1.2  christos 									\
    252  1.1.1.2  christos   /* enum_flags on both LHS/RHS.  */					\
    253  1.1.1.2  christos   template <typename enum_type,						\
    254  1.1.1.2  christos 	    typename = is_enum_flags_enum_type_t<enum_type>>		\
    255  1.1.1.2  christos   constexpr enum_flags<enum_type>					\
    256  1.1.1.2  christos   OPERATOR_OP (enum_flags<enum_type> e1, enum_flags<enum_type> e2)	\
    257  1.1.1.2  christos   { return e1.raw () OP e2.raw (); }					\
    258  1.1.1.2  christos 									\
    259  1.1.1.2  christos   /* Delete cases involving unrelated types.  */			\
    260  1.1.1.2  christos 									\
    261  1.1.1.2  christos   template <typename enum_type, typename unrelated_type,		\
    262  1.1.1.2  christos 	    typename = is_enum_flags_enum_type_t<enum_type>>		\
    263  1.1.1.2  christos   constexpr enum_flags<enum_type>					\
    264  1.1.1.2  christos   OPERATOR_OP (enum_type e1, unrelated_type e2) = delete;		\
    265  1.1.1.2  christos 									\
    266  1.1.1.2  christos   template <typename enum_type, typename unrelated_type,		\
    267  1.1.1.2  christos 	    typename = is_enum_flags_enum_type_t<enum_type>>		\
    268  1.1.1.2  christos   constexpr enum_flags<enum_type>					\
    269  1.1.1.2  christos   OPERATOR_OP (unrelated_type e1, enum_type e2) = delete;		\
    270  1.1.1.2  christos 									\
    271  1.1.1.2  christos   template <typename enum_type, typename unrelated_type,		\
    272  1.1.1.2  christos 	    typename = is_enum_flags_enum_type_t<enum_type>>		\
    273  1.1.1.2  christos   constexpr enum_flags<enum_type>					\
    274  1.1.1.2  christos   OPERATOR_OP (enum_flags<enum_type> e1, unrelated_type e2) = delete;	\
    275  1.1.1.2  christos 									\
    276  1.1.1.2  christos   template <typename enum_type, typename unrelated_type,		\
    277  1.1.1.2  christos 	    typename = is_enum_flags_enum_type_t<enum_type>>		\
    278  1.1.1.2  christos   constexpr enum_flags<enum_type>					\
    279  1.1.1.2  christos   OPERATOR_OP (unrelated_type e1, enum_flags<enum_type> e2) = delete;
    280  1.1.1.2  christos 
    281  1.1.1.2  christos /* Generate non-member compound assignment operators.  Only the raw
    282  1.1.1.2  christos    enum versions are defined here.  The enum_flags versions are
    283  1.1.1.2  christos    defined as member functions, simply because it's less code that
    284  1.1.1.2  christos    way.
    285  1.1.1.2  christos 
    286  1.1.1.2  christos    Note we delete operators that would allow e.g.,
    287  1.1.1.2  christos 
    288  1.1.1.2  christos      "enum_type | 1" or "enum_type1 | enum_type2"
    289  1.1.1.2  christos 
    290  1.1.1.2  christos    because that would allow a mistake like :
    291  1.1.1.2  christos      enum flags1 { F1_FLAGS1 = 1 };
    292  1.1.1.2  christos      enum flags2 { F2_FLAGS2 = 2 };
    293  1.1.1.2  christos      enum flags1 val;
    294  1.1.1.2  christos      switch (val) {
    295  1.1.1.2  christos        case F1_FLAGS1 | F2_FLAGS2:
    296  1.1.1.2  christos      ...
    297      1.1  christos 
    298  1.1.1.2  christos    If you really need to 'or' enumerators of different flag types,
    299  1.1.1.2  christos    cast to integer first.
    300  1.1.1.2  christos */
    301  1.1.1.2  christos #define ENUM_FLAGS_GEN_COMPOUND_ASSIGN(OPERATOR_OP, OP)			\
    302  1.1.1.2  christos   /* lval reference version.  */					\
    303  1.1.1.2  christos   template <typename enum_type,						\
    304  1.1.1.2  christos 	    typename = is_enum_flags_enum_type_t<enum_type>>		\
    305  1.1.1.2  christos   constexpr enum_type &							\
    306  1.1.1.2  christos   OPERATOR_OP (enum_type &e1, enum_type e2)				\
    307  1.1.1.2  christos   { return e1 = e1 OP e2; }						\
    308  1.1.1.2  christos 									\
    309  1.1.1.2  christos   /* rval reference version.  */					\
    310  1.1.1.2  christos   template <typename enum_type,						\
    311  1.1.1.2  christos 	    typename = is_enum_flags_enum_type_t<enum_type>>		\
    312  1.1.1.2  christos   void									\
    313  1.1.1.2  christos   OPERATOR_OP (enum_type &&e1, enum_type e2) = delete;			\
    314  1.1.1.2  christos 									\
    315  1.1.1.2  christos   /* Delete compound assignment from unrelated types.  */		\
    316  1.1.1.2  christos 									\
    317  1.1.1.2  christos   template <typename enum_type, typename other_enum_type,		\
    318  1.1.1.2  christos 	    typename = is_enum_flags_enum_type_t<enum_type>>		\
    319  1.1.1.2  christos   constexpr enum_type &							\
    320  1.1.1.2  christos   OPERATOR_OP (enum_type &e1, other_enum_type e2) = delete;		\
    321  1.1.1.2  christos 									\
    322  1.1.1.2  christos   template <typename enum_type, typename other_enum_type,		\
    323  1.1.1.2  christos 	    typename = is_enum_flags_enum_type_t<enum_type>>		\
    324  1.1.1.2  christos   void									\
    325  1.1.1.2  christos   OPERATOR_OP (enum_type &&e1, other_enum_type e2) = delete;
    326  1.1.1.2  christos 
    327  1.1.1.2  christos ENUM_FLAGS_GEN_BINOP (operator|, |)
    328  1.1.1.2  christos ENUM_FLAGS_GEN_BINOP (operator&, &)
    329  1.1.1.2  christos ENUM_FLAGS_GEN_BINOP (operator^, ^)
    330  1.1.1.2  christos 
    331  1.1.1.2  christos ENUM_FLAGS_GEN_COMPOUND_ASSIGN (operator|=, |)
    332  1.1.1.2  christos ENUM_FLAGS_GEN_COMPOUND_ASSIGN (operator&=, &)
    333  1.1.1.2  christos ENUM_FLAGS_GEN_COMPOUND_ASSIGN (operator^=, ^)
    334  1.1.1.2  christos 
    335  1.1.1.2  christos /* Allow comparison with enum_flags, raw enum, and integers, only.
    336  1.1.1.2  christos    The latter case allows "== 0".  As side effect, it allows comparing
    337  1.1.1.2  christos    with integer variables too, but that's not a common mistake to
    338  1.1.1.2  christos    make.  It's important to disable comparison with unrelated types to
    339  1.1.1.2  christos    prevent accidentally comparing with unrelated enum values, which
    340  1.1.1.2  christos    are convertible to integer, and thus coupled with enum_flags
    341  1.1.1.3  christos    conversion to underlying type too, would trigger the built-in 'bool
    342  1.1.1.2  christos    operator==(unsigned, int)' operator.  */
    343  1.1.1.2  christos 
    344  1.1.1.2  christos #define ENUM_FLAGS_GEN_COMP(OPERATOR_OP, OP)				\
    345  1.1.1.2  christos 									\
    346  1.1.1.2  christos   /* enum_flags OP enum_flags */					\
    347  1.1.1.2  christos 									\
    348  1.1.1.2  christos   template <typename enum_type>						\
    349  1.1.1.2  christos   constexpr bool							\
    350  1.1.1.2  christos   OPERATOR_OP (enum_flags<enum_type> lhs, enum_flags<enum_type> rhs)	\
    351  1.1.1.2  christos   { return lhs.raw () OP rhs.raw (); }					\
    352  1.1.1.2  christos 									\
    353  1.1.1.2  christos   /* enum_flags OP other */						\
    354  1.1.1.2  christos 									\
    355  1.1.1.2  christos   template <typename enum_type>						\
    356  1.1.1.2  christos   constexpr bool							\
    357  1.1.1.2  christos   OPERATOR_OP (enum_flags<enum_type> lhs, enum_type rhs)		\
    358  1.1.1.2  christos   { return lhs.raw () OP rhs; }						\
    359  1.1.1.2  christos 									\
    360  1.1.1.2  christos   template <typename enum_type>						\
    361  1.1.1.2  christos   constexpr bool							\
    362  1.1.1.2  christos   OPERATOR_OP (enum_flags<enum_type> lhs, int rhs)			\
    363  1.1.1.2  christos   { return lhs.raw () OP rhs; }						\
    364  1.1.1.2  christos 									\
    365  1.1.1.2  christos   template <typename enum_type, typename U>				\
    366  1.1.1.2  christos   constexpr bool							\
    367  1.1.1.2  christos   OPERATOR_OP (enum_flags<enum_type> lhs, U rhs) = delete;		\
    368  1.1.1.2  christos 									\
    369  1.1.1.2  christos   /* other OP enum_flags */						\
    370  1.1.1.2  christos 									\
    371  1.1.1.2  christos   template <typename enum_type>						\
    372  1.1.1.2  christos   constexpr bool							\
    373  1.1.1.2  christos   OPERATOR_OP (enum_type lhs, enum_flags<enum_type> rhs)		\
    374  1.1.1.2  christos   { return lhs OP rhs.raw (); }						\
    375  1.1.1.2  christos 									\
    376  1.1.1.2  christos   template <typename enum_type>						\
    377  1.1.1.2  christos   constexpr bool							\
    378  1.1.1.2  christos   OPERATOR_OP (int lhs, enum_flags<enum_type> rhs)			\
    379  1.1.1.2  christos   { return lhs OP rhs.raw (); }						\
    380  1.1.1.2  christos 									\
    381  1.1.1.2  christos   template <typename enum_type, typename U>				\
    382  1.1.1.2  christos   constexpr bool							\
    383  1.1.1.2  christos   OPERATOR_OP (U lhs, enum_flags<enum_type> rhs) = delete;
    384  1.1.1.2  christos 
    385  1.1.1.2  christos ENUM_FLAGS_GEN_COMP (operator==, ==)
    386  1.1.1.2  christos ENUM_FLAGS_GEN_COMP (operator!=, !=)
    387  1.1.1.2  christos 
    388  1.1.1.2  christos /* Unary operators for the raw flags enum.  */
    389  1.1.1.2  christos 
    390  1.1.1.2  christos /* We require underlying type to be unsigned when using operator~ --
    391  1.1.1.2  christos    if it were not unsigned, undefined behavior could result.  However,
    392  1.1.1.2  christos    asserting this in the class itself would require too many
    393  1.1.1.2  christos    unnecessary changes to usages of otherwise OK enum types.  */
    394  1.1.1.2  christos template <typename enum_type,
    395  1.1.1.2  christos 	  typename = is_enum_flags_enum_type_t<enum_type>,
    396  1.1.1.2  christos 	  typename
    397  1.1.1.2  christos 	    = gdb::Requires<enum_flags_detail::EnumIsUnsigned<enum_type>>>
    398  1.1.1.2  christos constexpr enum_type
    399  1.1.1.2  christos operator~ (enum_type e)
    400      1.1  christos {
    401  1.1.1.2  christos   using underlying = typename enum_flags<enum_type>::underlying_type;
    402  1.1.1.2  christos   return (enum_type) ~underlying (e);
    403      1.1  christos }
    404      1.1  christos 
    405  1.1.1.2  christos template <typename enum_type,
    406  1.1.1.2  christos 	  typename = is_enum_flags_enum_type_t<enum_type>,
    407  1.1.1.2  christos 	  typename = gdb::Requires<enum_flags_detail::EnumIsSigned<enum_type>>>
    408  1.1.1.2  christos constexpr void operator~ (enum_type e) = delete;
    409  1.1.1.2  christos 
    410  1.1.1.2  christos template <typename enum_type,
    411  1.1.1.2  christos 	  typename = is_enum_flags_enum_type_t<enum_type>,
    412  1.1.1.2  christos 	  typename
    413  1.1.1.2  christos 	    = gdb::Requires<enum_flags_detail::EnumIsUnsigned<enum_type>>>
    414  1.1.1.2  christos constexpr enum_flags<enum_type>
    415  1.1.1.2  christos operator~ (enum_flags<enum_type> e)
    416      1.1  christos {
    417  1.1.1.2  christos   using underlying = typename enum_flags<enum_type>::underlying_type;
    418  1.1.1.2  christos   return (enum_type) ~underlying (e);
    419      1.1  christos }
    420      1.1  christos 
    421  1.1.1.2  christos template <typename enum_type,
    422  1.1.1.2  christos 	  typename = is_enum_flags_enum_type_t<enum_type>,
    423  1.1.1.2  christos 	  typename = gdb::Requires<enum_flags_detail::EnumIsSigned<enum_type>>>
    424  1.1.1.2  christos constexpr void operator~ (enum_flags<enum_type> e) = delete;
    425  1.1.1.2  christos 
    426  1.1.1.2  christos /* Delete operator<< and operator>>.  */
    427  1.1.1.2  christos 
    428  1.1.1.2  christos template <typename enum_type, typename any_type,
    429  1.1.1.2  christos 	  typename = is_enum_flags_enum_type_t<enum_type>>
    430  1.1.1.2  christos void operator<< (const enum_type &, const any_type &) = delete;
    431  1.1.1.2  christos 
    432  1.1.1.2  christos template <typename enum_type, typename any_type,
    433  1.1.1.2  christos 	  typename = is_enum_flags_enum_type_t<enum_type>>
    434  1.1.1.2  christos void operator<< (const enum_flags<enum_type> &, const any_type &) = delete;
    435  1.1.1.2  christos 
    436  1.1.1.2  christos template <typename enum_type, typename any_type,
    437  1.1.1.2  christos 	  typename = is_enum_flags_enum_type_t<enum_type>>
    438  1.1.1.2  christos void operator>> (const enum_type &, const any_type &) = delete;
    439  1.1.1.2  christos 
    440  1.1.1.2  christos template <typename enum_type, typename any_type,
    441  1.1.1.2  christos 	  typename = is_enum_flags_enum_type_t<enum_type>>
    442  1.1.1.2  christos void operator>> (const enum_flags<enum_type> &, const any_type &) = delete;
    443  1.1.1.2  christos 
    444  1.1.1.3  christos template<typename E>
    445  1.1.1.3  christos template<size_t N>
    446  1.1.1.3  christos std::string
    447  1.1.1.3  christos enum_flags<E>::to_string (const string_mapping (&mapping)[N]) const
    448  1.1.1.3  christos {
    449  1.1.1.3  christos   enum_type flags = raw ();
    450  1.1.1.3  christos   std::string res = hex_string (flags);
    451  1.1.1.3  christos   res += " [";
    452  1.1.1.3  christos 
    453  1.1.1.3  christos   bool need_space = false;
    454  1.1.1.3  christos   for (const auto &entry : mapping)
    455  1.1.1.3  christos     {
    456  1.1.1.3  christos       if ((flags & entry.flag) != 0)
    457  1.1.1.3  christos 	{
    458  1.1.1.3  christos 	  /* Work with an unsigned version of the underlying type,
    459  1.1.1.3  christos 	     because if enum_type's underlying type is signed, op~
    460  1.1.1.3  christos 	     won't be defined for it, and, bitwise operations on
    461  1.1.1.3  christos 	     signed types are implementation defined.  */
    462  1.1.1.3  christos 	  using uns = typename std::make_unsigned<underlying_type>::type;
    463  1.1.1.3  christos 	  flags &= (enum_type) ~(uns) entry.flag;
    464  1.1.1.3  christos 
    465  1.1.1.3  christos 	  if (need_space)
    466  1.1.1.3  christos 	    res += " ";
    467  1.1.1.3  christos 	  res += entry.str;
    468  1.1.1.3  christos 
    469  1.1.1.3  christos 	  need_space = true;
    470  1.1.1.3  christos 	}
    471  1.1.1.3  christos     }
    472  1.1.1.3  christos 
    473  1.1.1.3  christos   /* If there were flags not included in the mapping, print them as
    474  1.1.1.3  christos      a hex number.  */
    475  1.1.1.3  christos   if (flags != 0)
    476  1.1.1.3  christos     {
    477  1.1.1.3  christos       if (need_space)
    478  1.1.1.3  christos 	res += " ";
    479  1.1.1.3  christos       res += hex_string (flags);
    480  1.1.1.3  christos     }
    481  1.1.1.3  christos 
    482  1.1.1.3  christos   res += "]";
    483  1.1.1.3  christos 
    484  1.1.1.3  christos   return res;
    485  1.1.1.3  christos }
    486  1.1.1.3  christos 
    487      1.1  christos #else /* __cplusplus */
    488      1.1  christos 
    489      1.1  christos /* In C, the flags type is just a typedef for the enum type.  */
    490      1.1  christos 
    491      1.1  christos #define DEF_ENUM_FLAGS_TYPE(enum_type, flags_type) \
    492      1.1  christos   typedef enum_type flags_type
    493      1.1  christos 
    494      1.1  christos #endif /* __cplusplus */
    495      1.1  christos 
    496      1.1  christos #endif /* COMMON_ENUM_FLAGS_H */
    497