gdb: fix pretty printing max depth behaviour
authorKent Cheung <kent.cheung@arm.com>
Thu, 13 May 2021 14:42:20 +0000 (15:42 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Fri, 14 May 2021 05:51:21 +0000 (06:51 +0100)
The 'print max-depth' feature incorrectly causes GDB to skip printing
the string representation of pretty printed variables if the variable
is stored at a nested depth corresponding to the set max-depth value.
This change ensures that it is always printed before checking whether
the maximum print depth has been reached.

Regression tested with GCC 7.3.0 on x86_64, ppc64le, aarch64.

gdb/ChangeLog:

* cp-valprint.c (cp_print_value): Replaced duplicate code.
* guile/scm-pretty-print.c (ppscm_print_children): Check max_depth
just before printing child values.
(gdbscm_apply_val_pretty_printer): Don't check max_depth before
printing string representation.
* python/py-prettyprint.c (print_children): Check max_depth just
before printing child values.
(gdbpy_apply_val_pretty_printer): Don't check max_depth before
printing string representation.

gdb/testsuite/ChangeLog:

* gdb.python/py-format-string.c: Added a variable to test.
* gdb.python/py-format-string.exp: Check string representation is
printed at appropriate max_depth settings.
* gdb.python/py-nested-maps.exp: Likewise.
* gdb.guile/scm-pretty-print.exp: Add additional tests.

gdb/ChangeLog
gdb/cp-valprint.c
gdb/guile/scm-pretty-print.c
gdb/python/py-prettyprint.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.guile/scm-pretty-print.exp
gdb/testsuite/gdb.python/py-format-string.c
gdb/testsuite/gdb.python/py-format-string.exp
gdb/testsuite/gdb.python/py-nested-maps.exp

index 172886923311444fd8847141d15467aa252ddf91..7059ba2a51c3d2a1fe3d3d91a5f6c616afcbff97 100644 (file)
@@ -1,3 +1,15 @@
+2021-05-14  Kent Cheung  <kent.cheung@arm.com>
+
+       * cp-valprint.c (cp_print_value): Replaced duplicate code.
+       * guile/scm-pretty-print.c (ppscm_print_children): Check max_depth
+       just before printing child values.
+       (gdbscm_apply_val_pretty_printer): Don't check max_depth before
+       printing string representation.
+       * python/py-prettyprint.c (print_children): Check max_depth just
+       before printing child values.
+       (gdbpy_apply_val_pretty_printer): Don't check max_depth before
+       printing string representation.
+
 2021-05-14  Mike Frysinger  <vapier@gentoo.org>
 
        * remote-sim.c: Change gdb/callback.h & gdb/remote-sim.h includes to
index d303c83694da6e031377f049a121617e4686f1c2..6c0449458698dfc06b9a5fb380f89f7e8bf3ea76 100644 (file)
@@ -495,14 +495,8 @@ cp_print_value (struct value *val, struct ui_file *stream,
        {
          int result = 0;
 
-         if (options->max_depth > -1
-             && recurse >= options->max_depth)
-           {
-             const struct language_defn *language = current_language;
-             gdb_assert (language->struct_too_deep_ellipsis () != NULL);
-             fputs_filtered (language->struct_too_deep_ellipsis (), stream);
-           }
-         else
+         if (!val_print_check_max_depth (stream, recurse, options,
+                                         current_language))
            {
              struct value *baseclass_val = value_primitive_field (val, 0,
                                                                   i, type);
index 605615e62937a5a01d4d3d77dac65698313e2e45..2dd7798a9a1d2d2af283f58cbeac90e2bf116629 100644 (file)
@@ -818,21 +818,29 @@ ppscm_print_children (SCM printer, enum display_hint hint,
       gdb::unique_xmalloc_ptr<char> name
        = gdbscm_scm_to_c_string (scm_name);
 
-      /* Print initial "{".  For other elements, there are three cases:
+      /* Print initial "=" to separate print_string_repr output and
+        children.  For other elements, there are three cases:
         1. Maps.  Print a "," after each value element.
         2. Arrays.  Always print a ",".
         3. Other.  Always print a ",".  */
       if (i == 0)
-       {
-        if (printed_nothing)
-          fputs_filtered ("{", stream);
-        else
-          fputs_filtered (" = {", stream);
-       }
-
+      {
+       if (!printed_nothing)
+         fputs_filtered (" = ", stream);
+      }
       else if (! is_map || i % 2 == 0)
        fputs_filtered (pretty ? "," : ", ", stream);
 
+      /* Skip printing children if max_depth has been reached.  This check
+        is performed after print_string_repr and the "=" separator so that
+        these steps are not skipped if the variable is located within the
+        permitted depth.  */
+      if (val_print_check_max_depth (stream, recurse, options, language))
+       goto done;
+      else if (i == 0)
+       /* Print initial "{" to bookend children.  */
+       fputs_filtered ("{", stream);
+
       /* In summary mode, we just want to print "= {...}" if there is
         a value.  */
       if (options->summary)
@@ -991,12 +999,6 @@ gdbscm_apply_val_pretty_printer (const struct extension_language_defn *extlang,
     }
   gdb_assert (ppscm_is_pretty_printer_worker (printer));
 
-  if (val_print_check_max_depth (stream, recurse, options, language))
-    {
-      result = EXT_LANG_RC_OK;
-      goto done;
-    }
-
   /* If we are printing a map, we want some special formatting.  */
   hint = ppscm_get_display_hint_enum (printer);
   if (hint == HINT_ERROR)
index 7c0fdaa9e70315c10f099c5784401094010d6687..fef4dcd66fbba79aebaa468bbfb369eec16f841c 100644 (file)
@@ -431,22 +431,29 @@ print_children (PyObject *printer, const char *hint,
          continue;
        }
 
-      /* Print initial "{".  For other elements, there are three
-        cases:
+      /* Print initial "=" to separate print_string_repr output and
+        children.  For other elements, there are three cases:
         1. Maps.  Print a "," after each value element.
         2. Arrays.  Always print a ",".
         3. Other.  Always print a ",".  */
       if (i == 0)
-       {
-        if (is_py_none)
-          fputs_filtered ("{", stream);
-        else
-          fputs_filtered (" = {", stream);
-       }
-
+      {
+       if (!is_py_none)
+         fputs_filtered (" = ", stream);
+      }
       else if (! is_map || i % 2 == 0)
        fputs_filtered (pretty ? "," : ", ", stream);
 
+      /* Skip printing children if max_depth has been reached.  This check
+        is performed after print_string_repr and the "=" separator so that
+        these steps are not skipped if the variable is located within the
+        permitted depth.  */
+      if (val_print_check_max_depth (stream, recurse, options, language))
+       return;
+      else if (i == 0)
+       /* Print initial "{" to bookend children.  */
+       fputs_filtered ("{", stream);
+
       /* In summary mode, we just want to print "= {...}" if there is
         a value.  */
       if (options->summary)
@@ -597,9 +604,6 @@ gdbpy_apply_val_pretty_printer (const struct extension_language_defn *extlang,
   if (printer == Py_None)
     return EXT_LANG_RC_NOP;
 
-  if (val_print_check_max_depth (stream, recurse, options, language))
-    return EXT_LANG_RC_OK;
-
   /* If we are printing a map, we want some special formatting.  */
   gdb::unique_xmalloc_ptr<char> hint (gdbpy_get_display_hint (printer.get ()));
 
index c59e46ae65b5d724debc39ddc2ac7b6df8b2465e..cb0a04ebcc076c7ac8c71060b6833adabc19b6f0 100644 (file)
@@ -1,3 +1,12 @@
+2021-05-14  Kent Cheung  <kent.cheung@arm.com>
+           Andrew Burgess  <andrew.burgess@embecosm.com>
+
+       * gdb.python/py-format-string.c: Added a variable to test.
+       * gdb.python/py-format-string.exp: Check string representation is
+       printed at appropriate max_depth settings.
+       * gdb.python/py-nested-maps.exp: Likewise.
+       * gdb.guile/scm-pretty-print.exp: Add additional tests.
+
 2021-05-13  Andrew Burgess  <andrew.burgess@embecosm.com>
 
        * gdb.guile/scm-pretty-print.exp (run_lang_tests): Give some tests
index f1ed7141680d4cba6be3cae67b1d787e8e067da2..7bd9d469ff6c4f6f02aaa8d46755e13fd19e23c2 100644 (file)
@@ -92,6 +92,10 @@ proc run_lang_tests {exefile lang} {
        gdb_test "print x" " = \"this is x\""
        gdb_test "print cstring" " = \"const string\""
 
+       gdb_test_no_output "set print max-depth 0"
+       gdb_test "print cstring" " = \"const string\""
+       gdb_test_no_output "set print max-depth unlimited"
+
        gdb_test "print estring" " = \"embedded x\\\\201\\\\202\\\\203\\\\204\""
 
        gdb_test_no_output "guile (set! *pp-ls-encoding* \"UTF-8\")"
index 763fcc6205f0974b18daacd93bb22cc4ecbbd76f..450971cbf1c59b811bca0165b3d4b5b3933891e8 100644 (file)
@@ -23,6 +23,11 @@ typedef struct point
   int y;
 } point_t;
 
+typedef struct
+{
+  point_t the_point;
+} struct_point_t;
+
 typedef union
 {
   int an_int;
@@ -84,6 +89,7 @@ main ()
   point_t &a_point_t_ref = a_point_t;
 #endif
   struct point another_point = { 123, 456 };
+  struct_point_t a_struct_with_point = { a_point_t };
 
   struct_union_t a_struct_with_union;
   /* Fill the union in an endianness-independent way.  */
index ed82ee29fc65a2639a9d11f2846ed2e8333131ee..ea5e958b17d03d87f1deedb6de7db2ddb76c8e1c 100644 (file)
@@ -126,6 +126,7 @@ set default_regexp_dict [dict create \
   "a_point_t_pointer"          $default_pointer_regexp \
   "a_point_t_ref"              "Pretty Point \\(42, 12\\)" \
   "another_point"              "Pretty Point \\(123, 456\\)" \
+  "a_struct_with_point"                "\\{the_point = Pretty Point \\(42, 12\\)\\}" \
   "a_struct_with_union"                "\\{the_union = \\{an_int = 707406378, a_char = 42 '\\*'\\}\\}" \
   "an_enum"                    "ENUM_BAR" \
   "a_string"                   "${default_pointer_regexp} \"hello world\"" \
@@ -722,18 +723,26 @@ proc_with_prefix test_max_depth {} {
     set opts "max_depth=-1"
     with_test_prefix $opts {
        check_format_string "a_struct_with_union" $opts
+       check_format_string "a_point_t" $opts "Pretty Point \\(42, 12\\)"
+       check_format_string "a_struct_with_point" $opts
     }
     set opts "max_depth=0"
     with_test_prefix $opts {
        check_format_string "a_struct_with_union" $opts "\\{\.\.\.\\}"
+       check_format_string "a_point_t" $opts "Pretty Point \\(42, 12\\)"
+       check_format_string "a_struct_with_point" $opts "\\{\.\.\.\\}"
     }
     set opts "max_depth=1"
     with_test_prefix $opts {
        check_format_string "a_struct_with_union" $opts "\\{the_union = \\{\.\.\.\\}\\}"
+       check_format_string "a_point_t" $opts "Pretty Point \\(42, 12\\)"
+       check_format_string "a_struct_with_point" $opts
     }
     set opts "max_depth=2"
     with_test_prefix $opts {
        check_format_string "a_struct_with_union" $opts
+       check_format_string "a_point_t" $opts "Pretty Point \\(42, 12\\)"
+       check_format_string "a_struct_with_point" $opts
     }
 }
 
index 49cefa85673eb5dfe409c89663bc1382e598f0fa..befc48c999ae5e29f89d0532d599ff55ea04466b 100644 (file)
@@ -222,15 +222,15 @@ with_test_prefix "headers=on" {
     with_test_prefix "pretty=off" {
        gdb_print_expr_at_depths "*m1" \
            [list \
-                "\{\\.\\.\\.\}" \
+                "pp_map = \{\\.\\.\\.\}" \
                 "pp_map = \{\\\[\{a = 3, b = 4\}\\\] = \{\\.\\.\\.\}, \\\[\{a = 4, b = 5\}\\\] = \{\\.\\.\\.\}, \\\[\{a = 5, b = 6\}\\\] = \{\\.\\.\\.\}\}" \
                 "pp_map = \{\\\[\{a = 3, b = 4\}\\\] = \{x = 0, y = 1, z = 2\}, \\\[\{a = 4, b = 5\}\\\] = \{x = 3, y = 4, z = 5\}, \\\[\{a = 5, b = 6\}\\\] = \{x = 6, y = 7, z = 8\}\}" \
                ]
 
        gdb_print_expr_at_depths "*mm" \
            [list \
-                "\{\\.\\.\\.\}" \
-                "pp_map_map = \{\\\[$hex \"m1\"\\\] = \{\\.\\.\\.\}, \\\[$hex \"m2\"\\\] = \{\\.\\.\\.\}\}" \
+                "pp_map_map = \{\\.\\.\\.\}" \
+                "pp_map_map = \{\\\[$hex \"m1\"\\\] = pp_map = \{\\.\\.\\.\}, \\\[$hex \"m2\"\\\] = pp_map = \{\\.\\.\\.\}\}" \
                 "pp_map_map = \{\\\[$hex \"m1\"\\\] = pp_map = \{\\\[\{a = 3, b = 4\}\\\] = \{\\.\\.\\.\}, \\\[\{a = 4, b = 5\}\\\] = \{\\.\\.\\.\}, \\\[\{a = 5, b = 6\}\\\] = \{\\.\\.\\.\}\}, \\\[$hex \"m2\"\\\] = pp_map = \{\\\[\{a = 6, b = 7\}\\\] = \{\\.\\.\\.\}, \\\[\{a = 7, b = 8\}\\\] = \{\\.\\.\\.\}, \\\[\{a = 8, b = 9\}\\\] = \{\\.\\.\\.\}\}\}" \
                 "pp_map_map = \{\\\[$hex \"m1\"\\\] = pp_map = \{\\\[\{a = 3, b = 4\}\\\] = \{x = 0, y = 1, z = 2\}, \\\[\{a = 4, b = 5\}\\\] = \{x = 3, y = 4, z = 5\}, \\\[\{a = 5, b = 6\}\\\] = \{x = 6, y = 7, z = 8\}\}, \\\[$hex \"m2\"\\\] = pp_map = \{\\\[\{a = 6, b = 7\}\\\] = \{x = 9, y = 0, z = 1\}, \\\[\{a = 7, b = 8\}\\\] = \{x = 2, y = 3, z = 4\}, \\\[\{a = 8, b = 9\}\\\] = \{x = 5, y = 6, z = 7\}\}\}" \
                ]