https://gcc.gnu.org/g:e656656e711949ef42a7e284f7cf81ca56f37374

commit r15-535-ge656656e711949ef42a7e284f7cf81ca56f37374
Author: David Malcolm <dmalc...@redhat.com>
Date:   Wed May 15 21:22:52 2024 -0400

    diagnostics: use unicode art for interprocedural depth
    
    gcc/testsuite/ChangeLog:
            * gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c: Update expected
            output to use unicode for depth indication.
            * gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c: Likewise.
    
    gcc/ChangeLog:
            * text-art/theme.cc (ascii_theme::get_cppchar): Add
            cell_kind::INTERPROCEDURAL_*.
            (unicode_theme::get_cppchar): Likewise.
            * text-art/theme.h (theme::cell_kind): Likewise.
            * tree-diagnostic-path.cc:
            (thread_event_printer::print_swimlane_for_event_range): Use the
            above to get characters for indicating interprocedural stack
            depth activity, falling back to ascii.
            (selftest::test_interprocedural_path_1): Test with both ascii
            and unicode themes.
            (selftest::test_interprocedural_path_2): Likewise.
            (selftest::test_recursion): Likewise.
    
    Signed-off-by: David Malcolm <dmalc...@redhat.com>

Diff:
---
 .../analyzer/out-of-bounds-diagram-1-emoji.c       |  26 +-
 .../analyzer/out-of-bounds-diagram-1-unicode.c     |  26 +-
 gcc/text-art/theme.cc                              |  30 ++
 gcc/text-art/theme.h                               |  10 +
 gcc/tree-diagnostic-path.cc                        | 381 ++++++++++++++-------
 5 files changed, 331 insertions(+), 142 deletions(-)

diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c 
b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
index 7b4ecf0d6b0c..8d22e4109628 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c
@@ -18,19 +18,19 @@ void int_arr_write_element_after_end_off_by_one(int32_t x)
    arr[10] = x;
    ~~~~~~~~^~~
   event 1 (depth 0)
-    |
-    | int32_t arr[10];
-    |         ^~~
-    |         |
-    |         (1) capacity: 40 bytes
-    |
-    +--> 'int_arr_write_element_after_end_off_by_one': event 2 (depth 1)
-           |
-           |   arr[10] = x;
-           |   ~~~~~~~~^~~
-           |           |
-           |           (2) ⚠️  out-of-bounds write from byte 40 till byte 43 
but 'arr' ends at byte 40
-           |
+    │
+    │ int32_t arr[10];
+    │         ^~~
+    │         |
+    │         (1) capacity: 40 bytes
+    │
+    └──> 'int_arr_write_element_after_end_off_by_one': event 2 (depth 1)
+           │
+           │   arr[10] = x;
+           │   ~~~~~~~~^~~
+           │           |
+           │           (2) ⚠️  out-of-bounds write from byte 40 till byte 43 
but 'arr' ends at byte 40
+           │
    { dg-end-multiline-output "" } */
 
 /* { dg-begin-multiline-output "" }
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c 
b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c
index 71f66ff87c9e..58c4a7bedf34 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-diagram-1-unicode.c
@@ -18,19 +18,19 @@ void int_arr_write_element_after_end_off_by_one(int32_t x)
    arr[10] = x;
    ~~~~~~~~^~~
   event 1 (depth 0)
-    |
-    | int32_t arr[10];
-    |         ^~~
-    |         |
-    |         (1) capacity: 40 bytes
-    |
-    +--> 'int_arr_write_element_after_end_off_by_one': event 2 (depth 1)
-           |
-           |   arr[10] = x;
-           |   ~~~~~~~~^~~
-           |           |
-           |           (2) out-of-bounds write from byte 40 till byte 43 but 
'arr' ends at byte 40
-           |
+    │
+    │ int32_t arr[10];
+    │         ^~~
+    │         |
+    │         (1) capacity: 40 bytes
+    │
+    └──> 'int_arr_write_element_after_end_off_by_one': event 2 (depth 1)
+           │
+           │   arr[10] = x;
+           │   ~~~~~~~~^~~
+           │           |
+           │           (2) out-of-bounds write from byte 40 till byte 43 but 
'arr' ends at byte 40
+           │
    { dg-end-multiline-output "" } */
 
 /* { dg-begin-multiline-output "" }
diff --git a/gcc/text-art/theme.cc b/gcc/text-art/theme.cc
index 4ac0cae92e26..cba4c585c469 100644
--- a/gcc/text-art/theme.cc
+++ b/gcc/text-art/theme.cc
@@ -125,6 +125,21 @@ ascii_theme::get_cppchar (enum cell_kind kind) const
     case cell_kind::Y_ARROW_UP_TAIL:
     case cell_kind::Y_ARROW_DOWN_TAIL:
       return '|';
+
+    case cell_kind::INTERPROCEDURAL_PUSH_FRAME_LEFT:
+      return '+';
+    case cell_kind::INTERPROCEDURAL_PUSH_FRAME_MIDDLE:
+      return '-';
+    case cell_kind::INTERPROCEDURAL_PUSH_FRAME_RIGHT:
+      return '>';
+    case cell_kind::INTERPROCEDURAL_DEPTH_MARKER:
+      return '|';
+    case cell_kind::INTERPROCEDURAL_POP_FRAMES_LEFT:
+      return '<';
+    case cell_kind::INTERPROCEDURAL_POP_FRAMES_MIDDLE:
+      return '-';
+    case cell_kind::INTERPROCEDURAL_POP_FRAMES_RIGHT:
+      return '+';
     }
 }
 
@@ -180,5 +195,20 @@ unicode_theme::get_cppchar (enum cell_kind kind) const
     case cell_kind::Y_ARROW_UP_TAIL:
     case cell_kind::Y_ARROW_DOWN_TAIL:
       return 0x2502; /* "│": U+2502: BOX DRAWINGS LIGHT VERTICAL */
