public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [pushed] diagnostics: handle SGR codes in line_label::m_display_width
@ 2024-05-16  1:29 David Malcolm
  2024-05-16  1:29 ` [pushed] diagnostics: simplify output of purely intraprocedural execution paths David Malcolm
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: David Malcolm @ 2024-05-16  1:29 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r15-532-ga7be993806a90a.

gcc/ChangeLog:
	* diagnostic-show-locus.cc: Define INCLUDE_VECTOR and include
	"text-art/types.h".
	(line_label::line_label): Drop "policy" argument.  Use
	styled_string::calc_canvas_width when computing m_display_width,
	as this skips SGR codes.
	(layout::print_any_labels): Update for line_label ctor change.
	(selftest::test_one_liner_labels_utf8): Update expected text to
	reflect that the labels can fit on one line if we don't get
	confused by SGR colorization codes.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/diagnostic-show-locus.cc | 28 +++++++++++++++++-----------
 1 file changed, 17 insertions(+), 11 deletions(-)

diff --git a/gcc/diagnostic-show-locus.cc b/gcc/diagnostic-show-locus.cc
index ceccc0b793d1..f42006cfe2a1 100644
--- a/gcc/diagnostic-show-locus.cc
+++ b/gcc/diagnostic-show-locus.cc
@@ -19,6 +19,7 @@ along with GCC; see the file COPYING3.  If not see
 <http://www.gnu.org/licenses/>.  */
 
 #include "config.h"
+#define INCLUDE_VECTOR
 #include "system.h"
 #include "coretypes.h"
 #include "version.h"
@@ -31,6 +32,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "selftest.h"
 #include "selftest-diagnostic.h"
 #include "cpplib.h"
+#include "text-art/types.h"
 
 #ifdef HAVE_TERMIOS_H
 # include <termios.h>
@@ -1923,14 +1925,18 @@ struct pod_label_text
 class line_label
 {
 public:
-  line_label (const cpp_char_column_policy &policy,
-	      int state_idx, int column,
+  line_label (int state_idx, int column,
 	      label_text text)
   : m_state_idx (state_idx), m_column (column),
     m_text (std::move (text)), m_label_line (0), m_has_vbar (true)
   {
-    const int bytes = strlen (m_text.m_buffer);
-    m_display_width = cpp_display_width (m_text.m_buffer, bytes, policy);
+    /* Using styled_string rather than cpp_display_width here
+       lets us skip SGR formatting characters for color and URLs.
+       It doesn't handle tabs and unicode escaping, but we don't
+       expect to see either of those in labels.  */
+    text_art::style_manager sm;
+    text_art::styled_string str (sm, m_text.m_buffer);
+    m_display_width = str.calc_canvas_width ();
   }
 
   /* Sorting is primarily by column, then by state index.  */
@@ -1990,7 +1996,7 @@ layout::print_any_labels (linenum_type row)
 	if (text.get () == NULL)
 	  continue;
 
-	labels.safe_push (line_label (m_policy, i, disp_col, std::move (text)));
+	labels.safe_push (line_label (i, disp_col, std::move (text)));
       }
   }
 
@@ -4382,9 +4388,9 @@ test_one_liner_labels_utf8 ()
       ASSERT_STREQ (" <U+1F602>_foo = <U+03C0>_bar.<U+1F602>_field<U+03C0>;\n"
 		    " ^~~~~~~~~~~~~   ~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~\n"
 		    " |               |            |\n"
-		    " |               |            label 2\xcf\x80\n"
-		    " |               label 1\xcf\x80\n"
-		    " label 0\xf0\x9f\x98\x82\n",
+		    " label 0\xf0\x9f\x98\x82"
+		    /* ... */ "       label 1\xcf\x80"
+		    /* ...................*/ "     label 2\xcf\x80\n",
 		    pp_formatted_text (dc.printer));
     }
     {
@@ -4395,9 +4401,9 @@ test_one_liner_labels_utf8 ()
 	(" <f0><9f><98><82>_foo = <cf><80>_bar.<f0><9f><98><82>_field<cf><80>;\n"
 	 " ^~~~~~~~~~~~~~~~~~~~   ~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"
 	 " |                      |            |\n"
-	 " |                      |            label 2\xcf\x80\n"
-	 " |                      label 1\xcf\x80\n"
-	 " label 0\xf0\x9f\x98\x82\n",
+	 " label 0\xf0\x9f\x98\x82"
+	 /* ... */ "              label 1\xcf\x80"
+	 /* ..........................*/ "     label 2\xcf\x80\n",
 	 pp_formatted_text (dc.printer));
     }
   }
-- 
2.26.3


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [pushed] diagnostics: simplify output of purely intraprocedural execution paths
  2024-05-16  1:29 [pushed] diagnostics: handle SGR codes in line_label::m_display_width David Malcolm
@ 2024-05-16  1:29 ` David Malcolm
  2024-05-16  1:29 ` [pushed] diagnostics: add warning emoji to events with VERB_danger David Malcolm
  2024-05-16  1:30 ` [pushed] diagnostics: use unicode art for interprocedural depth David Malcolm
  2 siblings, 0 replies; 4+ messages in thread
From: David Malcolm @ 2024-05-16  1:29 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

Diagnostic path printing was added in r10-5901-g4bc1899b2e883f.  As of
that commit, with -fdiagnostics-path-format=inline-events (the default),
we print a vertical line to the left of the source line numbering,
visualizing the stack depth and interprocedural calls and returns as
indentation changes.

For cases where the events on a thread are purely interprocedural, this
line does nothing except take up space and complicate the output.

This patch adds logic to omit it for such cases, simpifying the output,
and, I believe, improving readability.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r15-533-g3cd267446755ab.

gcc/ChangeLog:
	* diagnostic-path.h: Update leading comment to reflect
	intraprocedural cases.  Fix typo in comment.
	* doc/invoke.texi: Update intraprocedural example.

gcc/testsuite/ChangeLog:
	* c-c++-common/analyzer/allocation-size-multiline-1.c: Update
	expected results for purely intraprocedural path.
	* c-c++-common/analyzer/allocation-size-multiline-2.c: Likewise.
	* c-c++-common/analyzer/allocation-size-multiline-3.c: Likewise.
	* c-c++-common/analyzer/analyzer-verbosity-0.c: Likewise.
	* c-c++-common/analyzer/analyzer-verbosity-1.c: Likewise.
	* c-c++-common/analyzer/analyzer-verbosity-2.c: Likewise.
	* c-c++-common/analyzer/analyzer-verbosity-3.c: Likewise.
	* c-c++-common/analyzer/malloc-macro-inline-events.c: Likewise.
	Doing so for this file requires a rewrite since the paths
	prefixing the "in expansion of macro" lines become the only thing
	on their line and so are no longer pruned by multiline.exp logic
	for pruning extra content on non-blank lines.
	* c-c++-common/analyzer/malloc-paths-9-noexcept.c: Likewise.
	* c-c++-common/analyzer/setjmp-2.c: Likewise.
	* gcc.dg/analyzer/malloc-paths-9.c: Likewise.
	* gcc.dg/analyzer/out-of-bounds-multiline-2.c: Likewise.
	* gcc.dg/plugin/diagnostic-test-paths-2.c: Likewise.

gcc/ChangeLog:
	* tree-diagnostic-path.cc (per_thread_summary::interprocedural_p):
	New.
	(thread_event_printer::print_swimlane_for_event_range): Don't
	indent and print the stack depth line if this thread's events are
	purely intraprocedural.
	(selftest::test_intraprocedural_path): Update expected output.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 gcc/diagnostic-path.h                         |  32 +-
 gcc/doc/invoke.texi                           |  30 +-
 .../analyzer/allocation-size-multiline-1.c    |  68 +-
 .../analyzer/allocation-size-multiline-2.c    |  72 +--
 .../analyzer/allocation-size-multiline-3.c    |  48 +-
 .../analyzer/analyzer-verbosity-0.c           |  40 +-
 .../analyzer/analyzer-verbosity-1.c           |  40 +-
 .../analyzer/analyzer-verbosity-2.c           |  40 +-
 .../analyzer/analyzer-verbosity-3.c           |  40 +-
 .../analyzer/malloc-macro-inline-events.c     |  83 +--
 .../analyzer/malloc-paths-9-noexcept.c        | 604 +++++++++---------
 .../c-c++-common/analyzer/setjmp-2.c          | 140 ++--
 .../gcc.dg/analyzer/malloc-paths-9.c          | 302 +++++----
 .../analyzer/out-of-bounds-multiline-2.c      |  21 +-
 .../gcc.dg/plugin/diagnostic-test-paths-2.c   |  30 +-
 gcc/tree-diagnostic-path.cc                   |  86 ++-
 16 files changed, 799 insertions(+), 877 deletions(-)

diff --git a/gcc/diagnostic-path.h b/gcc/diagnostic-path.h
index fb7abe88ed32..696991c6d736 100644
--- a/gcc/diagnostic-path.h
+++ b/gcc/diagnostic-path.h
@@ -41,22 +41,20 @@ class sarif_object;
         29 |     PyList_Append(list, item);
            |     ^~~~~~~~~~~~~~~~~~~~~~~~~
        'demo': events 1-3
