Fix sorting of enum values in FlagEnumerationPrinter
authorSimon Marchi <simon.marchi@polymtl.ca>
Wed, 20 Jan 2016 18:42:53 +0000 (13:42 -0500)
committerSimon Marchi <simon.marchi@polymtl.ca>
Wed, 20 Jan 2016 18:44:33 +0000 (13:44 -0500)
The lambda function used to sort the enumerator list does not work
properly.  This list consists of tuples, (enum label, enum value).  The
key function returns x.enumval.  enumval not being defined for a tuple,
we see this exception in the test log:

  Python Exception <class 'AttributeError'> 'tuple' object has no attribute 'enumval'

The function should return the second item of the tuple, which is the
enumval.

The pretty-printer still worked mostly correctly, except that the
enumeration values were not sorted.  The test still passed because the
enumeration values are already sorted where they are defined.  The test
also passed despite the exception being printed, because the right output
was printed after the exception:

  print (enum flag_enum) (FLAG_1)
  Python Exception <type 'exceptions.AttributeError'> 'tuple' objecthas no attribute 'enumval':M
  $7 = 0x1 [FLAG_1]
  (gdb) PASS: gdb.python/py-pp-maint.exp: print FLAG_1

New in v2:

- Improved test case, I stole Pedro's example directly.  It verifies
  that the sorting of enumerators by value works, by checking that
  printing FOO_MASK appears as FOO_1 | FOO_2 | FOO_3.

  I noticed that I could change the regexps to almost anything and the
  tests would still pass.  I think it was because of the | in there.  I
  made them more robust by using string_to_regexp.  I used curly braces
  { } instead of quoting marks " " for strings, so that I could use
  square brackets [ ] in them without having to escape them all.  I also
  removed the "message" part of the tests, since they are redundant with
  the command, and it's just more maintenance to have to update them.

  Tested with Python 2.7 and 3.5.

gdb/ChangeLog:

* python/lib/gdb/printing.py (FlagEnumerationPrinter.__call__):
Fix enumerators sort key function.

gdb/testsuite/ChangeLog:

* gdb.python/py-pp-maint.exp: Change/add enum flag tests.
* gdb.python/py-pp-maint.c (enum flag_enum): Use more complex
enum flag values.

gdb/ChangeLog
gdb/python/lib/gdb/printing.py
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.python/py-pp-maint.c
gdb/testsuite/gdb.python/py-pp-maint.exp

index 937f8ac941029086c7cd7927339af12f60f1c15d..705c2e146f0b05025ccd2cb6aff5ec0a520461a4 100644 (file)
@@ -1,3 +1,8 @@
+2016-01-20  Simon Marchi  <simon.marchi@polymtl.ca>
+
+       * python/lib/gdb/printing.py (FlagEnumerationPrinter.__call__):
+       Fix enumerators sort key function.
+
 2016-01-20  Joel Brobecker  <brobecker@adacore.com>
 
        * printcmd.c (print_scalar_formatted): Move binary operator from
index 5160581a5b2f8a6857b0df18c80a7074af4fba00..63c3aeb23d8116dc0c49f1dc7acb7106131d869a 100644 (file)
@@ -263,7 +263,7 @@ class FlagEnumerationPrinter(PrettyPrinter):
                 self.enumerators.append((field.name, field.enumval))
             # Sorting the enumerators by value usually does the right
             # thing.
-            self.enumerators.sort(key = lambda x: x.enumval)
+            self.enumerators.sort(key = lambda x: x[1])
 
         if self.enabled:
             return _EnumInstance(self.enumerators, val)
index 3485cfe555cc3ccb3047f79cc05e92a7a291ad84..7e6da03c94c3a5691ae869bf4207f6057c0b2e58 100644 (file)
@@ -1,3 +1,9 @@
+2016-01-20  Simon Marchi  <simon.marchi@polymtl.ca>
+
+       * gdb.python/py-pp-maint.exp: Change/add enum flag tests.
+       * gdb.python/py-pp-maint.c (enum flag_enum): Use more complex
+       enum flag values.
+
 2016-01-20  Andreas Arnez  <arnez@linux.vnet.ibm.com>
 
        * gdb.base/gnu_vector.exp: Re-establish handling for should_kfail
index 657dfd7c19b3ac9d64a6787b74cf6acf10905e37..d750496ff7d0a1ed1ed8866d8d2b154c69a64932 100644 (file)
 
 #include <string.h>
 
+
 enum flag_enum
   {
-    FLAG_1 = 1,
-    FLAG_2 = 2,
-    FLAG_3 = 4,
-    ALL = FLAG_1 | FLAG_2 | FLAG_3
+    /* Define the enumeration values in an unsorted manner to verify that we
+       effectively sort them by value.  */
+    FOO_MASK = 0x07,
+    FOO_1    = 0x01,
+    FOO_2    = 0x02,
+    FOO_3    = 0x04,
+
+    BAR_MASK = 0x70,
+    BAR_1    = 0x10,
+    BAR_2    = 0x20,
+    BAR_3    = 0x40,
   };
 
 enum flag_enum fval;
index db0768f86c007dccf7d5a5052ed2b6ebaf20a7de..a424931078c2da94bd59866f22b165c4bd3b7996 100644 (file)
@@ -119,14 +119,23 @@ gdb_test "print flt" " = x=<42> y=<43>" \
 gdb_test "print ss" " = a=<a=<1> b=<$hex>> b=<a=<2> b=<$hex>>" \
     "print ss re-enabled"
 
-gdb_test "print (enum flag_enum) (FLAG_1)" \
-    " = 0x1 .FLAG_1." \
-    "print FLAG_1"
+gdb_test_exact "print (enum flag_enum) (FOO_1)" \
+    { = 0x1 [FOO_1]}
 
-gdb_test "print (enum flag_enum) (FLAG_1 | FLAG_3)" \
-    " = 0x5 .FLAG_1 | FLAG_3." \
-    "print FLAG_1 | FLAG_3"
+gdb_test_exact "print (enum flag_enum) (BAR_3)" \
+    { = 0x40 [BAR_3]}
 
-gdb_test "print (enum flag_enum) (4 + 8)" \
-    " = 0xc .FLAG_1 | <unknown: 0x8>." \
-    "print FLAG_1 | 8"
+gdb_test_exact "print (enum flag_enum) (BAR_2 | FOO_2)" \
+    { = 0x22 [FOO_2 | BAR_2]}
+
+gdb_test_exact "print (enum flag_enum) (FOO_1 | FOO_2 | FOO_3)" \
+    { = 0x7 [FOO_1 | FOO_2 | FOO_3]}
+
+gdb_test_exact "print (enum flag_enum) (FOO_MASK)" \
+    { = 0x7 [FOO_1 | FOO_2 | FOO_3]}
+
+gdb_test_exact "print (enum flag_enum) (FOO_MASK | (BAR_MASK & ~BAR_2))" \
+    { = 0x57 [FOO_1 | FOO_2 | FOO_3 | BAR_1 | BAR_3]}
+
+gdb_test_exact "print (enum flag_enum) (0x4 + 0x8)" \
+    { = 0xc [FOO_3 | <unknown: 0x8>]}