+
+    case cell_kind::INTERPROCEDURAL_PUSH_FRAME_LEFT:
+      return 0x2514; /* "└": U+2514: BOX DRAWINGS LIGHT UP AND RIGHT  */
+    case cell_kind::INTERPROCEDURAL_PUSH_FRAME_MIDDLE:
+      return 0x2500; /* "─": U+2500: BOX DRAWINGS LIGHT HORIZONTAL */
+    case cell_kind::INTERPROCEDURAL_PUSH_FRAME_RIGHT:
+      return '>';
+    case cell_kind::INTERPROCEDURAL_DEPTH_MARKER:
+      return 0x2502; /* "│": U+2502: BOX DRAWINGS LIGHT VERTICAL */
+    case cell_kind::INTERPROCEDURAL_POP_FRAMES_LEFT:
+      return '<';
+    case cell_kind::INTERPROCEDURAL_POP_FRAMES_MIDDLE:
+      return 0x2500; /* "─": U+2500: BOX DRAWINGS LIGHT HORIZONTAL */
+    case cell_kind::INTERPROCEDURAL_POP_FRAMES_RIGHT:
+      return 0x2518; /* "┘": U+2518: BOX DRAWINGS LIGHT UP AND LEFT.  */
     }
 }
diff --git a/gcc/text-art/theme.h b/gcc/text-art/theme.h
index 62845ac8074b..dd50f5a5e416 100644
--- a/gcc/text-art/theme.h
+++ b/gcc/text-art/theme.h
@@ -63,6 +63,16 @@ class theme
     Y_ARROW_UP_TAIL,
     Y_ARROW_DOWN_HEAD,
     Y_ARROW_DOWN_TAIL,
