gdb: allow duplicate enumerators in flag enums

I have come across some uses cases where it would be desirable to treat
an enum that has duplicate values as a "flag enum".  For example, this
one here [1]:

    enum membarrier_cmd {
            MEMBARRIER_CMD_QUERY                                = 0,
            MEMBARRIER_CMD_GLOBAL                               = (1 << 0),
            MEMBARRIER_CMD_GLOBAL_EXPEDITED                     = (1 << 1),
            MEMBARRIER_CMD_REGISTER_GLOBAL_EXPEDITED            = (1 << 2),
            MEMBARRIER_CMD_PRIVATE_EXPEDITED                    = (1 << 3),
            MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED           = (1 << 4),
            MEMBARRIER_CMD_PRIVATE_EXPEDITED_SYNC_CORE          = (1 << 5),
            MEMBARRIER_CMD_REGISTER_PRIVATE_EXPEDITED_SYNC_CORE = (1 << 6),

            /* Alias for header backward compatibility. */
            MEMBARRIER_CMD_SHARED = MEMBARRIER_CMD_GLOBAL,
    };

The last enumerator is kept for backwards compatibility.  Without this
patch, this enumeration wouldn't be considered a flag enum, because two
enumerators collide.   With this patch, it would be considered a flag
enum, and the value 3 would be printed as:

  MEMBARRIER_CMD_GLOBAL | MEMBARRIER_CMD_GLOBAL_EXPEDITED

Although if people prefer, we could display both MEMBARRIER_CMD_GLOBAL
and MEMBARRIER_CMD_SHARED in the result.  It wouldn't be wrong, and
could perhaps be useful in case a bit may have multiple meanings
(depending on some other bit value).

[1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/include/uapi/linux/membarrier.h?id=0bf999f9c5e74c7ecf9dafb527146601e5c848b9#n125

gdb/ChangeLog:

	* dwarf2/read.c (update_enumeration_type_from_children): Allow
	flag enums to contain duplicate enumerators.
	* valprint.c (generic_val_print_enum_1): Update comment.

gdb/testsuite/ChangeLog:

	* gdb.base/printcmds.c (enum flag_enum): Add FE_TWO_LEGACY
	enumerator.
This commit is contained in:
Simon Marchi 2020-02-18 17:29:23 -05:00
parent edd45eb06b
commit 6740f0cc3b
5 changed files with 19 additions and 11 deletions

View File

@ -1,3 +1,9 @@
2020-02-18 Simon Marchi <simon.marchi@efficios.com>
* dwarf2/read.c (update_enumeration_type_from_children): Allow
flag enums to contain duplicate enumerators.
* valprint.c (generic_val_print_enum_1): Update comment.
2020-02-18 Simon Marchi <simon.marchi@efficios.com>
* dwarf2/read.c: Include "count-one-bits.h".

View File

@ -15495,7 +15495,6 @@ update_enumeration_type_from_children (struct die_info *die,
struct die_info *child_die;
int unsigned_enum = 1;
int flag_enum = 1;
ULONGEST mask = 0;
auto_obstack obstack;
@ -15531,10 +15530,6 @@ update_enumeration_type_from_children (struct die_info *die,
{
if (count_one_bits_ll (value) >= 2)
flag_enum = 0;
else if ((mask & value) != 0)
flag_enum = 0;
else
mask |= value;
}
/* If we already know that the enum type is neither unsigned, nor

View File

@ -1,3 +1,8 @@
2020-02-18 Simon Marchi <simon.marchi@efficios.com>
* gdb.base/printcmds.c (enum flag_enum): Add FE_TWO_LEGACY
enumerator.
2020-02-18 Simon Marchi <simon.marchi@efficios.com>
* gdb.base/printcmds.c (enum flag_enum): Prefix enumerators with

View File

@ -99,9 +99,10 @@ volatile enum some_volatile_enum some_volatile_enum = enumvolval1;
/* An enum considered as a "flag enum". */
enum flag_enum
{
FE_NONE = 0x00,
FE_ONE = 0x01,
FE_TWO = 0x02,
FE_NONE = 0x00,
FE_ONE = 0x01,
FE_TWO = 0x02,
FE_TWO_LEGACY = 0x02,
};
enum flag_enum three = FE_ONE | FE_TWO;

View File

@ -631,9 +631,10 @@ generic_val_print_enum_1 (struct type *type, LONGEST val,
{
int first = 1;
/* We have a "flag" enum, so we try to decompose it into
pieces as appropriate. A flag enum has disjoint
constants by definition. */
/* We have a "flag" enum, so we try to decompose it into pieces as
appropriate. The enum may have multiple enumerators representing
the same bit, in which case we choose to only print the first one
we find. */
fputs_filtered ("(", stream);
for (i = 0; i < len; ++i)
{