aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog8
-rw-r--r--gdb/dwarf2/read.c12
-rw-r--r--gdb/testsuite/ChangeLog12
-rw-r--r--gdb/testsuite/gdb.base/printcmds.c30
-rw-r--r--gdb/testsuite/gdb.base/printcmds.exp20
-rw-r--r--gdb/valprint.c8
6 files changed, 81 insertions, 9 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ee7298b..ca9f364 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,11 @@
+2020-02-18 Simon Marchi <simon.marchi@efficios.com>
+
+ * dwarf2/read.c: Include "count-one-bits.h".
+ (update_enumeration_type_from_children): If an enumerator has
+ multiple bits set, don't treat the enumeration as a "flag enum".
+ * valprint.c (generic_val_print_enum_1): Assert that enumerators
+ of flag enums have 0 or 1 bit set.
+
2020-02-18 Bernd Edlinger <bernd.edlinger@hotmail.de>
* aarch64-tdep.c (aarch64_displaced_step_copy_insn): Use an explicit
diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c
index e74383e..5a77b62 100644
--- a/gdb/dwarf2/read.c
+++ b/gdb/dwarf2/read.c
@@ -82,6 +82,7 @@
#include "gdbsupport/selftest.h"
#include "rust-lang.h"
#include "gdbsupport/pathstuff.h"
+#include "count-one-bits.h"
/* When == 1, print basic high level tracing messages.
When > 1, be more verbose.
@@ -15526,10 +15527,15 @@ update_enumeration_type_from_children (struct die_info *die,
unsigned_enum = 0;
flag_enum = 0;
}
- else if ((mask & value) != 0)
- flag_enum = 0;
else
- mask |= value;
+ {
+ 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
a flag type, no need to look at the rest of the enumerates. */
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index e8ef3d3..5aaf5fe 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,15 @@
+2020-02-18 Simon Marchi <simon.marchi@efficios.com>
+
+ * gdb.base/printcmds.c (enum flag_enum): Prefix enumerators with
+ FE_, add FE_NONE.
+ (three): Update.
+ (enum flag_enum_without_zero): New enum.
+ (flag_enum_without_zero): New variable.
+ (enum not_flag_enum): New enum.
+ (three_not_flag): New variable.
+ * gdb.base/printcmds.exp (test_artificial_arrays): Update.
+ (test_print_enums): Add more tests for printing flag enums.
+
2020-02-18 Tom de Vries <tdevries@suse.de>
* lib/ada.exp (gdb_compile_ada_1): Factor out of ...
diff --git a/gdb/testsuite/gdb.base/printcmds.c b/gdb/testsuite/gdb.base/printcmds.c
index 57e04e6..acb3cb3 100644
--- a/gdb/testsuite/gdb.base/printcmds.c
+++ b/gdb/testsuite/gdb.base/printcmds.c
@@ -96,9 +96,35 @@ enum some_volatile_enum { enumvolval1, enumvolval2 };
name. See PR11827. */
volatile enum some_volatile_enum some_volatile_enum = enumvolval1;
-enum flag_enum { ONE = 1, TWO = 2 };
+/* An enum considered as a "flag enum". */
+enum flag_enum
+{
+ FE_NONE = 0x00,
+ FE_ONE = 0x01,
+ FE_TWO = 0x02,
+};
+
+enum flag_enum three = FE_ONE | FE_TWO;
+
+/* Another enum considered as a "flag enum", but with no enumerator with value
+ 0. */
+enum flag_enum_without_zero
+{
+ FEWZ_ONE = 0x01,
+ FEWZ_TWO = 0x02,
+};
+
+enum flag_enum_without_zero flag_enum_without_zero = 0;
+
+/* Not a flag enum, an enumerator value has multiple bits sets. */
+enum not_flag_enum
+{
+ NFE_ONE = 0x01,
+ NFE_TWO = 0x02,
+ NFE_F0 = 0xf0,
+};
-enum flag_enum three = ONE | TWO;
+enum not_flag_enum three_not_flag = NFE_ONE | NFE_TWO;
/* A structure with an embedded array at an offset > 0. The array has
all elements with the same repeating value, which must not be the
diff --git a/gdb/testsuite/gdb.base/printcmds.exp b/gdb/testsuite/gdb.base/printcmds.exp
index 6e98b79..6afb965 100644
--- a/gdb/testsuite/gdb.base/printcmds.exp
+++ b/gdb/testsuite/gdb.base/printcmds.exp
@@ -653,9 +653,9 @@ proc test_artificial_arrays {} {
gdb_test_escape_braces "p int1dim\[0\]${ctrlv}@2${ctrlv}@3" \
"({{0, 1}, {2, 3}, {4, 5}}|\[Cc\]annot.*)" \
{p int1dim[0]@2@3}
- gdb_test_escape_braces "p int1dim\[0\]${ctrlv}@TWO" " = {0, 1}" \
+ gdb_test_escape_braces "p int1dim\[0\]${ctrlv}@FE_TWO" " = {0, 1}" \
{p int1dim[0]@TWO}
- gdb_test_escape_braces "p int1dim\[0\]${ctrlv}@TWO${ctrlv}@three" \
+ gdb_test_escape_braces "p int1dim\[0\]${ctrlv}@FE_TWO${ctrlv}@three" \
"({{0, 1}, {2, 3}, {4, 5}}|\[Cc\]annot.*)" \
{p int1dim[0]@TWO@three}
gdb_test_escape_braces {p/x (short [])0x12345678} \
@@ -736,7 +736,21 @@ proc test_print_enums {} {
# Regression test for PR11827.
gdb_test "print some_volatile_enum" "enumvolval1"
- gdb_test "print three" " = \\\(ONE \\| TWO\\\)"
+ # Print a flag enum.
+ gdb_test "print three" [string_to_regexp " = (FE_ONE | FE_TWO)"]
+
+ # Print a flag enum with value 0, where an enumerator has value 0.
+ gdb_test "print (enum flag_enum) 0x0" [string_to_regexp " = FE_NONE"]
+
+ # Print a flag enum with value 0, where no enumerator has value 0.
+ gdb_test "print flag_enum_without_zero" [string_to_regexp " = (unknown: 0)"]
+
+ # Print a flag enum with unknown bits set.
+ gdb_test "print (enum flag_enum) 0xf1" [string_to_regexp " = (FE_ONE | unknown: 240)"]
+
+ # Test printing an enum not considered a "flag enum" (because one of its
+ # enumerators has multiple bits set).
+ gdb_test "print three_not_flag" [string_to_regexp " = 3"]
}
proc test_printf {} {
diff --git a/gdb/valprint.c b/gdb/valprint.c
index f26a87d..77b9a49 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -39,6 +39,7 @@
#include "cli/cli-option.h"
#include "gdbarch.h"
#include "cli/cli-style.h"
+#include "count-one-bits.h"
/* Maximum number of wchars returned from wchar_iterate. */
#define MAX_WCHARS 4
@@ -638,7 +639,12 @@ generic_val_print_enum_1 (struct type *type, LONGEST val,
{
QUIT;
- if ((val & TYPE_FIELD_ENUMVAL (type, i)) != 0)
+ ULONGEST enumval = TYPE_FIELD_ENUMVAL (type, i);
+ int nbits = count_one_bits_ll (enumval);
+
+ gdb_assert (nbits == 0 || nbits == 1);
+
+ if ((val & enumval) != 0)
{
if (!first)
fputs_filtered (" | ", stream);