+
+    /* The interprocedural depth indications shown in execution paths
+       with DPF_INLINE_EVENTS.  */
+    INTERPROCEDURAL_PUSH_FRAME_LEFT,   /* e.g. "+".  */
+    INTERPROCEDURAL_PUSH_FRAME_MIDDLE, /* e.g. "-".  */
+    INTERPROCEDURAL_PUSH_FRAME_RIGHT,  /* e.g. ">".  */
+    INTERPROCEDURAL_DEPTH_MARKER,       /* e.g. "|".  */
+    INTERPROCEDURAL_POP_FRAMES_LEFT,   /* e.g. "<".  */
+    INTERPROCEDURAL_POP_FRAMES_MIDDLE, /* e.g. "-".  */
+    INTERPROCEDURAL_POP_FRAMES_RIGHT  /* e.g. "+".  */
   };
 
   virtual ~theme () = default;
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc
index bc90aaf321cc..9ae5191774ec 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/tree-diagnostic-path.cc
@@ -437,6 +437,15 @@ public:
       = colorize_start (pp_show_color (pp), line_color);
     const char *end_line_color = colorize_stop (pp_show_color (pp));
 
+    text_art::ascii_theme fallback_theme;
+    text_art::theme *theme = dc->get_diagram_theme ();
+    if (!theme)
+      theme = &fallback_theme;
+
+    cppchar_t depth_marker_char = theme->get_cppchar
+      (text_art::theme::cell_kind::INTERPROCEDURAL_DEPTH_MARKER);
+    /* e.g. "|".  */
+
     const bool interprocedural_p = m_per_thread_summary.interprocedural_p ();
 
     write_indent (pp, m_cur_indent);
@@ -446,11 +455,21 @@ public:
          {
            gcc_assert (interprocedural_p);
            /* Show pushed stack frame(s).  */
-           const char *push_prefix = "+--> ";
+           cppchar_t left = theme->get_cppchar
+             (text_art::theme::cell_kind::INTERPROCEDURAL_PUSH_FRAME_LEFT);
+           cppchar_t middle = theme->get_cppchar
+             (text_art::theme::cell_kind::INTERPROCEDURAL_PUSH_FRAME_MIDDLE);
+           cppchar_t right = theme->get_cppchar
+             (text_art::theme::cell_kind::INTERPROCEDURAL_PUSH_FRAME_RIGHT);
+           /* e.g. "+--> ".  */
            pp_string (pp, start_line_color);
-           pp_string (pp, push_prefix);
+           pp_unicode_character (pp, left);
+           pp_unicode_character (pp, middle);
+           pp_unicode_character (pp, middle);
+           pp_unicode_character (pp, right);
+           pp_space (pp);
            pp_string (pp, end_line_color);
-           m_cur_indent += strlen (push_prefix);
+           m_cur_indent += 5;
          }
       }
     if (range->m_fndecl)
@@ -473,7 +492,7 @@ public:
       {
        write_indent (pp, m_cur_indent + per_frame_indent);
        pp_string (pp, start_line_color);
-       pp_string (pp, "|");
+       pp_unicode_character (pp, depth_marker_char);
        pp_string (pp, end_line_color);
        pp_newline (pp);
 
@@ -483,7 +502,7 @@ public:
          pretty_printer tmp_pp;
          write_indent (&tmp_pp, m_cur_indent + per_frame_indent);
          pp_string (&tmp_pp, start_line_color);
-         pp_string (&tmp_pp, "|");
+         pp_unicode_character (&tmp_pp, depth_marker_char);
          pp_string (&tmp_pp, end_line_color);
          prefix = xstrdup (pp_formatted_text (&tmp_pp));
        }
@@ -494,7 +513,7 @@ public:
 
        write_indent (pp, m_cur_indent + per_frame_indent);
        pp_string (pp, start_line_color);
-       pp_string (pp, "|");
+       pp_unicode_character (pp, depth_marker_char);
        pp_string (pp, end_line_color);
        pp_newline (pp);
       }
@@ -510,9 +529,15 @@ public:
                /* Show returning from stack frame(s), by printing
                   something like:
                   "                   |\n"
-                  "     <------------ +\n"
+                  "     <-------------+\n"
                   "     |\n".  */
                gcc_assert (interprocedural_p);