-          |
-          |   25 |   list = PyList_New(0);
-          |      |          ^~~~~~~~~~~~~
-          |      |          |
-          |      |          (1) when 'PyList_New' fails, returning NULL
-          |   26 |
-          |   27 |   for (i = 0; i < count; i++) {
-          |      |   ~~~
-          |      |   |
-          |      |   (2) when 'i < count'
-          |   28 |     item = PyLong_FromLong(random());
-          |   29 |     PyList_Append(list, item);
-          |      |     ~~~~~~~~~~~~~~~~~~~~~~~~~
-          |      |     |
-          |      |     (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
-          |
+        25 |   list = PyList_New(0);
+           |          ^~~~~~~~~~~~~
+           |          |
+           |          (1) when 'PyList_New' fails, returning NULL
+        26 |
+        27 |   for (i = 0; i < count; i++) {
+           |   ~~~
+           |   |
+           |   (2) when 'i < count'
+        28 |     item = PyLong_FromLong(random());
+        29 |     PyList_Append(list, item);
+           |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+           |     |
+           |     (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
 
     The diagnostic-printing code has consolidated the path into a single
     run of events, since all the events are near each other and within the same
@@ -146,7 +144,7 @@ class diagnostic_event
 
   virtual tree get_fndecl () const = 0;
 
-  /* Stack depth, so that consumers can visualizes the interprocedural
+  /* Stack depth, so that consumers can visualize the interprocedural
      calls, returns, and frame nesting.  */
   virtual int get_stack_depth () const = 0;
 
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index ddcd5213f06a..e50c983361fe 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -5571,22 +5571,20 @@ For example, the same events as above might be printed as:
 
 @smallexample
   'test': events 1-3
-    |
-    |   25 |   list = PyList_New(0);
-    |      |          ^~~~~~~~~~~~~
-    |      |          |
-    |      |          (1) when 'PyList_New' fails, returning NULL
-    |   26 |
-    |   27 |   for (i = 0; i < count; i++) @{
-    |      |   ~~~
-    |      |   |
-    |      |   (2) when 'i < count'
-    |   28 |     item = PyLong_FromLong(random());
-    |   29 |     PyList_Append(list, item);
-    |      |     ~~~~~~~~~~~~~~~~~~~~~~~~~
-    |      |     |
-    |      |     (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
-    |
+   25 |   list = PyList_New(0);
+      |          ^~~~~~~~~~~~~
+      |          |
+      |          (1) when 'PyList_New' fails, returning NULL
+   26 |
+   27 |   for (i = 0; i < count; i++) @{
+      |   ~~~
+      |   |
+      |   (2) when 'i < count'
+   28 |     item = PyLong_FromLong(random());
+   29 |     PyList_Append(list, item);
+      |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+      |     |
+      |     (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
 @end smallexample
 
 Interprocedural control flow is shown by grouping the events by stack frame,
diff --git a/gcc/testsuite/c-c++-common/analyzer/allocation-size-multiline-1.c b/gcc/testsuite/c-c++-common/analyzer/allocation-size-multiline-1.c
index de1a49c436e8..bc8319471757 100644
--- a/gcc/testsuite/c-c++-common/analyzer/allocation-size-multiline-1.c
+++ b/gcc/testsuite/c-c++-common/analyzer/allocation-size-multiline-1.c
@@ -12,25 +12,21 @@ void test_constant_1 (void)
    int32_t *ptr = (int32_t *) __builtin_malloc (1);
                               ^~~~~~~~~~~~~~~~~~~~
   'test_constant_1': events 1-2
-    |
-    |   int32_t *ptr = (int32_t *) __builtin_malloc (1);
-    |                              ^~~~~~~~~~~~~~~~~~~~
-    |                              |
-    |                              (1) allocated 1 byte here
-    |                              (2) assigned to 'int32_t *'
-    |
+   int32_t *ptr = (int32_t *) __builtin_malloc (1);
+                              ^~~~~~~~~~~~~~~~~~~~
+                              |
+                              (1) allocated 1 byte here
+                              (2) assigned to 'int32_t *'
    { dg-end-multiline-output "" { target c } } */
 /* { dg-begin-multiline-output "" }
    int32_t *ptr = (int32_t *) __builtin_malloc (1);
                               ~~~~~~~~~~~~~~~~~^~~
   'void test_constant_1()': events 1-2
-    |
-    |   int32_t *ptr = (int32_t *) __builtin_malloc (1);
-    |                              ~~~~~~~~~~~~~~~~~^~~
-    |                                               |
-    |                                               (1) allocated 1 byte here
-    |                                               (2) assigned to 'int32_t*' {aka '{re:long :re?}int*'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
-    |
+   int32_t *ptr = (int32_t *) __builtin_malloc (1);
+                              ~~~~~~~~~~~~~~~~~^~~
+                                               |
+                                               (1) allocated 1 byte here
+                                               (2) assigned to 'int32_t*' {aka '{re:long :re?}int*'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
    { dg-end-multiline-output "" { target c++ } } */
 
 void test_constant_2 (void)
@@ -43,26 +39,22 @@ void test_constant_2 (void)
    int32_t *ptr = (int32_t *) __builtin_malloc (2);
                               ^~~~~~~~~~~~~~~~~~~~
   'test_constant_2': events 1-2
-    |
-    |   int32_t *ptr = (int32_t *) __builtin_malloc (2);
-    |                              ^~~~~~~~~~~~~~~~~~~~
-    |                              |
-    |                              (1) allocated 2 bytes here
-    |                              (2) assigned to 'int32_t *'
-    |
+   int32_t *ptr = (int32_t *) __builtin_malloc (2);
+                              ^~~~~~~~~~~~~~~~~~~~
+                              |
+                              (1) allocated 2 bytes here
+                              (2) assigned to 'int32_t *'
    { dg-end-multiline-output "" { target c } } */
 
 /* { dg-begin-multiline-output "" }
    int32_t *ptr = (int32_t *) __builtin_malloc (2);
                               ~~~~~~~~~~~~~~~~~^~~
   'void test_constant_2()': events 1-2
-    |
-    |   int32_t *ptr = (int32_t *) __builtin_malloc (2);
-    |                              ~~~~~~~~~~~~~~~~~^~~
-    |                                               |
-    |                                               (1) allocated 2 bytes here
-    |                                               (2) assigned to 'int32_t*' {aka '{re:long :re?}int*'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
-    |
+   int32_t *ptr = (int32_t *) __builtin_malloc (2);
+                              ~~~~~~~~~~~~~~~~~^~~
+                                               |
+                                               (1) allocated 2 bytes here
+                                               (2) assigned to 'int32_t*' {aka '{re:long :re?}int*'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
    { dg-end-multiline-output "" { target c++ } } */
 
 void test_symbolic (int n)
@@ -75,22 +67,18 @@ void test_symbolic (int n)
    int32_t *ptr = (int32_t *) __builtin_malloc (n * 2);
                               ^~~~~~~~~~~~~~~~~~~~~~~~
   'test_symbolic': event 1
-    |
-    |   int32_t *ptr = (int32_t *) __builtin_malloc (n * 2);
-    |                              ^~~~~~~~~~~~~~~~~~~~~~~~
-    |                              |
-    |                              (1) allocated 'n * 2' bytes and assigned to 'int32_t *'
-    |
+   int32_t *ptr = (int32_t *) __builtin_malloc (n * 2);
+                              ^~~~~~~~~~~~~~~~~~~~~~~~
+                              |
+                              (1) allocated 'n * 2' bytes and assigned to 'int32_t *'
    { dg-end-multiline-output "" { target c } } */
 
 /* { dg-begin-multiline-output "" }
    int32_t *ptr = (int32_t *) __builtin_malloc (n * 2);
                               ~~~~~~~~~~~~~~~~~^~~~~~~
   'void test_symbolic(int)': event 1
-    |
-    |   int32_t *ptr = (int32_t *) __builtin_malloc (n * 2);
-    |                              ~~~~~~~~~~~~~~~~~^~~~~~~
-    |                                               |
-    |                                               (1) allocated '(n * 2)' bytes and assigned to 'int32_t*' {aka '{re:long :re?}int*'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
-    |
+   int32_t *ptr = (int32_t *) __builtin_malloc (n * 2);
+                              ~~~~~~~~~~~~~~~~~^~~~~~~
+                                               |
+                                               (1) allocated '(n * 2)' bytes and assigned to 'int32_t*' {aka '{re:long :re?}int*'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
    { dg-end-multiline-output "" { target c++ } } */
diff --git a/gcc/testsuite/c-c++-common/analyzer/allocation-size-multiline-2.c b/gcc/testsuite/c-c++-common/analyzer/allocation-size-multiline-2.c
index a5def2764fe6..cfd6b4f6f4f3 100644
--- a/gcc/testsuite/c-c++-common/analyzer/allocation-size-multiline-2.c
+++ b/gcc/testsuite/c-c++-common/analyzer/allocation-size-multiline-2.c
@@ -12,25 +12,21 @@ void test_constant_1 (void)
    int32_t *ptr = (int32_t *) __builtin_alloca (1);
                               ^~~~~~~~~~~~~~~~~~~~
   'test_constant_1': events 1-2
-    |
-    |   int32_t *ptr = (int32_t *) __builtin_alloca (1);
-    |                              ^~~~~~~~~~~~~~~~~~~~
-    |                              |
-    |                              (1) allocated 1 byte here
-    |                              (2) assigned to 'int32_t *'
-    |
+   int32_t *ptr = (int32_t *) __builtin_alloca (1);
+                              ^~~~~~~~~~~~~~~~~~~~
+                              |
+                              (1) allocated 1 byte here
+                              (2) assigned to 'int32_t *'
    { dg-end-multiline-output "" { target c } } */
 /* { dg-begin-multiline-output "" }
    int32_t *ptr = (int32_t *) __builtin_alloca (1);
                               ~~~~~~~~~~~~~~~~~^~~
   'void test_constant_1()': events 1-2
-    |
-    |   int32_t *ptr = (int32_t *) __builtin_alloca (1);
-    |                              ~~~~~~~~~~~~~~~~~^~~
-    |                                               |
-    |                                               (1) allocated 1 byte here
-    |                                               (2) assigned to 'int32_t*' {aka '{re:long :re?}int*'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
-    |
+   int32_t *ptr = (int32_t *) __builtin_alloca (1);
+                              ~~~~~~~~~~~~~~~~~^~~
+                                               |
+                                               (1) allocated 1 byte here
+                                               (2) assigned to 'int32_t*' {aka '{re:long :re?}int*'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
    { dg-end-multiline-output "" { target c++ } } */
 
 void test_constant_2 (void)
@@ -42,25 +38,21 @@ void test_constant_2 (void)
    int32_t *ptr = (int32_t *) __builtin_alloca (2);
                               ^~~~~~~~~~~~~~~~~~~~
   'test_constant_2': events 1-2
-    |
-    |   int32_t *ptr = (int32_t *) __builtin_alloca (2);
-    |                              ^~~~~~~~~~~~~~~~~~~~
-    |                              |
-    |                              (1) allocated 2 bytes here
-    |                              (2) assigned to 'int32_t *'
-    |
+   int32_t *ptr = (int32_t *) __builtin_alloca (2);
+                              ^~~~~~~~~~~~~~~~~~~~
+                              |
+                              (1) allocated 2 bytes here
+                              (2) assigned to 'int32_t *'
    { dg-end-multiline-output "" { target c } } */
 /* { dg-begin-multiline-output "" }
    int32_t *ptr = (int32_t *) __builtin_alloca (2);
                               ~~~~~~~~~~~~~~~~~^~~
   'void test_constant_2()': events 1-2
-    |
-    |   int32_t *ptr = (int32_t *) __builtin_alloca (2);
-    |                              ~~~~~~~~~~~~~~~~~^~~
-    |                                               |
-    |                                               (1) allocated 2 bytes here
-    |                                               (2) assigned to 'int32_t*' {aka '{re:long :re?}int*'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
-    |
+   int32_t *ptr = (int32_t *) __builtin_alloca (2);
+                              ~~~~~~~~~~~~~~~~~^~~
+                                               |
+                                               (1) allocated 2 bytes here
+                                               (2) assigned to 'int32_t*' {aka '{re:long :re?}int*'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
    { dg-end-multiline-output "" { target c++ } } */
 
 void test_symbolic (int n)
@@ -72,25 +64,21 @@ void test_symbolic (int n)
    int32_t *ptr = (int32_t *) __builtin_alloca (n * 2);
                               ^~~~~~~~~~~~~~~~~~~~~~~~
   'test_symbolic': events 1-2
-    |
-    |   int32_t *ptr = (int32_t *) __builtin_alloca (n * 2);
-    |                              ^~~~~~~~~~~~~~~~~~~~~~~~
-    |                              |
-    |                              (1) allocated 'n * 2' bytes here
-    |                              (2) assigned to 'int32_t *'
-    |
+   int32_t *ptr = (int32_t *) __builtin_alloca (n * 2);
+                              ^~~~~~~~~~~~~~~~~~~~~~~~
+                              |
+                              (1) allocated 'n * 2' bytes here
+                              (2) assigned to 'int32_t *'
    { dg-end-multiline-output "" { target c } } */
 /* { dg-begin-multiline-output "" }
    int32_t *ptr = (int32_t *) __builtin_alloca (n * 2);
                               ~~~~~~~~~~~~~~~~~^~~~~~~
   'void test_symbolic(int)': events 1-2
-    |
-    |   int32_t *ptr = (int32_t *) __builtin_alloca (n * 2);
-    |                              ~~~~~~~~~~~~~~~~~^~~~~~~
-    |                                               |
-    |                                               (1) allocated '(n * 2)' bytes here
-    |                                               (2) assigned to 'int32_t*' {aka '{re:long :re?}int*'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
-    |
+   int32_t *ptr = (int32_t *) __builtin_alloca (n * 2);
+                              ~~~~~~~~~~~~~~~~~^~~~~~~
+                                               |
+                                               (1) allocated '(n * 2)' bytes here
+                                               (2) assigned to 'int32_t*' {aka '{re:long :re?}int*'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
    { dg-end-multiline-output "" { target c++ } } */
 
 /* FIXME: am getting a duplicate warning here for some reason
diff --git a/gcc/testsuite/c-c++-common/analyzer/allocation-size-multiline-3.c b/gcc/testsuite/c-c++-common/analyzer/allocation-size-multiline-3.c
index 3cf7fb004240..eeb52192fd44 100644
--- a/gcc/testsuite/c-c++-common/analyzer/allocation-size-multiline-3.c
+++ b/gcc/testsuite/c-c++-common/analyzer/allocation-size-multiline-3.c
@@ -16,25 +16,21 @@ void test_constant_99 (void)
    int32_t *ptr = (int32_t *) alloca (99);
                               ^~~~~~
   'test_constant_99': events 1-2
-    |
-    |   int32_t *ptr = (int32_t *) alloca (99);
-    |                              ^~~~~~
-    |                              |
-    |                              (1) allocated 99 bytes here
-    |                              (2) assigned to 'int32_t *' {aka '{re:long :re?}int *'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
-    |
+   int32_t *ptr = (int32_t *) alloca (99);
+                              ^~~~~~
+                              |
+                              (1) allocated 99 bytes here
+                              (2) assigned to 'int32_t *' {aka '{re:long :re?}int *'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
    { dg-end-multiline-output "" { target c } } */
 /* { dg-begin-multiline-output "" }
    int32_t *ptr = (int32_t *) alloca (99);
                               ^~~~~~
   'void test_constant_99()': events 1-2
-    |
-    |   int32_t *ptr = (int32_t *) alloca (99);
-    |                              ^~~~~~
-    |                              |
-    |                              (1) allocated 99 bytes here
-    |                              (2) assigned to 'int32_t*' {aka '{re:long :re?}int*'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
-    |
+   int32_t *ptr = (int32_t *) alloca (99);
+                              ^~~~~~
+                              |
+                              (1) allocated 99 bytes here
+                              (2) assigned to 'int32_t*' {aka '{re:long :re?}int*'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
    { dg-end-multiline-output "" { target c++ } } */
 
 void test_symbolic (int n)
@@ -46,23 +42,19 @@ void test_symbolic (int n)
    int32_t *ptr = (int32_t *) alloca (n * 2);
                               ^~~~~~
   'test_symbolic': events 1-2
-    |
-    |   int32_t *ptr = (int32_t *) alloca (n * 2);
-    |                              ^~~~~~
-    |                              |
-    |                              (1) allocated 'n * 2' bytes here
-    |                              (2) assigned to 'int32_t *' {aka '{re:long :re?}int *'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
-    |
+   int32_t *ptr = (int32_t *) alloca (n * 2);
+                              ^~~~~~
+                              |
+                              (1) allocated 'n * 2' bytes here
+                              (2) assigned to 'int32_t *' {aka '{re:long :re?}int *'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
    { dg-end-multiline-output "" { target c } } */
 /* { dg-begin-multiline-output "" }
    int32_t *ptr = (int32_t *) alloca (n * 2);
                               ^~~~~~
   'void test_symbolic(int)': events 1-2
-    |
-    |   int32_t *ptr = (int32_t *) alloca (n * 2);
-    |                              ^~~~~~
-    |                              |
-    |                              (1) allocated '(n * 2)' bytes here
-    |                              (2) assigned to 'int32_t*' {aka '{re:long :re?}int*'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
-    |
+   int32_t *ptr = (int32_t *) alloca (n * 2);
+                              ^~~~~~
+                              |
+                              (1) allocated '(n * 2)' bytes here
+                              (2) assigned to 'int32_t*' {aka '{re:long :re?}int*'} here; 'sizeof (int32_t {aka {re:long :re?}int})' is '4'
    { dg-end-multiline-output "" { target c++ } } */
diff --git a/gcc/testsuite/c-c++-common/analyzer/analyzer-verbosity-0.c b/gcc/testsuite/c-c++-common/analyzer/analyzer-verbosity-0.c
index 24fe84deb14f..acc41567f48d 100644
--- a/gcc/testsuite/c-c++-common/analyzer/analyzer-verbosity-0.c
+++ b/gcc/testsuite/c-c++-common/analyzer/analyzer-verbosity-0.c
@@ -227,31 +227,27 @@ void test_3 (void *ptr)
    NN |   free (ptr);
       |   ^~~~~~~~~~
   'test_3': events 1-2
-    |
-    |   NN |   free (ptr);
-    |      |   ^~~~~~~~~~
-    |      |   |
-    |      |   (1) first 'free' here
-    |   NN |   called_by_test_3 ();
-    |   NN |   free (ptr);
-    |      |   ~~~~~~~~~~
-    |      |   |
-    |      |   (2) second 'free' here; first 'free' was at (1)
-    |
+   NN |   free (ptr);
+      |   ^~~~~~~~~~
+      |   |
+      |   (1) first 'free' here
+   NN |   called_by_test_3 ();
+   NN |   free (ptr);
+      |   ~~~~~~~~~~
+      |   |
+      |   (2) second 'free' here; first 'free' was at (1)
   { dg-end-multiline-output "" { target c } } */
 /* { dg-begin-multiline-output "" }
    NN |   free (ptr);
       |   ~~~~~^~~~~
   'void test_3(void*)': events 1-2
-    |
-    |   NN |   free (ptr);
-    |      |   ~~~~~^~~~~
-    |      |        |
-    |      |        (1) first 'free' here
-    |   NN |   called_by_test_3 ();
-    |   NN |   free (ptr);
-    |      |   ~~~~~~~~~~
-    |      |        |
-    |      |        (2) second 'free' here; first 'free' was at (1)
-    |
+   NN |   free (ptr);
+      |   ~~~~~^~~~~
+      |        |
+      |        (1) first 'free' here
+   NN |   called_by_test_3 ();
+   NN |   free (ptr);
+      |   ~~~~~~~~~~
+      |        |
+      |        (2) second 'free' here; first 'free' was at (1)
   { dg-end-multiline-output "" { target c++ } } */
diff --git a/gcc/testsuite/c-c++-common/analyzer/analyzer-verbosity-1.c b/gcc/testsuite/c-c++-common/analyzer/analyzer-verbosity-1.c
index e13437052584..27b885dc9554 100644
--- a/gcc/testsuite/c-c++-common/analyzer/analyzer-verbosity-1.c
+++ b/gcc/testsuite/c-c++-common/analyzer/analyzer-verbosity-1.c
@@ -285,31 +285,27 @@ void test_3 (void *ptr)
    NN |   free (ptr);
       |   ^~~~~~~~~~
   'test_3': events 1-2
-    |
-    |   NN |   free (ptr);
-    |      |   ^~~~~~~~~~
-    |      |   |
-    |      |   (1) first 'free' here
-    |   NN |   called_by_test_3 ();
-    |   NN |   free (ptr);
-    |      |   ~~~~~~~~~~
-    |      |   |
-    |      |   (2) second 'free' here; first 'free' was at (1)
-    |
+   NN |   free (ptr);
+      |   ^~~~~~~~~~
+      |   |
+      |   (1) first 'free' here
+   NN |   called_by_test_3 ();
+   NN |   free (ptr);
+      |   ~~~~~~~~~~
+      |   |
+      |   (2) second 'free' here; first 'free' was at (1)
   { dg-end-multiline-output "" { target c } } */
 /* { dg-begin-multiline-output "" }
    NN |   free (ptr);
       |   ~~~~~^~~~~
   'void test_3(void*)': events 1-2
-    |
-    |   NN |   free (ptr);
-    |      |   ~~~~~^~~~~
-    |      |        |
-    |      |        (1) first 'free' here
-    |   NN |   called_by_test_3 ();
-    |   NN |   free (ptr);
-    |      |   ~~~~~~~~~~
-    |      |        |
-    |      |        (2) second 'free' here; first 'free' was at (1)
-    |
+   NN |   free (ptr);
+      |   ~~~~~^~~~~
+      |        |
+      |        (1) first 'free' here
+   NN |   called_by_test_3 ();
+   NN |   free (ptr);
+      |   ~~~~~~~~~~
+      |        |
+      |        (2) second 'free' here; first 'free' was at (1)
   { dg-end-multiline-output "" { target c++ } } */
diff --git a/gcc/testsuite/c-c++-common/analyzer/analyzer-verbosity-2.c b/gcc/testsuite/c-c++-common/analyzer/analyzer-verbosity-2.c
index 0fd865485df9..d2dc522cc1aa 100644
--- a/gcc/testsuite/c-c++-common/analyzer/analyzer-verbosity-2.c
+++ b/gcc/testsuite/c-c++-common/analyzer/analyzer-verbosity-2.c
@@ -345,31 +345,27 @@ void test_3 (void *ptr)
    NN |   free (ptr);
       |   ^~~~~~~~~~
   'test_3': events 1-2
-    |
-    |   NN |   free (ptr);
-    |      |   ^~~~~~~~~~
-    |      |   |
-    |      |   (1) first 'free' here
-    |   NN |   called_by_test_3 ();
-    |   NN |   free (ptr);
-    |      |   ~~~~~~~~~~
-    |      |   |
-    |      |   (2) second 'free' here; first 'free' was at (1)
-    |
+   NN |   free (ptr);
+      |   ^~~~~~~~~~
+      |   |
+      |   (1) first 'free' here
+   NN |   called_by_test_3 ();
+   NN |   free (ptr);
+      |   ~~~~~~~~~~
+      |   |
+      |   (2) second 'free' here; first 'free' was at (1)
   { dg-end-multiline-output "" { target c } } */
 /* { dg-begin-multiline-output "" }
    NN |   free (ptr);
       |   ~~~~~^~~~~
   'void test_3(void*)': events 1-2
-    |
-    |   NN |   free (ptr);
-    |      |   ~~~~~^~~~~
-    |      |        |
-    |      |        (1) first 'free' here
-    |   NN |   called_by_test_3 ();
-    |   NN |   free (ptr);
-    |      |   ~~~~~~~~~~
-    |      |        |
-    |      |        (2) second 'free' here; first 'free' was at (1)
-    |
+   NN |   free (ptr);
+      |   ~~~~~^~~~~
+      |        |
+      |        (1) first 'free' here
+   NN |   called_by_test_3 ();
+   NN |   free (ptr);
+      |   ~~~~~~~~~~
+      |        |
+      |        (2) second 'free' here; first 'free' was at (1)
   { dg-end-multiline-output "" { target c++ } } */
diff --git a/gcc/testsuite/c-c++-common/analyzer/analyzer-verbosity-3.c b/gcc/testsuite/c-c++-common/analyzer/analyzer-verbosity-3.c
index ac699ec544e1..3661f1fd485b 100644
--- a/gcc/testsuite/c-c++-common/analyzer/analyzer-verbosity-3.c
+++ b/gcc/testsuite/c-c++-common/analyzer/analyzer-verbosity-3.c
@@ -345,31 +345,27 @@ void test_3 (void *ptr)
    NN |   free (ptr);
       |   ^~~~~~~~~~
   'test_3': events 1-2
-    |
-    |   NN |   free (ptr);
-    |      |   ^~~~~~~~~~
-    |      |   |
-    |      |   (1) first 'free' here
-    |   NN |   called_by_test_3 ();
-    |   NN |   free (ptr);
-    |      |   ~~~~~~~~~~
-    |      |   |
-    |      |   (2) second 'free' here; first 'free' was at (1)
-    |
+   NN |   free (ptr);
+      |   ^~~~~~~~~~
+      |   |
+      |   (1) first 'free' here
+   NN |   called_by_test_3 ();
+   NN |   free (ptr);
+      |   ~~~~~~~~~~
+      |   |
+      |   (2) second 'free' here; first 'free' was at (1)
   { dg-end-multiline-output "" { target c } } */
 /* { dg-begin-multiline-output "" }
    NN |   free (ptr);
       |   ~~~~~^~~~~
   'void test_3(void*)': events 1-2
-    |
-    |   NN |   free (ptr);
-    |      |   ~~~~~^~~~~
-    |      |        |
-    |      |        (1) first 'free' here
-    |   NN |   called_by_test_3 ();
-    |   NN |   free (ptr);
-    |      |   ~~~~~~~~~~
-    |      |        |
-    |      |        (2) second 'free' here; first 'free' was at (1)
-    |
+   NN |   free (ptr);
+      |   ~~~~~^~~~~
+      |        |
+      |        (1) first 'free' here
+   NN |   called_by_test_3 ();
+   NN |   free (ptr);
+      |   ~~~~~~~~~~
+      |        |
+      |        (2) second 'free' here; first 'free' was at (1)
   { dg-end-multiline-output "" { target c++ } } */
diff --git a/gcc/testsuite/c-c++-common/analyzer/malloc-macro-inline-events.c b/gcc/testsuite/c-c++-common/analyzer/malloc-macro-inline-events.c
index d00d076b209a..8620bc919a5b 100644
--- a/gcc/testsuite/c-c++-common/analyzer/malloc-macro-inline-events.c
+++ b/gcc/testsuite/c-c++-common/analyzer/malloc-macro-inline-events.c
@@ -17,51 +17,58 @@ void test (void *ptr)
       |                           ^~~~~~~~~
    NN |   WRAPPED_FREE (ptr);
       |   ^~~~~~~~~~~~
-  'test': event 1
-    |
-    |
-    |   NN | #define WRAPPED_FREE(PTR) free(PTR)
-    |      |                           ^~~~~~~~~
-    |      |                           |
-    |      |                           (1) first 'free' here
-    |   NN |   WRAPPED_FREE (ptr);
-    |      |   ^~~~~~~~~~~~
-    |
-  'test': event 2
-    |
-    |
-    |   NN | #define WRAPPED_FREE(PTR) free(PTR)
-    |      |                           ^~~~~~~~~
-    |      |                           |
-    |      |                           (2) second 'free' here; first 'free' was at (1)
-    |   NN |   WRAPPED_FREE (ptr);
-    |      |   ^~~~~~~~~~~~
-    |
      { dg-end-multiline-output "" { target c } } */
   /* { dg-begin-multiline-output "" }
    NN | #define WRAPPED_FREE(PTR) free(PTR)
       |                           ~~~~^~~~~
    NN |   WRAPPED_FREE (ptr);
       |   ^~~~~~~~~~~~
+     { dg-end-multiline-output "" { target c++ } } */
+  /* { dg-begin-multiline-output "" }
+  'test': event 1
+     { dg-end-multiline-output "" { target c } } */
+  /* { dg-begin-multiline-output "" }
   'void test(void*)': event 1
-    |
-    |
-    |   NN | #define WRAPPED_FREE(PTR) free(PTR)
-    |      |                           ~~~~^~~~~
-    |      |                               |
-    |      |                               (1) first 'free' here
-    |   NN |   WRAPPED_FREE (ptr);
-    |      |   ^~~~~~~~~~~~
-    |
+     { dg-end-multiline-output "" { target c++ } } */
+  /* { dg-prune-output "\[^\n\r\]*malloc-macro.h\[^\n\r\]*" } */
+  /* { dg-begin-multiline-output "" }
+   NN | #define WRAPPED_FREE(PTR) free(PTR)
+      |                           ^~~~~~~~~
+      |                           |
+      |                           (1) first 'free' here
+   NN |   WRAPPED_FREE (ptr);
+      |   ^~~~~~~~~~~~
+     { dg-end-multiline-output "" { target c } } */
+  /* { dg-begin-multiline-output "" }
+   NN | #define WRAPPED_FREE(PTR) free(PTR)
+      |                           ~~~~^~~~~
+      |                               |
+      |                               (1) first 'free' here
+   NN |   WRAPPED_FREE (ptr);
+      |   ^~~~~~~~~~~~
+     { dg-end-multiline-output "" { target c++ } } */
+  /* { dg-prune-output "\[^\n\r\]*malloc-macro.h\[^\n\r\]*" } */
+  /* { dg-begin-multiline-output "" }
+  'test': event 2
+     { dg-end-multiline-output "" { target c } } */
+  /* { dg-begin-multiline-output "" }
   'void test(void*)': event 2
-    |
-    |
-    |   NN | #define WRAPPED_FREE(PTR) free(PTR)
-    |      |                           ~~~~^~~~~
-    |      |                               |
-    |      |                               (2) second 'free' here; first 'free' was at (1)
-    |   NN |   WRAPPED_FREE (ptr);
-    |      |   ^~~~~~~~~~~~
-    |
+     { dg-end-multiline-output "" { target c++ } } */
+  /* { dg-prune-output "\[^\n\r\]*malloc-macro.h\[^\n\r\]*" } */
+  /* { dg-begin-multiline-output "" }
+   NN | #define WRAPPED_FREE(PTR) free(PTR)
+      |                           ^~~~~~~~~
+      |                           |
+      |                           (2) second 'free' here; first 'free' was at (1)
+   NN |   WRAPPED_FREE (ptr);
+      |   ^~~~~~~~~~~~
+     { dg-end-multiline-output "" { target c } } */
+  /* { dg-begin-multiline-output "" }
+   NN | #define WRAPPED_FREE(PTR) free(PTR)
+      |                           ~~~~^~~~~
+      |                               |
+      |                               (2) second 'free' here; first 'free' was at (1)
+   NN |   WRAPPED_FREE (ptr);
+      |   ^~~~~~~~~~~~
      { dg-end-multiline-output "" { target c++ } } */
 }
diff --git a/gcc/testsuite/c-c++-common/analyzer/malloc-paths-9-noexcept.c b/gcc/testsuite/c-c++-common/analyzer/malloc-paths-9-noexcept.c
index f914ed6216fa..57d25f436a08 100644
--- a/gcc/testsuite/c-c++-common/analyzer/malloc-paths-9-noexcept.c
+++ b/gcc/testsuite/c-c++-common/analyzer/malloc-paths-9-noexcept.c
@@ -13,39 +13,35 @@ void test_1 (void)
    NN |   free (ptr);
       |   ^~~~~~~~~~
   'test_1': events 1-3
-    |
-    |   NN |   void *ptr = malloc (1024);
-    |      |               ^~~~~~~~~~~~~
-    |      |               |
-    |      |               (1) allocated here
-    |   NN |   free (ptr);
-    |      |   ~~~~~~~~~~   
-    |      |   |
-    |      |   (2) first 'free' here
-    |   NN |   free (ptr);
-    |      |   ~~~~~~~~~~   
-    |      |   |
-    |      |   (3) second 'free' here; first 'free' was at (2)
-    |
+   NN |   void *ptr = malloc (1024);
+      |               ^~~~~~~~~~~~~
+      |               |
+      |               (1) allocated here
+   NN |   free (ptr);
+      |   ~~~~~~~~~~   
+      |   |
+      |   (2) first 'free' here
+   NN |   free (ptr);
+      |   ~~~~~~~~~~   
+      |   |
+      |   (3) second 'free' here; first 'free' was at (2)
    { dg-end-multiline-output "" { target c } } */
 /* { dg-begin-multiline-output "" }
    NN |   free (ptr);
       |   ~~~~~^~~~~
   'void test_1()': events 1-3
-    |
-    |   NN |   void *ptr = malloc (1024);
-    |      |               ~~~~~~~^~~~~~
-    |      |                      |
-    |      |                      (1) allocated here
-    |   NN |   free (ptr);
-    |      |   ~~~~~~~~~~          
-    |      |        |
-    |      |        (2) first 'free' here
-    |   NN |   free (ptr);
-    |      |   ~~~~~~~~~~          
-    |      |        |
-    |      |        (3) second 'free' here; first 'free' was at (2)
-    |
+   NN |   void *ptr = malloc (1024);
+      |               ~~~~~~~^~~~~~
+      |                      |
+      |                      (1) allocated here
+   NN |   free (ptr);
+      |   ~~~~~~~~~~          
+      |        |
+      |        (2) first 'free' here
+   NN |   free (ptr);
+      |   ~~~~~~~~~~          
+      |        |
+      |        (3) second 'free' here; first 'free' was at (2)
    { dg-end-multiline-output "" { target c++ } } */
 
 void test_2 (int x, int y)
@@ -62,59 +58,55 @@ void test_2 (int x, int y)
    NN |     free (ptr);
       |     ^~~~~~~~~~
   'test_2': events 1-7
-    |
-    |   NN |   void *ptr = malloc (1024);
-    |      |               ^~~~~~~~~~~~~
-    |      |               |
-    |      |               (1) allocated here
-    |   NN |   if (x)
-    |      |      ~         
-    |      |      |
-    |      |      (2) following 'true' branch (when 'x != 0')...
-    |   NN |     free (ptr);
-    |      |     ~~~~~~~~~~ 
-    |      |     |
-    |      |     (3) ...to here
-    |      |     (4) first 'free' here
-    |   NN |   if (y)
-    |      |      ~         
-    |      |      |
-    |      |      (5) following 'true' branch (when 'y != 0')...
-    |   NN |     free (ptr);
-    |      |     ~~~~~~~~~~ 
-    |      |     |
-    |      |     (6) ...to here
-    |      |     (7) second 'free' here; first 'free' was at (4)
-    |
+   NN |   void *ptr = malloc (1024);
+      |               ^~~~~~~~~~~~~
+      |               |
+      |               (1) allocated here
+   NN |   if (x)
+      |      ~         
+      |      |
+      |      (2) following 'true' branch (when 'x != 0')...
+   NN |     free (ptr);
+      |     ~~~~~~~~~~ 
+      |     |
+      |     (3) ...to here
+      |     (4) first 'free' here
+   NN |   if (y)
+      |      ~         
+      |      |
+      |      (5) following 'true' branch (when 'y != 0')...
+   NN |     free (ptr);
+      |     ~~~~~~~~~~ 
+      |     |
+      |     (6) ...to here
+      |     (7) second 'free' here; first 'free' was at (4)
    { dg-end-multiline-output "" { target c } } */
 /* { dg-begin-multiline-output "" }
    NN |     free (ptr);
       |     ~~~~~^~~~~
   'void test_2(int, int)': events 1-7
-    |
-    |   NN |   void *ptr = malloc (1024);
-    |      |               ~~~~~~~^~~~~~
-    |      |                      |
-    |      |                      (1) allocated here
-    |   NN |   if (x)
-    |      |   ~~                  
-    |      |   |
-    |      |   (2) following 'true' branch (when 'x != 0')...
-    |   NN |     free (ptr);
-    |      |     ~~~~~~~~~~        
-    |      |          |
-    |      |          (3) ...to here
-    |      |          (4) first 'free' here
-    |   NN |   if (y)
-    |      |   ~~                  
-    |      |   |
-    |      |   (5) following 'true' branch (when 'y != 0')...
-    |   NN |     free (ptr);
-    |      |     ~~~~~~~~~~        
-    |      |          |
-    |      |          (6) ...to here
-    |      |          (7) second 'free' here; first 'free' was at (4)
-    |
+   NN |   void *ptr = malloc (1024);
+      |               ~~~~~~~^~~~~~
+      |                      |
+      |                      (1) allocated here
+   NN |   if (x)
+      |   ~~                  
+      |   |
+      |   (2) following 'true' branch (when 'x != 0')...
+   NN |     free (ptr);
+      |     ~~~~~~~~~~        
+      |          |
+      |          (3) ...to here
+      |          (4) first 'free' here
+   NN |   if (y)
+      |   ~~                  
+      |   |
+      |   (5) following 'true' branch (when 'y != 0')...
+   NN |     free (ptr);
+      |     ~~~~~~~~~~        
+      |          |
+      |          (6) ...to here
+      |          (7) second 'free' here; first 'free' was at (4)
    { dg-end-multiline-output "" { target c++ } } */
 
 /* "leak of 'ptr'.  */
@@ -122,55 +114,51 @@ void test_2 (int x, int y)
    NN | }
       | ^
   'test_2': events 1-6
-    |
-    |   NN |   void *ptr = malloc (1024);
-    |      |               ^~~~~~~~~~~~~
-    |      |               |
-    |      |               (1) allocated here
-    |   NN |   if (x)
-    |      |      ~         
-    |      |      |
-    |      |      (2) following 'false' branch (when 'x == 0')...
-    |   NN |     free (ptr);
-    |   NN |   if (y)
-    |      |      ~         
-    |      |      |
-    |      |      (3) ...to here
-    |      |      (4) following 'false' branch (when 'y == 0')...
-    |   NN |     free (ptr);
-    |   NN | }
-    |      | ~              
-    |      | |
-    |      | (5) ...to here
-    |      | (6) 'ptr' leaks here; was allocated at (1)
-    |
+   NN |   void *ptr = malloc (1024);
+      |               ^~~~~~~~~~~~~
+      |               |
+      |               (1) allocated here
+   NN |   if (x)
+      |      ~         
+      |      |
+      |      (2) following 'false' branch (when 'x == 0')...
+   NN |     free (ptr);
+   NN |   if (y)
+      |      ~         
+      |      |
+      |      (3) ...to here
+      |      (4) following 'false' branch (when 'y == 0')...
+   NN |     free (ptr);
+   NN | }
+      | ~              
+      | |
+      | (5) ...to here
+      | (6) 'ptr' leaks here; was allocated at (1)
    { dg-end-multiline-output "" { target c } } */
 /* { dg-begin-multiline-output "" }
    NN | }
       | ^
   'void test_2(int, int)': events 1-6
-    |
-    |   NN |   void *ptr = malloc (1024);
-    |      |               ~~~~~~~^~~~~~
-    |      |                      |
-    |      |                      (1) allocated here
-    |   NN |   if (x)
-    |      |   ~~                  
-    |      |   |
-    |      |   (2) following 'false' branch (when 'x == 0')...
-    |   NN |     free (ptr);
-    |   NN |   if (y)
-    |      |   ~~                  
-    |      |   |
-    |      |   (3) ...to here
-    |      |   (4) following 'false' branch (when 'y == 0')...
-    |   NN |     free (ptr);
-    |   NN | }
-    |      | ~                     
-    |      | |
-    |      | (5) ...to here
-    |      | (6) 'ptr' leaks here; was allocated at (1)
-    |
+   NN |   void *ptr = malloc (1024);
+      |               ~~~~~~~^~~~~~
+      |                      |
+      |                      (1) allocated here
+   NN |   if (x)
+      |   ~~                  
+      |   |
+      |   (2) following 'false' branch (when 'x == 0')...
+   NN |     free (ptr);
+   NN |   if (y)
+      |   ~~                  
+      |   |
+      |   (3) ...to here
+      |   (4) following 'false' branch (when 'y == 0')...
+   NN |     free (ptr);
+   NN | }
+      | ~                     
+      | |
+      | (5) ...to here
+      | (6) 'ptr' leaks here; was allocated at (1)
    { dg-end-multiline-output "" { target c++ } } */
 
 int test_3 (int x, int y)
@@ -195,31 +183,27 @@ int test_3 (int x, int y)
    NN |   *ptr = 42;
       |   ~~~~~^~~~
   'test_3': events 1-2
-    |
-    |   NN |   int *ptr = (int *)malloc (sizeof (int));
-    |      |                     ^~~~~~~~~~~~~~~~~~~~~
-    |      |                     |
-    |      |                     (1) this call could return NULL
-    |   NN |   *ptr = 42;
-    |      |   ~~~~~~~~~          
-    |      |        |
-    |      |        (2) 'ptr' could be NULL: unchecked value from (1)
-    |
+   NN |   int *ptr = (int *)malloc (sizeof (int));
+      |                     ^~~~~~~~~~~~~~~~~~~~~
+      |                     |
+      |                     (1) this call could return NULL
+   NN |   *ptr = 42;
+      |   ~~~~~~~~~          
+      |        |
+      |        (2) 'ptr' could be NULL: unchecked value from (1)
    { dg-end-multiline-output "" { target c } } */
 /* { dg-begin-multiline-output "" }
    NN |   *ptr = 42;
       |   ~~~~~^~~~
   'int test_3(int, int)': events 1-2
-    |
-    |   NN |   int *ptr = (int *)malloc (sizeof (int));
-    |      |                     ~~~~~~~^~~~~~~~~~~~~~
-    |      |                            |
-    |      |                            (1) this call could return NULL
-    |   NN |   *ptr = 42;
-    |      |   ~~~~~~~~~                 
-    |      |        |
-    |      |        (2) 'ptr' could be NULL: unchecked value from (1)
-    |
+   NN |   int *ptr = (int *)malloc (sizeof (int));
+      |                     ~~~~~~~^~~~~~~~~~~~~~
+      |                            |
+      |                            (1) this call could return NULL
+   NN |   *ptr = 42;
+      |   ~~~~~~~~~                 
+      |        |
+      |        (2) 'ptr' could be NULL: unchecked value from (1)
    { dg-end-multiline-output "" { target c++ } } */
 
 /* "use after 'free' of 'ptr'".  */
@@ -227,59 +211,55 @@ int test_3 (int x, int y)
    NN |   *ptr = 19;
       |   ~~~~~^~~~
   'test_3': events 1-6
-    |
-    |   NN |   int *ptr = (int *)malloc (sizeof (int));
-    |      |                     ^~~~~~~~~~~~~~~~~~~~~
-    |      |                     |
-    |      |                     (1) allocated here
-    |   NN |   *ptr = 42;
-    |      |   ~~~~~~~~~          
-    |      |        |
-    |      |        (2) assuming 'ptr' is non-NULL
-    |   NN |   if (x)
-    |      |      ~               
-    |      |      |
-    |      |      (3) following 'true' branch (when 'x != 0')...
-    |   NN |     free (ptr);
-    |      |     ~~~~~~~~~~       
-    |      |     |
-    |      |     (4) ...to here
-    |      |     (5) freed here
-    |   NN | 
-    |   NN |   *ptr = 19;
-    |      |   ~~~~~~~~~          
-    |      |        |
-    |      |        (6) use after 'free' of 'ptr'; freed at (5)
-    |
+   NN |   int *ptr = (int *)malloc (sizeof (int));
+      |                     ^~~~~~~~~~~~~~~~~~~~~
+      |                     |
+      |                     (1) allocated here
+   NN |   *ptr = 42;
+      |   ~~~~~~~~~          
+      |        |
+      |        (2) assuming 'ptr' is non-NULL
+   NN |   if (x)
+      |      ~               
+      |      |
+      |      (3) following 'true' branch (when 'x != 0')...
+   NN |     free (ptr);
+      |     ~~~~~~~~~~       
+      |     |
+      |     (4) ...to here
+      |     (5) freed here
+   NN | 
+   NN |   *ptr = 19;
+      |   ~~~~~~~~~          
+      |        |
+      |        (6) use after 'free' of 'ptr'; freed at (5)
    { dg-end-multiline-output "" { target c } } */
 /* { dg-begin-multiline-output "" }
    NN |   *ptr = 19;
       |   ~~~~~^~~~
   'int test_3(int, int)': events 1-6
-    |
-    |   NN |   int *ptr = (int *)malloc (sizeof (int));
-    |      |                     ~~~~~~~^~~~~~~~~~~~~~
-    |      |                            |
-    |      |                            (1) allocated here
-    |   NN |   *ptr = 42;
-    |      |   ~~~~~~~~~                 
-    |      |        |
-    |      |        (2) assuming 'ptr' is non-NULL
-    |   NN |   if (x)
-    |      |   ~~                        
-    |      |   |
-    |      |   (3) following 'true' branch (when 'x != 0')...
-    |   NN |     free (ptr);
-    |      |     ~~~~~~~~~~              
-    |      |          |
-    |      |          (4) ...to here
-    |      |          (5) freed here
-    |   NN | 
-    |   NN |   *ptr = 19;
-    |      |   ~~~~~~~~~                 
-    |      |        |
-    |      |        (6) use after 'free' of 'ptr'; freed at (5)
-    |
+   NN |   int *ptr = (int *)malloc (sizeof (int));
+      |                     ~~~~~~~^~~~~~~~~~~~~~
+      |                            |
+      |                            (1) allocated here
+   NN |   *ptr = 42;
+      |   ~~~~~~~~~                 
+      |        |
+      |        (2) assuming 'ptr' is non-NULL
+   NN |   if (x)
+      |   ~~                        
+      |   |
+      |   (3) following 'true' branch (when 'x != 0')...
+   NN |     free (ptr);
+      |     ~~~~~~~~~~              
+      |          |
+      |          (4) ...to here
+      |          (5) freed here
+   NN | 
+   NN |   *ptr = 19;
+      |   ~~~~~~~~~                 
+      |        |
+      |        (6) use after 'free' of 'ptr'; freed at (5)
    { dg-end-multiline-output "" { target c++ } } */
 
 /* "use after 'free' of 'ptr'".  */
@@ -287,79 +267,75 @@ int test_3 (int x, int y)
    NN |   return *ptr;
       |          ^~~~
   'test_3': events 1-8
-    |
-    |   NN |   int *ptr = (int *)malloc (sizeof (int));
-    |      |                     ^~~~~~~~~~~~~~~~~~~~~
-    |      |                     |
-    |      |                     (1) allocated here
-    |   NN |   *ptr = 42;
-    |      |   ~~~~~~~~~          
-    |      |        |
-    |      |        (2) assuming 'ptr' is non-NULL
-    |   NN |   if (x)
-    |      |      ~               
-    |      |      |
-    |      |      (3) following 'false' branch (when 'x == 0')...
-    |......
-    |   NN |   *ptr = 19;
-    |      |   ~~~~~~~~~          
-    |      |        |
-    |      |        (4) ...to here
-    |......
-    |   NN |   if (y)
-    |      |      ~               
-    |      |      |
-    |      |      (5) following 'true' branch (when 'y != 0')...
-    |   NN |     free (ptr);
-    |      |     ~~~~~~~~~~       
-    |      |     |
-    |      |     (6) ...to here
-    |      |     (7) freed here
-    |   NN |      
-    |   NN |   return *ptr;
-    |      |          ~~~~        
-    |      |          |
-    |      |          (8) use after 'free' of 'ptr'; freed at (7)
-    |
+   NN |   int *ptr = (int *)malloc (sizeof (int));
+      |                     ^~~~~~~~~~~~~~~~~~~~~
+      |                     |
+      |                     (1) allocated here
+   NN |   *ptr = 42;
+      |   ~~~~~~~~~          
+      |        |
+      |        (2) assuming 'ptr' is non-NULL
+   NN |   if (x)
+      |      ~               
+      |      |
+      |      (3) following 'false' branch (when 'x == 0')...
+......
+   NN |   *ptr = 19;
+      |   ~~~~~~~~~          
+      |        |
+      |        (4) ...to here
+......
+   NN |   if (y)
+      |      ~               
+      |      |
+      |      (5) following 'true' branch (when 'y != 0')...
+   NN |     free (ptr);
+      |     ~~~~~~~~~~       
+      |     |
+      |     (6) ...to here
+      |     (7) freed here
+   NN |      
+   NN |   return *ptr;
+      |          ~~~~        
+      |          |
+      |          (8) use after 'free' of 'ptr'; freed at (7)
    { dg-end-multiline-output "" { target c } } */
 /* { dg-begin-multiline-output "" }
    NN |   return *ptr;
       |           ^~~
   'int test_3(int, int)': events 1-8
-    |
-    |   NN |   int *ptr = (int *)malloc (sizeof (int));
-    |      |                     ~~~~~~~^~~~~~~~~~~~~~
-    |      |                            |
-    |      |                            (1) allocated here
-    |   NN |   *ptr = 42;
-    |      |   ~~~~~~~~~                 
-    |      |        |
-    |      |        (2) assuming 'ptr' is non-NULL
-    |   NN |   if (x)
-    |      |   ~~                        
-    |      |   |
-    |      |   (3) following 'false' branch (when 'x == 0')...
-    |......
-    |   NN |   *ptr = 19;
-    |      |   ~~~~~~~~~                 
-    |      |        |
-    |      |        (4) ...to here
-    |......
-    |   NN |   if (y)
-    |      |   ~~                        
-    |      |   |
-    |      |   (5) following 'true' branch (when 'y != 0')...
-    |   NN |     free (ptr);
-    |      |     ~~~~~~~~~~              
-    |      |          |
-    |      |          (6) ...to here
-    |      |          (7) freed here
-    |   NN |      
-    |   NN |   return *ptr;
-    |      |           ~~~               
-    |      |           |
-    |      |           (8) use after 'free' of 'ptr'; freed at (7)
-    |
+   NN |   int *ptr = (int *)malloc (sizeof (int));
+      |                     ~~~~~~~^~~~~~~~~~~~~~
+      |                            |
+      |                            (1) allocated here
+   NN |   *ptr = 42;
+      |   ~~~~~~~~~                 
+      |        |
+      |        (2) assuming 'ptr' is non-NULL
+   NN |   if (x)
+      |   ~~                        
+      |   |
+      |   (3) following 'false' branch (when 'x == 0')...
+......
+   NN |   *ptr = 19;
+      |   ~~~~~~~~~                 
+      |        |
+      |        (4) ...to here
+......
+   NN |   if (y)
+      |   ~~                        
+      |   |
+      |   (5) following 'true' branch (when 'y != 0')...
+   NN |     free (ptr);
+      |     ~~~~~~~~~~              
+      |          |
+      |          (6) ...to here
+      |          (7) freed here
+   NN |      
+   NN |   return *ptr;
+      |           ~~~               
+      |           |
+      |           (8) use after 'free' of 'ptr'; freed at (7)
    { dg-end-multiline-output "" { target c++ } } */
 
 /* "leak of 'ptr'".  */
@@ -367,69 +343,65 @@ int test_3 (int x, int y)
    NN |   return *ptr;
       |          ^~~~
   'test_3': events 1-7
-    |
-    |   NN |   int *ptr = (int *)malloc (sizeof (int));
-    |      |                     ^~~~~~~~~~~~~~~~~~~~~
-    |      |                     |
-    |      |                     (1) allocated here
-    |   NN |   *ptr = 42;
-    |      |   ~~~~~~~~~          
-    |      |        |
-    |      |        (2) assuming 'ptr' is non-NULL
-    |   NN |   if (x)
-    |      |      ~               
-    |      |      |
-    |      |      (3) following 'false' branch (when 'x == 0')...
-    |......
-    |   NN |   *ptr = 19;
-    |      |   ~~~~~~~~~          
-    |      |        |
-    |      |        (4) ...to here
-    |......
-    |   NN |   if (y)
-    |      |      ~               
-    |      |      |
-    |      |      (5) following 'false' branch (when 'y == 0')...
-    |......
-    |   NN |   return *ptr;
-    |      |          ~~~~        
-    |      |          |
-    |      |          (6) ...to here
-    |      |          (7) 'ptr' leaks here; was allocated at (1)
-    |
+   NN |   int *ptr = (int *)malloc (sizeof (int));
+      |                     ^~~~~~~~~~~~~~~~~~~~~
+      |                     |
+      |                     (1) allocated here
+   NN |   *ptr = 42;
+      |   ~~~~~~~~~          
+      |        |
+      |        (2) assuming 'ptr' is non-NULL
+   NN |   if (x)
+      |      ~               
+      |      |
+      |      (3) following 'false' branch (when 'x == 0')...
+......
+   NN |   *ptr = 19;
+      |   ~~~~~~~~~          
+      |        |
+      |        (4) ...to here
+......
+   NN |   if (y)
+      |      ~               
+      |      |
+      |      (5) following 'false' branch (when 'y == 0')...
+......
+   NN |   return *ptr;
+      |          ~~~~        
+      |          |
+      |          (6) ...to here
+      |          (7) 'ptr' leaks here; was allocated at (1)
    { dg-end-multiline-output "" { target c } } */
 /* { dg-begin-multiline-output "" }
    NN |   return *ptr;
       |           ^~~
   'int test_3(int, int)': events 1-7
-    |
-    |   NN |   int *ptr = (int *)malloc (sizeof (int));
-    |      |                     ~~~~~~~^~~~~~~~~~~~~~
-    |      |                            |
-    |      |                            (1) allocated here
-    |   NN |   *ptr = 42;
-    |      |   ~~~~~~~~~                 
-    |      |        |
-    |      |        (2) assuming 'ptr' is non-NULL
-    |   NN |   if (x)
-    |      |   ~~                        
-    |      |   |
-    |      |   (3) following 'false' branch (when 'x == 0')...
-    |......
-    |   NN |   *ptr = 19;
-    |      |   ~~~~~~~~~                 
-    |      |        |
-    |      |        (4) ...to here
-    |......
-    |   NN |   if (y)
-    |      |   ~~                        
-    |      |   |
-    |      |   (5) following 'false' branch (when 'y == 0')...
-    |......
-    |   NN |   return *ptr;
-    |      |           ~~~               
-    |      |           |
-    |      |           (6) ...to here
-    |      |           (7) 'ptr' leaks here; was allocated at (1)
-    |
+   NN |   int *ptr = (int *)malloc (sizeof (int));
+      |                     ~~~~~~~^~~~~~~~~~~~~~
+      |                            |
+      |                            (1) allocated here
+   NN |   *ptr = 42;
+      |   ~~~~~~~~~                 
+      |        |
+      |        (2) assuming 'ptr' is non-NULL
+   NN |   if (x)
+      |   ~~                        
+      |   |
+      |   (3) following 'false' branch (when 'x == 0')...
+......
+   NN |   *ptr = 19;
+      |   ~~~~~~~~~                 
+      |        |
+      |        (4) ...to here
+......
+   NN |   if (y)
+      |   ~~                        
+      |   |
+      |   (5) following 'false' branch (when 'y == 0')...
+......
+   NN |   return *ptr;
+      |           ~~~               
+      |           |
+      |           (6) ...to here
+      |           (7) 'ptr' leaks here; was allocated at (1)
    { dg-end-multiline-output "" { target c++ } } */
diff --git a/gcc/testsuite/c-c++-common/analyzer/setjmp-2.c b/gcc/testsuite/c-c++-common/analyzer/setjmp-2.c
index 731a17293fc7..264764551d2a 100644
--- a/gcc/testsuite/c-c++-common/analyzer/setjmp-2.c
+++ b/gcc/testsuite/c-c++-common/analyzer/setjmp-2.c
@@ -39,95 +39,79 @@ void test_2 (void)
    NN |       __analyzer_dump_path ();
       |       ^~~~~~~~~~~~~~~~~~~~~~~
   'test_2': event 1
-    |
-    |   NN |   i = SETJMP(env);
-    |      |       ^~~~~~
-    |      |       |
-    |      |       (1) 'setjmp' called here
-    |
+   NN |   i = SETJMP(env);
+      |       ^~~~~~
+      |       |
+      |       (1) 'setjmp' called here
   'test_2': events 2-4
-    |
-    |   NN |   if (i != 0)
-    |      |      ^
-    |      |      |
-    |      |      (2) following 'false' branch (when 'i == 0')...
-    |......
-    |   NN |     longjmp (env, 1);
-    |      |     ~~~~~~~~~~~~~~~~
-    |      |     |
-    |      |     (3) ...to here
-    |      |     (4) rewinding within 'test_2' from 'longjmp'...
-    |
+   NN |   if (i != 0)
+      |      ^
+      |      |
+      |      (2) following 'false' branch (when 'i == 0')...
+......
+   NN |     longjmp (env, 1);
+      |     ~~~~~~~~~~~~~~~~
+      |     |
+      |     (3) ...to here
+      |     (4) rewinding within 'test_2' from 'longjmp'...
   'test_2': event 5
-    |
-    |   NN |   i = SETJMP(env);
-    |      |       ^~~~~~
-    |      |       |
-    |      |       (5) ...to 'setjmp' (saved at (1))
-    |
+   NN |   i = SETJMP(env);
+      |       ^~~~~~
+      |       |
+      |       (5) ...to 'setjmp' (saved at (1))
   'test_2': events 6-8
-    |
-    |   NN |   if (i != 0)
-    |      |      ^
-    |      |      |
-    |      |      (6) following 'true' branch (when 'i != 0')...
-    |   NN |     {
-    |   NN |       foo (2);
-    |      |       ~~~~~~~
-    |      |       |
-    |      |       (7) ...to here
-    |   NN |       __analyzer_dump_path ();
-    |      |       ~~~~~~~~~~~~~~~~~~~~~~~
-    |      |       |
-    |      |       (8) here
-    |
+   NN |   if (i != 0)
+      |      ^
+      |      |
+      |      (6) following 'true' branch (when 'i != 0')...
+   NN |     {
+   NN |       foo (2);
+      |       ~~~~~~~
+      |       |
+      |       (7) ...to here
+   NN |       __analyzer_dump_path ();
+      |       ~~~~~~~~~~~~~~~~~~~~~~~
+      |       |
+      |       (8) here
     { dg-end-multiline-output "" { target c } } */
 /* { dg-begin-multiline-output "" }
    NN |       __analyzer_dump_path ();
       |       ~~~~~~~~~~~~~~~~~~~~~^~
   'void test_2()': event 1
-    |
-    |   NN |   i = SETJMP(env);
-    |      |       ^~~~~~
-    |      |       |
-    |      |       (1) 'setjmp' called here
-    |
+   NN |   i = SETJMP(env);
+      |       ^~~~~~
+      |       |
+      |       (1) 'setjmp' called here
   'void test_2()': events 2-4
-    |
-    |   NN |   if (i != 0)
-    |      |   ^~
-    |      |   |
-    |      |   (2) following 'false' branch (when 'i == 0')...
-    |......
-    |   NN |     longjmp (env, 1);
-    |      |     ~~~~~~~~~~~~~~~~
-    |      |             |
-    |      |             (3) ...to here
-    |      |             (4) rewinding within 'test_2' from 'longjmp'...
-    |
+   NN |   if (i != 0)
+      |   ^~
+      |   |
+      |   (2) following 'false' branch (when 'i == 0')...
+......
+   NN |     longjmp (env, 1);
+      |     ~~~~~~~~~~~~~~~~
+      |             |
+      |             (3) ...to here
+      |             (4) rewinding within 'test_2' from 'longjmp'...
   'void test_2()': event 5
-    |
-    |   NN |   i = SETJMP(env);
-    |      |       ^~~~~~
-    |      |       |
-    |      |       (5) ...to 'setjmp' (saved at (1))
-    |
+   NN |   i = SETJMP(env);
+      |       ^~~~~~
+      |       |
+      |       (5) ...to 'setjmp' (saved at (1))
   'void test_2()': events 6-8
-    |
-    |   NN |   if (i != 0)
-    |      |   ^~
-    |      |   |
-    |      |   (6) following 'true' branch (when 'i != 0')...
-    |   NN |     {
-    |   NN |       foo (2);
-    |      |       ~~~~~~~
-    |      |           |
-    |      |           (7) ...to here
-    |   NN |       __analyzer_dump_path ();
-    |      |       ~~~~~~~~~~~~~~~~~~~~~~~
-    |      |                            |
-    |      |                            (8) here
-    |
+   NN |   if (i != 0)
+      |   ^~
+      |   |
+      |   (6) following 'true' branch (when 'i != 0')...
+   NN |     {
+   NN |       foo (2);
+      |       ~~~~~~~
+      |           |
+      |           (7) ...to here
+   NN |       __analyzer_dump_path ();
+      |       ~~~~~~~~~~~~~~~~~~~~~~~
+      |                            |
+      |                            (8) here
     { dg-end-multiline-output "" { target c++ } } */
 
 void test_3 (void)
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c b/gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c
index 83eec292e85d..a832b084738e 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c
@@ -15,20 +15,18 @@ void test_1 (void)
    NN |   free (ptr);
       |   ^~~~~~~~~~
   'test_1': events 1-3
-    |
-    |   NN |   void *ptr = malloc (1024);
-    |      |               ^~~~~~~~~~~~~
-    |      |               |
-    |      |               (1) allocated here
-    |   NN |   free (ptr);
-    |      |   ~~~~~~~~~~   
-    |      |   |
-    |      |   (2) first 'free' here
-    |   NN |   free (ptr);
-    |      |   ~~~~~~~~~~   
-    |      |   |
-    |      |   (3) second 'free' here; first 'free' was at (2)
-    |
+   NN |   void *ptr = malloc (1024);
+      |               ^~~~~~~~~~~~~
+      |               |
+      |               (1) allocated here
+   NN |   free (ptr);
+      |   ~~~~~~~~~~   
+      |   |
+      |   (2) first 'free' here
+   NN |   free (ptr);
+      |   ~~~~~~~~~~   
+      |   |
+      |   (3) second 'free' here; first 'free' was at (2)
    { dg-end-multiline-output "" } */
 
 void test_2 (int x, int y)
@@ -45,30 +43,28 @@ void test_2 (int x, int y)
    NN |     free (ptr);
       |     ^~~~~~~~~~
   'test_2': events 1-7
-    |
-    |   NN |   void *ptr = malloc (1024);
-    |      |               ^~~~~~~~~~~~~
-    |      |               |
-    |      |               (1) allocated here
-    |   NN |   if (x)
-    |      |      ~         
-    |      |      |
-    |      |      (2) following 'true' branch (when 'x != 0')...
-    |   NN |     free (ptr);
-    |      |     ~~~~~~~~~~ 
-    |      |     |
-    |      |     (3) ...to here
-    |      |     (4) first 'free' here
-    |   NN |   if (y)
-    |      |      ~         
-    |      |      |
-    |      |      (5) following 'true' branch (when 'y != 0')...
-    |   NN |     free (ptr);
-    |      |     ~~~~~~~~~~ 
-    |      |     |
-    |      |     (6) ...to here
-    |      |     (7) second 'free' here; first 'free' was at (4)
-    |
+   NN |   void *ptr = malloc (1024);
+      |               ^~~~~~~~~~~~~
+      |               |
+      |               (1) allocated here
+   NN |   if (x)
+      |      ~         
+      |      |
+      |      (2) following 'true' branch (when 'x != 0')...
+   NN |     free (ptr);
+      |     ~~~~~~~~~~ 
+      |     |
+      |     (3) ...to here
+      |     (4) first 'free' here
+   NN |   if (y)
+      |      ~         
+      |      |
+      |      (5) following 'true' branch (when 'y != 0')...
+   NN |     free (ptr);
+      |     ~~~~~~~~~~ 
+      |     |
+      |     (6) ...to here
+      |     (7) second 'free' here; first 'free' was at (4)
    { dg-end-multiline-output "" } */
 
 /* "leak of 'ptr'.  */
@@ -76,28 +72,26 @@ void test_2 (int x, int y)
    NN | }
       | ^
   'test_2': events 1-6
-    |
-    |   NN |   void *ptr = malloc (1024);
-    |      |               ^~~~~~~~~~~~~
-    |      |               |
-    |      |               (1) allocated here
-    |   NN |   if (x)
-    |      |      ~         
-    |      |      |
-    |      |      (2) following 'false' branch (when 'x == 0')...
-    |   NN |     free (ptr);
-    |   NN |   if (y)
-    |      |      ~         
-    |      |      |
-    |      |      (3) ...to here
-    |      |      (4) following 'false' branch (when 'y == 0')...
-    |   NN |     free (ptr);
-    |   NN | }
-    |      | ~              
-    |      | |
-    |      | (5) ...to here
-    |      | (6) 'ptr' leaks here; was allocated at (1)
-    |
+   NN |   void *ptr = malloc (1024);
+      |               ^~~~~~~~~~~~~
+      |               |
+      |               (1) allocated here
+   NN |   if (x)
+      |      ~         
+      |      |
+      |      (2) following 'false' branch (when 'x == 0')...
+   NN |     free (ptr);
+   NN |   if (y)
+      |      ~         
+      |      |
+      |      (3) ...to here
+      |      (4) following 'false' branch (when 'y == 0')...
+   NN |     free (ptr);
+   NN | }
+      | ~              
+      | |
+      | (5) ...to here
+      | (6) 'ptr' leaks here; was allocated at (1)
    { dg-end-multiline-output "" } */
 
 int test_3 (int x, int y)
@@ -122,16 +116,14 @@ int test_3 (int x, int y)
    NN |   *ptr = 42;
       |   ~~~~~^~~~
   'test_3': events 1-2
-    |
-    |   NN |   int *ptr = (int *)malloc (sizeof (int));
-    |      |                     ^~~~~~~~~~~~~~~~~~~~~
-    |      |                     |
-    |      |                     (1) this call could return NULL
-    |   NN |   *ptr = 42;
-    |      |   ~~~~~~~~~          
-    |      |        |
-    |      |        (2) 'ptr' could be NULL: unchecked value from (1)
-    |
+   NN |   int *ptr = (int *)malloc (sizeof (int));
+      |                     ^~~~~~~~~~~~~~~~~~~~~
+      |                     |
+      |                     (1) this call could return NULL
+   NN |   *ptr = 42;
+      |   ~~~~~~~~~          
+      |        |
+      |        (2) 'ptr' could be NULL: unchecked value from (1)
    { dg-end-multiline-output "" } */
 
 /* "use after 'free' of 'ptr'".  */
@@ -139,30 +131,28 @@ int test_3 (int x, int y)
    NN |   *ptr = 19;
       |   ~~~~~^~~~
   'test_3': events 1-6
-    |
-    |   NN |   int *ptr = (int *)malloc (sizeof (int));
-    |      |                     ^~~~~~~~~~~~~~~~~~~~~
-    |      |                     |
-    |      |                     (1) allocated here
-    |   NN |   *ptr = 42;
-    |      |   ~~~~~~~~~          
-    |      |        |
-    |      |        (2) assuming 'ptr' is non-NULL
-    |   NN |   if (x)
-    |      |      ~               
-    |      |      |
-    |      |      (3) following 'true' branch (when 'x != 0')...
-    |   NN |     free (ptr);
-    |      |     ~~~~~~~~~~       
-    |      |     |
-    |      |     (4) ...to here
-    |      |     (5) freed here
-    |   NN | 
-    |   NN |   *ptr = 19;
-    |      |   ~~~~~~~~~          
-    |      |        |
-    |      |        (6) use after 'free' of 'ptr'; freed at (5)
-    |
+   NN |   int *ptr = (int *)malloc (sizeof (int));
+      |                     ^~~~~~~~~~~~~~~~~~~~~
+      |                     |
+      |                     (1) allocated here
+   NN |   *ptr = 42;
+      |   ~~~~~~~~~          
+      |        |
+      |        (2) assuming 'ptr' is non-NULL
+   NN |   if (x)
+      |      ~               
+      |      |
+      |      (3) following 'true' branch (when 'x != 0')...
+   NN |     free (ptr);
+      |     ~~~~~~~~~~       
+      |     |
+      |     (4) ...to here
+      |     (5) freed here
+   NN | 
+   NN |   *ptr = 19;
+      |   ~~~~~~~~~          
+      |        |
+      |        (6) use after 'free' of 'ptr'; freed at (5)
    { dg-end-multiline-output "" } */
 
 /* "use after 'free' of 'ptr'".  */
@@ -170,40 +160,38 @@ int test_3 (int x, int y)
    NN |   return *ptr;
       |          ^~~~
   'test_3': events 1-8
-    |
-    |   NN |   int *ptr = (int *)malloc (sizeof (int));
-    |      |                     ^~~~~~~~~~~~~~~~~~~~~
-    |      |                     |
-    |      |                     (1) allocated here
-    |   NN |   *ptr = 42;
-    |      |   ~~~~~~~~~          
-    |      |        |
-    |      |        (2) assuming 'ptr' is non-NULL
-    |   NN |   if (x)
-    |      |      ~               
-    |      |      |
-    |      |      (3) following 'false' branch (when 'x == 0')...
-    |......
-    |   NN |   *ptr = 19;
-    |      |   ~~~~~~~~~          
-    |      |        |
-    |      |        (4) ...to here
-    |......
-    |   NN |   if (y)
-    |      |      ~               
-    |      |      |
-    |      |      (5) following 'true' branch (when 'y != 0')...
-    |   NN |     free (ptr);
-    |      |     ~~~~~~~~~~       
-    |      |     |
-    |      |     (6) ...to here
-    |      |     (7) freed here
-    |   NN |      
-    |   NN |   return *ptr;
-    |      |          ~~~~        
-    |      |          |
-    |      |          (8) use after 'free' of 'ptr'; freed at (7)
-    |
+   NN |   int *ptr = (int *)malloc (sizeof (int));
+      |                     ^~~~~~~~~~~~~~~~~~~~~
+      |                     |
+      |                     (1) allocated here
+   NN |   *ptr = 42;
+      |   ~~~~~~~~~          
+      |        |
+      |        (2) assuming 'ptr' is non-NULL
+   NN |   if (x)
+      |      ~               
+      |      |
+      |      (3) following 'false' branch (when 'x == 0')...
+......
+   NN |   *ptr = 19;
+      |   ~~~~~~~~~          
+      |        |
+      |        (4) ...to here
+......
+   NN |   if (y)
+      |      ~               
+      |      |
+      |      (5) following 'true' branch (when 'y != 0')...
+   NN |     free (ptr);
+      |     ~~~~~~~~~~       
+      |     |
+      |     (6) ...to here
+      |     (7) freed here
+   NN |      
+   NN |   return *ptr;
+      |          ~~~~        
+      |          |
+      |          (8) use after 'free' of 'ptr'; freed at (7)
    { dg-end-multiline-output "" } */
 
 /* "leak of 'ptr'".  */
@@ -211,34 +199,32 @@ int test_3 (int x, int y)
    NN |   return *ptr;
       |          ^~~~
   'test_3': events 1-7
-    |
-    |   NN |   int *ptr = (int *)malloc (sizeof (int));
-    |      |                     ^~~~~~~~~~~~~~~~~~~~~
-    |      |                     |
-    |      |                     (1) allocated here
-    |   NN |   *ptr = 42;
-    |      |   ~~~~~~~~~          
-    |      |        |
-    |      |        (2) assuming 'ptr' is non-NULL
-    |   NN |   if (x)
-    |      |      ~               
-    |      |      |
-    |      |      (3) following 'false' branch (when 'x == 0')...
-    |......
-    |   NN |   *ptr = 19;
-    |      |   ~~~~~~~~~          
-    |      |        |
-    |      |        (4) ...to here
-    |......
-    |   NN |   if (y)
-    |      |      ~               
-    |      |      |
-    |      |      (5) following 'false' branch (when 'y == 0')...
-    |......
-    |   NN |   return *ptr;
-    |      |          ~~~~        
-    |      |          |
-    |      |          (6) ...to here
-    |      |          (7) 'ptr' leaks here; was allocated at (1)
-    |
+   NN |   int *ptr = (int *)malloc (sizeof (int));
+      |                     ^~~~~~~~~~~~~~~~~~~~~
+      |                     |
+      |                     (1) allocated here
+   NN |   *ptr = 42;
+      |   ~~~~~~~~~          
+      |        |
+      |        (2) assuming 'ptr' is non-NULL
+   NN |   if (x)
+      |      ~               
+      |      |
+      |      (3) following 'false' branch (when 'x == 0')...
+......
+   NN |   *ptr = 19;
+      |   ~~~~~~~~~          
+      |        |
+      |        (4) ...to here
+......
+   NN |   if (y)
+      |      ~               
+      |      |
+      |      (5) following 'false' branch (when 'y == 0')...
+......
+   NN |   return *ptr;
+      |          ~~~~        
+      |          |
+      |          (6) ...to here
+      |          (7) 'ptr' leaks here; was allocated at (1)
    { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-multiline-2.c b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-multiline-2.c
index 660901ab782d..47f3bcb524fc 100644
--- a/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-multiline-2.c
+++ b/gcc/testsuite/gcc.dg/analyzer/out-of-bounds-multiline-2.c
@@ -18,15 +18,14 @@ void int_vla_write_element_after_end_off_by_one(int32_t x, size_t n)
    arr[n] = x;
    ~~~~~~~^~~
   'int_vla_write_element_after_end_off_by_one': events 1-2 (depth 1)
-    |
-    |   int32_t arr[n];
-    |           ^~~
-    |           |
-    |           (1) capacity: 'n * 4' bytes
-    |
-    |   arr[n] = x;
-    |   ~~~~~~~~~~
-    |          |
-    |          (2) write of 4 bytes at offset 'n * 4' exceeds the buffer
-    |
+   int32_t arr[n];
+           ^~~
+           |
+           (1) capacity: 'n * 4' bytes
+   { dg-end-multiline-output "" } */
+/* { dg-begin-multiline-output "" }
+   arr[n] = x;
+   ~~~~~~~~~~
+          |
+          (2) write of 4 bytes at offset 'n * 4' exceeds the buffer
    { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-2.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-2.c
index b2b269a12b51..b8134aebfda4 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-2.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-2.c
@@ -36,21 +36,19 @@ make_a_list_of_random_ints_badly(PyObject *self,
    29 |     PyList_Append(list, item);
       |     ^~~~~~~~~~~~~~~~~~~~~~~~~
   'make_a_list_of_random_ints_badly': events 1-3
-    |
-    |   25 |   list = PyList_New(0);
-    |      |          ^~~~~~~~~~~~~
-    |      |          |
-    |      |          (1) when 'PyList_New' fails, returning NULL
-    |   26 | 
-    |   27 |   for (i = 0; i < count; i++) {
-    |      |               ~~~~~~~~~
-    |      |                 |
-    |      |                 (2) when 'i < count'
-    |   28 |     item = PyLong_FromLong(random());
-    |   29 |     PyList_Append(list, item);
-    |      |     ~~~~~~~~~~~~~~~~~~~~~~~~~
-    |      |     |
-    |      |     (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
-    |
+   25 |   list = PyList_New(0);
+      |          ^~~~~~~~~~~~~
+      |          |
+      |          (1) when 'PyList_New' fails, returning NULL
+   26 | 
+   27 |   for (i = 0; i < count; i++) {
+      |               ~~~~~~~~~
+      |                 |
+      |                 (2) when 'i < count'
+   28 |     item = PyLong_FromLong(random());
+   29 |     PyList_Append(list, item);
+      |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+      |     |
+      |     (3) when calling 'PyList_Append', passing NULL from (1) as argument 1
      { dg-end-multiline-output "" } */
 }
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc
index 8247192a2504..33389ef5d33e 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/tree-diagnostic-path.cc
@@ -141,6 +141,8 @@ public:
   const char *get_name () const { return m_name.get (); }
   unsigned get_swimlane_index () const { return m_swimlane_idx; }
 
+  bool interprocedural_p () const;
+
 private:
   friend struct path_summary;
   friend class thread_event_printer;
@@ -293,6 +295,26 @@ private:
   }
 };
 
+/* Return true iff there is more than one stack frame used by the events
+   of this thread.  */
+
+bool
+per_thread_summary::interprocedural_p () const
+{
+  if (m_event_ranges.is_empty ())
+    return false;
+  tree first_fndecl = m_event_ranges[0]->m_fndecl;
+  int first_stack_depth = m_event_ranges[0]->m_stack_depth;
+  for (auto range : m_event_ranges)
+    {
+      if (range->m_fndecl != first_fndecl)
+	return true;
+      if (range->m_stack_depth != first_stack_depth)
+	return true;
+    }
+  return false;
+}
+
 /* path_summary's ctor.  */
 
 path_summary::path_summary (const diagnostic_path &path,
@@ -391,11 +413,14 @@ public:
       = colorize_start (pp_show_color (pp), line_color);
     const char *end_line_color = colorize_stop (pp_show_color (pp));
 
+    const bool interprocedural_p = m_per_thread_summary.interprocedural_p ();
+
     write_indent (pp, m_cur_indent);
     if (const event_range *prev_range = get_any_prev_range ())
       {
 	if (range->m_stack_depth > prev_range->m_stack_depth)
 	  {
+	    gcc_assert (interprocedural_p);
 	    /* Show pushed stack frame(s).  */
 	    const char *push_prefix = "+--> ";
 	    pp_string (pp, start_line_color);
@@ -420,34 +445,37 @@ public:
     pp_newline (pp);
 
     /* Print a run of events.  */
-    {
-      write_indent (pp, m_cur_indent + per_frame_indent);
-      pp_string (pp, start_line_color);
-      pp_string (pp, "|");
-      pp_string (pp, end_line_color);
-      pp_newline (pp);
-
-      char *saved_prefix = pp_take_prefix (pp);
-      char *prefix;
+    if (interprocedural_p)
       {
-	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_string (&tmp_pp, end_line_color);
-	prefix = xstrdup (pp_formatted_text (&tmp_pp));
+	write_indent (pp, m_cur_indent + per_frame_indent);
+	pp_string (pp, start_line_color);
+	pp_string (pp, "|");
+	pp_string (pp, end_line_color);
+	pp_newline (pp);
+
+	char *saved_prefix = pp_take_prefix (pp);
+	char *prefix;
+	{
+	  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_string (&tmp_pp, end_line_color);
+	  prefix = xstrdup (pp_formatted_text (&tmp_pp));
+	}
+	pp_set_prefix (pp, prefix);
+	pp_prefixing_rule (pp) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
+	range->print (dc, pp);
+	pp_set_prefix (pp, saved_prefix);
+
+	write_indent (pp, m_cur_indent + per_frame_indent);
+	pp_string (pp, start_line_color);
+	pp_string (pp, "|");
+	pp_string (pp, end_line_color);
+	pp_newline (pp);
       }
-      pp_set_prefix (pp, prefix);
-      pp_prefixing_rule (pp) = DIAGNOSTICS_SHOW_PREFIX_EVERY_LINE;
+    else
       range->print (dc, pp);
-      pp_set_prefix (pp, saved_prefix);
-
-      write_indent (pp, m_cur_indent + per_frame_indent);
-      pp_string (pp, start_line_color);
-      pp_string (pp, "|");
-      pp_string (pp, end_line_color);
-      pp_newline (pp);
-    }
 
     if (const event_range *next_range = get_any_next_range ())
       {
@@ -460,6 +488,7 @@ public:
 		   "                   |\n"
 		   "     <------------ +\n"
 		   "     |\n".  */
+		gcc_assert (interprocedural_p);
 		int vbar_for_next_frame
 		  = *m_vbar_column_for_depth.get (next_range->m_stack_depth);
 
@@ -492,6 +521,7 @@ public:
 	else if (range->m_stack_depth < next_range->m_stack_depth)
 	  {
 	    /* Prepare to show pushed stack frame.  */
+	    gcc_assert (interprocedural_p);
 	    gcc_assert (range->m_stack_depth != EMPTY);
 	    gcc_assert (range->m_stack_depth != DELETED);
 	    m_vbar_column_for_depth.put (range->m_stack_depth,
@@ -766,10 +796,8 @@ test_intraprocedural_path (pretty_printer *event_pp)
   test_diagnostic_context dc;
   print_path_summary_as_text (&summary, &dc, true);
   ASSERT_STREQ ("  `foo': events 1-2 (depth 0)\n"
-		"    |\n"
-		"    | (1): first `free'\n"
-		"    | (2): double `free'\n"
-		"    |\n",
+		" (1): first `free'\n"
+		" (2): double `free'\n",
 		pp_formatted_text (dc.printer));
 }
 
-- 
2.26.3


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [pushed] diagnostics: add warning emoji to events with VERB_danger
  2024-05-16  1:29 [pushed] diagnostics: handle SGR codes in line_label::m_display_width David Malcolm
  2024-05-16  1:29 ` [pushed] diagnostics: simplify output of purely intraprocedural execution paths David Malcolm
@ 2024-05-16  1:29 ` David Malcolm
  2024-05-16  1:30 ` [pushed] diagnostics: use unicode art for interprocedural depth David Malcolm
  2 siblings, 0 replies; 4+ messages in thread
From: David Malcolm @ 2024-05-16  1:29 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

Tweak the printing of -fdiagnostics-path-format=inline-events so that
any event with diagnostic_event::VERB_danger gains a warning emoji,
provided that the text art theme enables emoji support.

VERB_danger is set by the analyzer on the last event in a path, and so
this emoji appears at the end of all analyzer execution paths
highlighting the location of the problem.

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r15-534-g0b7ebe5427a4af.

gcc/testsuite/ChangeLog:
	* gcc.dg/analyzer/out-of-bounds-diagram-1-emoji.c: Update expected
	output to include warning emoji.
	* gcc.dg/analyzer/warning-emoji.c: New test.

gcc/ChangeLog:
	* tree-diagnostic-path.cc: Include "text-art/theme.h".
	(path_label::get_text): If the event has
	diagnostic_event::VERB_danger, and the theme enables emojis, then
	add a warning emoji between the event number and the event text.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
---
 .../analyzer/out-of-bounds-diagram-1-emoji.c  |  2 +-
 gcc/testsuite/gcc.dg/analyzer/warning-emoji.c | 29 ++++++++++++++++++
 gcc/tree-diagnostic-path.cc                   | 30 +++++++++++++++++--
 3 files changed, 57 insertions(+), 4 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/warning-emoji.c

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 1c6125225ff2..7b4ecf0d6b0c 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
@@ -29,7 +29,7 @@ void int_arr_write_element_after_end_off_by_one(int32_t x)
            |   arr[10] = x;
            |   ~~~~~~~~^~~
            |           |
-           |           (2) out-of-bounds write from byte 40 till byte 43 but 'arr' ends at byte 40
+           |           (2) ⚠️  out-of-bounds write from byte 40 till byte 43 but 'arr' ends at byte 40
            |
    { dg-end-multiline-output "" } */
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/warning-emoji.c b/gcc/testsuite/gcc.dg/analyzer/warning-emoji.c
new file mode 100644
index 000000000000..47e5fb0acf90
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/warning-emoji.c
@@ -0,0 +1,29 @@
+/* Verify that the final event in an analyzer path gets a "warning" emoji 
+   when -fdiagnostics-text-art-charset=emoji (and
+   -fdiagnostics-path-format=inline-events).  */
+
+/* { dg-additional-options "-fdiagnostics-show-line-numbers" } */
+/* { dg-additional-options "-fdiagnostics-show-caret" } */
+/* { dg-additional-options "-fdiagnostics-path-format=inline-events" } */
+/* { dg-additional-options "-fdiagnostics-text-art-charset=emoji" } */
+/* { dg-enable-nn-line-numbers "" } */
+
+void test (void *p)
+{
+  __builtin_free (p);
+  __builtin_free (p); /* { dg-warning "double-'free'" } */
+}
+
+/* { dg-begin-multiline-output "" }
+   NN |   __builtin_free (p);
+      |   ^~~~~~~~~~~~~~~~~~
+  'test': events 1-2
+   NN |   __builtin_free (p);
+      |   ^~~~~~~~~~~~~~~~~~
+      |   |
+      |   (1) first 'free' here
+   NN |   __builtin_free (p);
+      |   ~~~~~~~~~~~~~~~~~~
+      |   |
+      |   (2) ⚠️  second 'free' here; first 'free' was at (1)
+   { dg-end-multiline-output "" } */
diff --git a/gcc/tree-diagnostic-path.cc b/gcc/tree-diagnostic-path.cc
index 33389ef5d33e..bc90aaf321cc 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/tree-diagnostic-path.cc
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "diagnostic-event-id.h"
 #include "selftest.h"
 #include "selftest-diagnostic.h"
+#include "text-art/theme.h"
 
 /* Anonymous namespace for path-printing code.  */
 
@@ -60,13 +61,36 @@ class path_label : public range_label
     /* Get the description of the event, perhaps with colorization:
        normally, we don't colorize within a range_label, but this
        is special-cased for diagnostic paths.  */
-    bool colorize = pp_show_color (global_dc->printer);
+    const bool colorize = pp_show_color (global_dc->printer);
     label_text event_text (event.get_desc (colorize));
     gcc_assert (event_text.get ());
+
+    const diagnostic_event::meaning meaning (event.get_meaning ());
+
     pretty_printer pp;
-    pp_show_color (&pp) = pp_show_color (global_dc->printer);
+    pp_show_color (&pp) = colorize;
     diagnostic_event_id_t event_id (event_idx);
-    pp_printf (&pp, "%@ %s", &event_id, event_text.get ());
+
+    pp_printf (&pp, "%@", &event_id);
+    pp_space (&pp);
+
+    if (meaning.m_verb == diagnostic_event::VERB_danger)
+      if (text_art::theme *theme = global_dc->get_diagram_theme ())
+	if (theme->emojis_p ())
+	  {
+	    pp_unicode_character (&pp, 0x26A0); /* U+26A0 WARNING SIGN.  */
+	    /* Append U+FE0F VARIATION SELECTOR-16 to select the emoji
+	       variation of the char.  */
+	    pp_unicode_character (&pp, 0xFE0F);
+	    /* U+26A0 WARNING SIGN has East_Asian_Width == Neutral, but in its
+	       emoji variant is printed (by vte at least) with a 2nd half
+	       overlapping the next char.  Hence we add two spaces here: a space
+	       to be covered by this overlap, plus another space of padding.  */
+	    pp_string (&pp, "  ");
+	  }
+
+    pp_printf (&pp, "%s", event_text.get ());
+
     label_text result = label_text::take (xstrdup (pp_formatted_text (&pp)));
     return result;
   }
-- 
2.26.3


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [pushed] diagnostics: use unicode art for interprocedural depth
  2024-05-16  1:29 [pushed] diagnostics: handle SGR codes in line_label::m_display_width David Malcolm
  2024-05-16  1:29 ` [pushed] diagnostics: simplify output of purely intraprocedural execution paths David Malcolm
  2024-05-16  1:29 ` [pushed] diagnostics: add warning emoji to events with VERB_danger David Malcolm
@ 2024-05-16  1:30 ` David Malcolm
  2 siblings, 0 replies; 4+ messages in thread
From: David Malcolm @ 2024-05-16  1:30 UTC (permalink / raw)
  To: gcc-patches; +Cc: David Malcolm

Successfully bootstrapped & regrtested on x86_64-pc-linux-gnu.
Successful run of analyzer integration tests on x86_64-pc-linux-gnu.
Pushed to trunk as r15-535-ge656656e711949.

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 <dmalcolm@redhat.com>
---
 .../analyzer/out-of-bounds-diagram-1-emoji.c  |  26 +-
 .../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.  */
-- 
2.26.3


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2024-05-16  1:30 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-16  1:29 [pushed] diagnostics: handle SGR codes in line_label::m_display_width David Malcolm
2024-05-16  1:29 ` [pushed] diagnostics: simplify output of purely intraprocedural execution paths David Malcolm
2024-05-16  1:29 ` [pushed] diagnostics: add warning emoji to events with VERB_danger David Malcolm
2024-05-16  1:30 ` [pushed] diagnostics: use unicode art for interprocedural depth David Malcolm

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).