+               cppchar_t left = theme->get_cppchar
+                 (text_art::theme::cell_kind::INTERPROCEDURAL_POP_FRAMES_LEFT);
+               cppchar_t middle = theme->get_cppchar
+                 
(text_art::theme::cell_kind::INTERPROCEDURAL_POP_FRAMES_MIDDLE);
+               cppchar_t right = theme->get_cppchar
+                 
(text_art::theme::cell_kind::INTERPROCEDURAL_POP_FRAMES_RIGHT);
                int vbar_for_next_frame
                  = *m_vbar_column_for_depth.get (next_range->m_stack_depth);
 
@@ -520,18 +545,18 @@ public:
                  = vbar_for_next_frame - per_frame_indent;
                write_indent (pp, vbar_for_next_frame);
                pp_string (pp, start_line_color);
-               pp_character (pp, '<');
+               pp_unicode_character (pp, left);
                for (int i = indent_for_next_frame + per_frame_indent;
                     i < m_cur_indent + per_frame_indent - 1; i++)
-                 pp_character (pp, '-');
-               pp_character (pp, '+');
+                 pp_unicode_character (pp, middle);
+               pp_unicode_character (pp, right);
                pp_string (pp, end_line_color);
                pp_newline (pp);
                m_cur_indent = indent_for_next_frame;
 
                write_indent (pp, vbar_for_next_frame);
                pp_string (pp, start_line_color);
-               pp_character (pp, '|');
+               pp_unicode_character (pp, depth_marker_char);
                pp_string (pp, end_line_color);
                pp_newline (pp);
              }
@@ -864,59 +889,119 @@ test_interprocedural_path_1 (pretty_printer *event_pp)
   path_summary summary (path, false);
   ASSERT_EQ (summary.get_num_ranges (), 9);
 
-  test_diagnostic_context dc;
-  print_path_summary_as_text (&summary, &dc, true);
-  ASSERT_STREQ
-    ("  `test': events 1-2 (depth 0)\n"
-     "    |\n"
-     "    | (1): entering `test'\n"
-     "    | (2): calling `make_boxed_int'\n"
-     "    |\n"
-     "    +--> `make_boxed_int': events 3-4 (depth 1)\n"
-     "           |\n"
-     "           | (3): entering `make_boxed_int'\n"
-     "           | (4): calling `wrapped_malloc'\n"
-     "           |\n"
-     "           +--> `wrapped_malloc': events 5-6 (depth 2)\n"
-     "                  |\n"
-     "                  | (5): entering `wrapped_malloc'\n"
-     "                  | (6): calling malloc\n"
-     "                  |\n"
-     "    <-------------+\n"
-     "    |\n"
-     "  `test': events 7-8 (depth 0)\n"
-     "    |\n"
-     "    | (7): returning to `test'\n"
-     "    | (8): calling `free_boxed_int'\n"
-     "    |\n"
-     "    +--> `free_boxed_int': events 9-10 (depth 1)\n"
-     "           |\n"
-     "           | (9): entering `free_boxed_int'\n"
-     "           | (10): calling `wrapped_free'\n"
-     "           |\n"
-     "           +--> `wrapped_free': events 11-12 (depth 2)\n"
-     "                  |\n"
-     "                  | (11): entering `wrapped_free'\n"
-     "                  | (12): calling free\n"
-     "                  |\n"
-     "    <-------------+\n"
-     "    |\n"
-     "  `test': events 13-14 (depth 0)\n"
-     "    |\n"
-     "    | (13): returning to `test'\n"
-     "    | (14): calling `free_boxed_int'\n"
-     "    |\n"
-     "    +--> `free_boxed_int': events 15-16 (depth 1)\n"
-     "           |\n"
-     "           | (15): entering `free_boxed_int'\n"
-     "           | (16): calling `wrapped_free'\n"
-     "           |\n"
-     "           +--> `wrapped_free': events 17-18 (depth 2)\n"
-     "                  |\n"
-     "                  | (17): entering `wrapped_free'\n"
-     "                  | (18): calling free\n"
-     "                  |\n",
-     pp_formatted_text (dc.printer));
+  {
+    test_diagnostic_context dc;
+    dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
+    print_path_summary_as_text (&summary, &dc, true);
+    ASSERT_STREQ
+      ("  `test': events 1-2 (depth 0)\n"
+       "    |\n"
+       "    | (1): entering `test'\n"
+       "    | (2): calling `make_boxed_int'\n"
+       "    |\n"
+       "    +--> `make_boxed_int': events 3-4 (depth 1)\n"
+       "           |\n"
+       "           | (3): entering `make_boxed_int'\n"
+       "           | (4): calling `wrapped_malloc'\n"
+       "           |\n"
+       "           +--> `wrapped_malloc': events 5-6 (depth 2)\n"
+       "                  |\n"
+       "                  | (5): entering `wrapped_malloc'\n"
+       "                  | (6): calling malloc\n"
+       "                  |\n"
+       "    <-------------+\n"
+       "    |\n"
+       "  `test': events 7-8 (depth 0)\n"
+       "    |\n"
+       "    | (7): returning to `test'\n"
+       "    | (8): calling `free_boxed_int'\n"
+       "    |\n"
+       "    +--> `free_boxed_int': events 9-10 (depth 1)\n"
+       "           |\n"
+       "           | (9): entering `free_boxed_int'\n"
+       "           | (10): calling `wrapped_free'\n"
+       "           |\n"
+       "           +--> `wrapped_free': events 11-12 (depth 2)\n"
+       "                  |\n"
+       "                  | (11): entering `wrapped_free'\n"
+       "                  | (12): calling free\n"
+       "                  |\n"
+       "    <-------------+\n"
+       "    |\n"
+       "  `test': events 13-14 (depth 0)\n"
+       "    |\n"
+       "    | (13): returning to `test'\n"
+       "    | (14): calling `free_boxed_int'\n"
+       "    |\n"
+       "    +--> `free_boxed_int': events 15-16 (depth 1)\n"
+       "           |\n"
+       "           | (15): entering `free_boxed_int'\n"
+       "           | (16): calling `wrapped_free'\n"
+       "           |\n"
+       "           +--> `wrapped_free': events 17-18 (depth 2)\n"
+       "                  |\n"
+       "                  | (17): entering `wrapped_free'\n"
+       "                  | (18): calling free\n"
+       "                  |\n",
+       pp_formatted_text (dc.printer));
+  }
+  {
+    test_diagnostic_context dc;
+    dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE);
+    print_path_summary_as_text (&summary, &dc, true);
+    ASSERT_STREQ
+      ("  `test': events 1-2 (depth 0)\n"
+       "    │\n"
+       "    │ (1): entering `test'\n"
+       "    │ (2): calling `make_boxed_int'\n"
+       "    │\n"
+       "    └──> `make_boxed_int': events 3-4 (depth 1)\n"
+       "           │\n"
+       "           │ (3): entering `make_boxed_int'\n"
+       "           │ (4): calling `wrapped_malloc'\n"
+       "           │\n"
+       "           └──> `wrapped_malloc': events 5-6 (depth 2)\n"
+       "                  │\n"
+       "                  │ (5): entering `wrapped_malloc'\n"
+       "                  │ (6): calling malloc\n"
+       "                  │\n"
+       "    <─────────────┘\n"
+       "    │\n"
+       "  `test': events 7-8 (depth 0)\n"
+       "    │\n"
+       "    │ (7): returning to `test'\n"
+       "    │ (8): calling `free_boxed_int'\n"
+       "    │\n"
+       "    └──> `free_boxed_int': events 9-10 (depth 1)\n"
+       "           │\n"
+       "           │ (9): entering `free_boxed_int'\n"
+       "           │ (10): calling `wrapped_free'\n"
+       "           │\n"
+       "           └──> `wrapped_free': events 11-12 (depth 2)\n"
+       "                  │\n"
+       "                  │ (11): entering `wrapped_free'\n"
+       "                  │ (12): calling free\n"
+       "                  │\n"
+       "    <─────────────┘\n"
+       "    │\n"
+       "  `test': events 13-14 (depth 0)\n"
+       "    │\n"
+       "    │ (13): returning to `test'\n"
+       "    │ (14): calling `free_boxed_int'\n"
+       "    │\n"
+       "    └──> `free_boxed_int': events 15-16 (depth 1)\n"
+       "           │\n"
+       "           │ (15): entering `free_boxed_int'\n"
+       "           │ (16): calling `wrapped_free'\n"
+       "           │\n"
+       "           └──> `wrapped_free': events 17-18 (depth 2)\n"
+       "                  │\n"
+       "                  │ (17): entering `wrapped_free'\n"
+       "                  │ (18): calling free\n"
+       "                  │\n",
+       pp_formatted_text (dc.printer));
+  }
+
 }
 
 /* Example where we pop the stack to an intermediate frame, rather than the
@@ -946,35 +1031,70 @@ test_interprocedural_path_2 (pretty_printer *event_pp)
   path_summary summary (path, false);
   ASSERT_EQ (summary.get_num_ranges (), 5);
 
-  test_diagnostic_context dc;
-  print_path_summary_as_text (&summary, &dc, true);
-  ASSERT_STREQ
-    ("  `foo': events 1-2 (depth 0)\n"
-     "    |\n"
-     "    | (1): entering `foo'\n"
-     "    | (2): calling `bar'\n"
-     "    |\n"
-     "    +--> `bar': events 3-4 (depth 1)\n"
-     "           |\n"
-     "           | (3): entering `bar'\n"
-     "           | (4): calling `baz'\n"
-     "           |\n"
-     "           +--> `baz': event 5 (depth 2)\n"
-     "                  |\n"
-     "                  | (5): entering `baz'\n"
-     "                  |\n"
-     "           <------+\n"
-     "           |\n"
-     "         `bar': events 6-7 (depth 1)\n"
-     "           |\n"
-     "           | (6): returning to `bar'\n"
-     "           | (7): calling `baz'\n"
-     "           |\n"
-     "           +--> `baz': event 8 (depth 2)\n"
-     "                  |\n"
-     "                  | (8): entering `baz'\n"
-     "                  |\n",
-     pp_formatted_text (dc.printer));
+  {
+    test_diagnostic_context dc;
+    dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
+    print_path_summary_as_text (&summary, &dc, true);
+    ASSERT_STREQ
+      ("  `foo': events 1-2 (depth 0)\n"
+       "    |\n"
+       "    | (1): entering `foo'\n"
+       "    | (2): calling `bar'\n"
+       "    |\n"
+       "    +--> `bar': events 3-4 (depth 1)\n"
+       "           |\n"
+       "           | (3): entering `bar'\n"
+       "           | (4): calling `baz'\n"
+       "           |\n"
+       "           +--> `baz': event 5 (depth 2)\n"
+       "                  |\n"
+       "                  | (5): entering `baz'\n"
+       "                  |\n"
+       "           <------+\n"
+       "           |\n"
+       "         `bar': events 6-7 (depth 1)\n"
+       "           |\n"
+       "           | (6): returning to `bar'\n"
+       "           | (7): calling `baz'\n"
+       "           |\n"
+       "           +--> `baz': event 8 (depth 2)\n"
+       "                  |\n"
+       "                  | (8): entering `baz'\n"
+       "                  |\n",
+       pp_formatted_text (dc.printer));
+  }
+  {
+    test_diagnostic_context dc;
+    dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE);
+    print_path_summary_as_text (&summary, &dc, true);
+    ASSERT_STREQ
+      ("  `foo': events 1-2 (depth 0)\n"
+       "    │\n"
+       "    │ (1): entering `foo'\n"
+       "    │ (2): calling `bar'\n"
+       "    │\n"
+       "    └──> `bar': events 3-4 (depth 1)\n"
+       "           │\n"
+       "           │ (3): entering `bar'\n"
+       "           │ (4): calling `baz'\n"
+       "           │\n"
+       "           └──> `baz': event 5 (depth 2)\n"
+       "                  │\n"
+       "                  │ (5): entering `baz'\n"
+       "                  │\n"
+       "           <──────┘\n"
+       "           │\n"
+       "         `bar': events 6-7 (depth 1)\n"
+       "           │\n"
+       "           │ (6): returning to `bar'\n"
+       "           │ (7): calling `baz'\n"
+       "           │\n"
+       "           └──> `baz': event 8 (depth 2)\n"
+       "                  │\n"
+       "                  │ (8): entering `baz'\n"
+       "                  │\n",
+       pp_formatted_text (dc.printer));
+  }
 }
 
 /* Verify that print_path_summary is sane in the face of a recursive
@@ -998,29 +1118,58 @@ test_recursion (pretty_printer *event_pp)
   path_summary summary (path, false);
   ASSERT_EQ (summary.get_num_ranges (), 4);
 
-  test_diagnostic_context dc;
-  print_path_summary_as_text (&summary, &dc, true);
-  ASSERT_STREQ
-    ("  `factorial': events 1-2 (depth 0)\n"
-     "    |\n"
-     "    | (1): entering `factorial'\n"
-     "    | (2): calling `factorial'\n"
-     "    |\n"
-     "    +--> `factorial': events 3-4 (depth 1)\n"
-     "           |\n"
-     "           | (3): entering `factorial'\n"
-     "           | (4): calling `factorial'\n"
-     "           |\n"
-     "           +--> `factorial': events 5-6 (depth 2)\n"
-     "                  |\n"
-     "                  | (5): entering `factorial'\n"
-     "                  | (6): calling `factorial'\n"
-     "                  |\n"
-     "                  +--> `factorial': event 7 (depth 3)\n"
-     "                         |\n"
-     "                         | (7): entering `factorial'\n"
-     "                         |\n",
-     pp_formatted_text (dc.printer));
+  {
+    test_diagnostic_context dc;
+    dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_ASCII);
+    print_path_summary_as_text (&summary, &dc, true);
+    ASSERT_STREQ
+      ("  `factorial': events 1-2 (depth 0)\n"
+       "    |\n"
+       "    | (1): entering `factorial'\n"
+       "    | (2): calling `factorial'\n"
+       "    |\n"
+       "    +--> `factorial': events 3-4 (depth 1)\n"
+       "           |\n"
+       "           | (3): entering `factorial'\n"
+       "           | (4): calling `factorial'\n"
+       "           |\n"
+       "           +--> `factorial': events 5-6 (depth 2)\n"
+       "                  |\n"
+       "                  | (5): entering `factorial'\n"
+       "                  | (6): calling `factorial'\n"
+       "                  |\n"
+       "                  +--> `factorial': event 7 (depth 3)\n"
+       "                         |\n"
+       "                         | (7): entering `factorial'\n"
+       "                         |\n",
+       pp_formatted_text (dc.printer));
+  }
+  {
+    test_diagnostic_context dc;
+    dc.set_text_art_charset (DIAGNOSTICS_TEXT_ART_CHARSET_UNICODE);
+    print_path_summary_as_text (&summary, &dc, true);
+    ASSERT_STREQ
+      ("  `factorial': events 1-2 (depth 0)\n"
+       "    │\n"
+       "    │ (1): entering `factorial'\n"
+       "    │ (2): calling `factorial'\n"
+       "    │\n"
+       "    └──> `factorial': events 3-4 (depth 1)\n"
+       "           │\n"
+       "           │ (3): entering `factorial'\n"
+       "           │ (4): calling `factorial'\n"
+       "           │\n"
+       "           └──> `factorial': events 5-6 (depth 2)\n"
+       "                  │\n"
+       "                  │ (5): entering `factorial'\n"
+       "                  │ (6): calling `factorial'\n"
+       "                  │\n"
+       "                  └──> `factorial': event 7 (depth 3)\n"
+       "                         │\n"
+       "                         │ (7): entering `factorial'\n"
+       "                         │\n",
+       pp_formatted_text (dc.printer));
+  }
 }
 
 /* Run all of the selftests within this file.  */

Reply via email to