From 67b20f477b7c556150df98c68fe604ad328c85ac Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 13 Nov 2019 14:50:07 -0500
Subject: [PATCH 55/78] FIXME: WIP on less LHS in paths (needs splitting)

---
 cover-letter.txt                                   |  88 +++--
 .../NOT_FOR_UPSTREAM-CVE-2005-1689-krb5-recvauth.c |   2 +-
 .../analyzer/NOT_FOR_UPSTREAM-setjmp-wikipedia-1.c | 144 +++----
 .../analyzer/NOT_FOR_UPSTREAM-setjmp-wikipedia-2.c |   2 +-
 .../gcc.dg/analyzer/analyzer-verbosity-0.c         | 138 +++----
 .../gcc.dg/analyzer/analyzer-verbosity-1.c         | 198 +++++-----
 .../gcc.dg/analyzer/analyzer-verbosity-2.c         | 256 ++++++------
 gcc/testsuite/gcc.dg/analyzer/malloc-ipa-11.c      | 124 +++---
 .../gcc.dg/analyzer/malloc-ipa-8-double-free.c     | 221 ++++++-----
 .../gcc.dg/analyzer/malloc-ipa-8-unchecked.c       |  74 ++--
 .../gcc.dg/analyzer/malloc-macro-inline-events.c   |  36 +-
 gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c     | 430 +++++++++++----------
 gcc/testsuite/gcc.dg/analyzer/setjmp-2.c           |  82 ++--
 gcc/testsuite/gcc.dg/analyzer/setjmp-3.c           | 128 +++---
 gcc/testsuite/gcc.dg/analyzer/setjmp-4.c           | 138 +++----
 gcc/testsuite/gcc.dg/analyzer/setjmp-5.c           |  80 ++--
 gcc/testsuite/gcc.dg/analyzer/setjmp-8.c           | 128 +++---
 gcc/testsuite/gcc.dg/analyzer/setjmp-9.c           | 128 +++---
 .../gcc.dg/plugin/diagnostic-path-format-default.c | 154 ++++----
 .../diagnostic-path-format-inline-events-1.c       | 154 ++++----
 .../diagnostic-path-format-inline-events-2.c       | 161 ++++----
 .../diagnostic-path-format-inline-events-3.c       | 161 ++++----
 .../gcc.dg/plugin/diagnostic-test-paths-2.c        |  34 +-
 gcc/tree-diagnostic-path.cc                        | 170 ++++----
 24 files changed, 1640 insertions(+), 1591 deletions(-)

diff --git a/cover-letter.txt b/cover-letter.txt
index a1bec49..00a7c99 100644
--- a/cover-letter.txt
+++ b/cover-letter.txt
@@ -66,39 +66,59 @@ describing a sequence of events predicted by the compiler that
 lead to the problem occurring, with their locations in the user's source,
 and text descriptions.
 
-For example, the following (hypothetical) error has a 3-event path:
-
- test.c: In function 'make_a_list_of_random_ints_badly':
- test.c:29:5: error: passing NULL as argument 1 to 'PyList_Append' which
-   requires a non-NULL parameter
-    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 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
-function; more complicated examples (such as interprocedural paths)
-might be printed as multiple runs of events.
+For example, the following warning has a 6-event interprocedural path:
+
+malloc-ipa-8-unchecked.c: In function 'make_boxed_int':
+malloc-ipa-8-unchecked.c:21:13: warning: dereference of possibly-NULL 'result' [CWE-690] [-Wanalyzer-possible-null-dereference]
+   21 |   result->i = i;
+      |   ~~~~~~~~~~^~~
+  'make_boxed_int': events 1-2
+    |
+    |   18 | make_boxed_int (int i)
+    |      | ^~~~~~~~~~~~~~
+    |      | |
+    |      | (1) entry to 'make_boxed_int'
+    |   19 | {
+    |   20 |   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
+    |      |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    |      |                                    |
+    |      |                                    (2) calling 'wrapped_malloc' from 'make_boxed_int'
+    |
+    +--> 'wrapped_malloc': events 3-4
+           |
+           |    7 | void *wrapped_malloc (size_t size)
+           |      |       ^~~~~~~~~~~~~~
+           |      |       |
+           |      |       (3) entry to 'wrapped_malloc'
+           |    8 | {
+           |    9 |   return malloc (size);
+           |      |          ~~~~~~~~~~~~~
+           |      |          |
+           |      |          (4) this call could return NULL
+           |
+    <------+
+    |
+  'make_boxed_int': events 5-6
+    |
+    |   20 |   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
+    |      |                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    |      |                                    |
+    |      |                                    (5) possible return of NULL to 'make_boxed_int' from 'wrapped_malloc'
+    |   21 |   result->i = i;
+    |      |   ~~~~~~~~~~~~~
+    |      |             |
+    |      |             (6) 'result' could be NULL: unchecked value from (4)
+    |
+
+The diagnostic-printing code has consolidated the path into 3 runs of events
+(where the events are near each other and within the same function).
+
+FIXME: html colorized version of the above
 
 (b) adding the ability to associate additional metadata with a diagnostic.
 The only such metadata added by the patch kit are CWE classifications (for
-the new warnings), so that we can emit e.g.:
+the new warnings), such as the CWE-690 in the warning above, or CWE-401 in
+this example:
 
 malloc-1.c: In function ‘test_42a’:
 malloc-1.c:466:1: warning: leak of ‘p’ [CWE-401] [-Wanalyzer-malloc-leak]
@@ -117,15 +137,9 @@ malloc-1.c:466:1: warning: leak of ‘p’ [CWE-401] [-Wanalyzer-malloc-leak]
        |      | (2) ‘p’ leaks here; was allocated at (1)
        |
 
-(c) adding support for embedding URL information in our textual output
-in a form understood by recent versions of terminals
-  https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
-so that in the above, the CWE-401 is a clickable link to
+The above "CWE-401" is a clickable hyperlink to
   https://cwe.mitre.org/data/definitions/401.html
 
-More broadly, the options become clickable links to GCC's online
-documentation.
-
 
 Rationale
 =========
diff --git a/gcc/testsuite/gcc.dg/analyzer/NOT_FOR_UPSTREAM-CVE-2005-1689-krb5-recvauth.c b/gcc/testsuite/gcc.dg/analyzer/NOT_FOR_UPSTREAM-CVE-2005-1689-krb5-recvauth.c
index 5095285..096f164 100644
--- a/gcc/testsuite/gcc.dg/analyzer/NOT_FOR_UPSTREAM-CVE-2005-1689-krb5-recvauth.c
+++ b/gcc/testsuite/gcc.dg/analyzer/NOT_FOR_UPSTREAM-CVE-2005-1689-krb5-recvauth.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -Wno-analyzer-too-complex" } */
+/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret -Wno-analyzer-too-complex" } */
 
 typedef unsigned char __u_char;
 typedef unsigned short int __u_short;
diff --git a/gcc/testsuite/gcc.dg/analyzer/NOT_FOR_UPSTREAM-setjmp-wikipedia-1.c b/gcc/testsuite/gcc.dg/analyzer/NOT_FOR_UPSTREAM-setjmp-wikipedia-1.c
index 625f5b6..c5a99c9 100644
--- a/gcc/testsuite/gcc.dg/analyzer/NOT_FOR_UPSTREAM-setjmp-wikipedia-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/NOT_FOR_UPSTREAM-setjmp-wikipedia-1.c
@@ -1,5 +1,5 @@
 /* Taken from https://en.wikipedia.org/wiki/Setjmp.h  */
-/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events" } */
+/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
 
 #include <stdio.h>
 #include <setjmp.h>
@@ -28,79 +28,81 @@ int main() {
 }
 
 /* { dg-begin-multiline-output "" }
+   NN |     __analyzer_dump_path ();
+      |     ^~~~~~~~~~~~~~~~~~~~~~~
   'main': event 1
-     |
-     |   NN | int main() {
-     |      |     ^~~~
-     |      |     |
-     |      |     (1) entry to 'main'
-     |
+    |
+    |   NN | int main() {
+    |      |     ^~~~
+    |      |     |
+    |      |     (1) entry to 'main'
+    |
   'main': event 2
-     |
-     |   NN |     if (!setjmp(buf))
-     |      |          ^~~~~~
-     |      |          |
-     |      |          (2) 'setjmp' called here
-     |
+    |
+    |   NN |     if (!setjmp(buf))
+    |      |          ^~~~~~
+    |      |          |
+    |      |          (2) 'setjmp' called here
+    |
   'main': events 3-5
-     |
-     |   NN |     if (!setjmp(buf))
-     |      |        ^
-     |      |        |
-     |      |        (3) following 'true' branch...
-     |   NN |         first();                // when executed, setjmp returned 0
-     |      |         ~~~~~~~
-     |      |         |
-     |      |         (4) ...to here
-     |      |         (5) calling 'first' from 'main'
-     |
-     +--> 'first': events 6-7
-             |
-             |   NN | void first() {
-             |      |      ^~~~~
-             |      |      |
-             |      |      (6) entry to 'first'
-             |   NN |     second();
-             |      |     ~~~~~~~~
-             |      |     |
-             |      |     (7) calling 'second' from 'first'
-             |
-             +--> 'second': events 8-9
-                      |
-                      |   NN | void second() {
-                      |      |      ^~~~~~
-                      |      |      |
-                      |      |      (8) entry to 'second'
-                      |   NN |     printf("second\n");         // prints
-                      |   NN |     longjmp(buf,1);             // jumps back to where setjmp was called - making setjmp now return 1
-                      |      |     ~~~~~~~~~~~~~~
-                      |      |     |
-                      |      |     (9) rewinding from 'longjmp' in 'second'...
-                      |
-     <----------------+
-     |
+    |
+    |   NN |     if (!setjmp(buf))
+    |      |        ^
+    |      |        |
+    |      |        (3) following 'true' branch...
+    |   NN |         first();                // when executed, setjmp returned 0
+    |      |         ~~~~~~~
+    |      |         |
+    |      |         (4) ...to here
+    |      |         (5) calling 'first' from 'main'
+    |
+    +--> 'first': events 6-7
+           |
+           |   NN | void first() {
+           |      |      ^~~~~
+           |      |      |
+           |      |      (6) entry to 'first'
+           |   NN |     second();
+           |      |     ~~~~~~~~
+           |      |     |
+           |      |     (7) calling 'second' from 'first'
+           |
+           +--> 'second': events 8-9
+                  |
+                  |   NN | void second() {
+                  |      |      ^~~~~~
+                  |      |      |
+                  |      |      (8) entry to 'second'
+                  |   NN |     printf("second\n");         // prints
+                  |   NN |     longjmp(buf,1);             // jumps back to where setjmp was called - making setjmp now return 1
+                  |      |     ~~~~~~~~~~~~~~
+                  |      |     |
+                  |      |     (9) rewinding from 'longjmp' in 'second'...
+                  |
+    <-------------+
+    |
   'main': event 10
-     |
-     |   NN |     if (!setjmp(buf))
-     |      |          ^~~~~~
-     |      |          |
-     |      |          (10) ...to 'setjmp' in 'main' (saved at (2))
-     |
+    |
+    |   NN |     if (!setjmp(buf))
+    |      |          ^~~~~~
+    |      |          |
+    |      |          (10) ...to 'setjmp' in 'main' (saved at (2))
+    |
   'main': events 11-13
-     |
-     |   NN |     if (!setjmp(buf))
-     |      |        ^
-     |      |        |
-     |      |        (11) following 'false' branch...
-     |......
-     |   NN |         printf("main\n");       // prints
-     |      |         ~~~~~~~~~~~~~~~~
-     |      |         |
-     |      |         (12) ...to here
-     |   NN | 
-     |   NN |     __analyzer_dump_path ();
-     |      |     ~~~~~~~~~~~~~~~~~~~~~~~
-     |      |     |
-     |      |     (13) here
-     |
+    |
+    |   NN |     if (!setjmp(buf))
+    |      |        ^
+    |      |        |
+    |      |        (11) following 'false' branch...
+    |......
+    |   NN |         printf("main\n");       // prints
+    |      |         ~~~~~~~~~~~~~~~~
+    |      |         |
+    |      |         (12) ...to here
+    |   NN | 
+    |   NN |     __analyzer_dump_path ();
+    |      |     ~~~~~~~~~~~~~~~~~~~~~~~
+    |      |     |
+    |      |     (13) here
+    |
     { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/NOT_FOR_UPSTREAM-setjmp-wikipedia-2.c b/gcc/testsuite/gcc.dg/analyzer/NOT_FOR_UPSTREAM-setjmp-wikipedia-2.c
index a2ff27f..17a4228 100644
--- a/gcc/testsuite/gcc.dg/analyzer/NOT_FOR_UPSTREAM-setjmp-wikipedia-2.c
+++ b/gcc/testsuite/gcc.dg/analyzer/NOT_FOR_UPSTREAM-setjmp-wikipedia-2.c
@@ -1,5 +1,5 @@
 /* Taken from https://en.wikipedia.org/wiki/Setjmp.h  */
-/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events" } */
+/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
 #include <setjmp.h>
 #include <stdio.h>
 #include <stdlib.h>
diff --git a/gcc/testsuite/gcc.dg/analyzer/analyzer-verbosity-0.c b/gcc/testsuite/gcc.dg/analyzer/analyzer-verbosity-0.c
index 6293075..98200b3 100644
--- a/gcc/testsuite/gcc.dg/analyzer/analyzer-verbosity-0.c
+++ b/gcc/testsuite/gcc.dg/analyzer/analyzer-verbosity-0.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fanalyzer-verbosity=0" } */
+/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret -fanalyzer-verbosity=0" } */
 
 #include <stdlib.h>
 
@@ -20,41 +20,43 @@ void test_1 (void *ptr, int a, int b)
 }
 
 /* { dg-begin-multiline-output "" }
+   NN |   free (ptr);
+      |   ^~~~~~~~~~
   'test_1': event 1
-      |
-      |   NN |     calls_free_1 (ptr);
-      |      |     ^~~~~~~~~~~~~~~~~~
-      |      |     |
-      |      |     (1) calling 'calls_free_1' from 'test_1'
-      |
-      +--> 'calls_free_1': event 2
-                  |
-                  |   NN |   free (ptr);
-                  |      |   ^~~~~~~~~~
-                  |      |   |
-                  |      |   (2) first 'free' here
-                  |
-      <-----------+
-      |
+    |
+    |   NN |     calls_free_1 (ptr);
+    |      |     ^~~~~~~~~~~~~~~~~~
+    |      |     |
+    |      |     (1) calling 'calls_free_1' from 'test_1'
+    |
+    +--> 'calls_free_1': event 2
+           |
+           |   NN |   free (ptr);
+           |      |   ^~~~~~~~~~
+           |      |   |
+           |      |   (2) first 'free' here
+           |
+    <------+
+    |
   'test_1': events 3-4
-      |
-      |   NN |     calls_free_1 (ptr);
-      |      |     ^~~~~~~~~~~~~~~~~~
-      |      |     |
-      |      |     (3) returning to 'test_1' from 'calls_free_1'
-      |......
-      |   NN |     calls_free_1 (ptr);
-      |      |     ~~~~~~~~~~~~~~~~~~
-      |      |     |
-      |      |     (4) passing freed pointer 'ptr' in call to 'calls_free_1' from 'test_1'
-      |
-      +--> 'calls_free_1': event 5
-                  |
-                  |   NN |   free (ptr);
-                  |      |   ^~~~~~~~~~
-                  |      |   |
-                  |      |   (5) second 'free' here; first 'free' was at (2)
-                  |
+    |
+    |   NN |     calls_free_1 (ptr);
+    |      |     ^~~~~~~~~~~~~~~~~~
+    |      |     |
+    |      |     (3) returning to 'test_1' from 'calls_free_1'
+    |......
+    |   NN |     calls_free_1 (ptr);
+    |      |     ~~~~~~~~~~~~~~~~~~
+    |      |     |
+    |      |     (4) passing freed pointer 'ptr' in call to 'calls_free_1' from 'test_1'
+    |
+    +--> 'calls_free_1': event 5
+           |
+           |   NN |   free (ptr);
+           |      |   ^~~~~~~~~~
+           |      |   |
+           |      |   (5) second 'free' here; first 'free' was at (2)
+           |
   { dg-end-multiline-output "" } */
 
 void calls_free_2 (void *ptr)
@@ -88,41 +90,43 @@ void test_2 (void *ptr, int a, int b)
 }
 
 /* { dg-begin-multiline-output "" }
+   NN |   free (ptr);
+      |   ^~~~~~~~~~
   'test_2': event 1
-      |
-      |   NN |       calls_free_2 (ptr);
-      |      |       ^~~~~~~~~~~~~~~~~~
-      |      |       |
-      |      |       (1) calling 'calls_free_2' from 'test_2'
-      |
-      +--> 'calls_free_2': event 2
-                  |
-                  |   NN |   free (ptr);
-                  |      |   ^~~~~~~~~~
-                  |      |   |
-                  |      |   (2) first 'free' here
-                  |
-      <-----------+
-      |
+    |
+    |   NN |       calls_free_2 (ptr);
+    |      |       ^~~~~~~~~~~~~~~~~~
+    |      |       |
+    |      |       (1) calling 'calls_free_2' from 'test_2'
+    |
+    +--> 'calls_free_2': event 2
+           |
+           |   NN |   free (ptr);
+           |      |   ^~~~~~~~~~
+           |      |   |
+           |      |   (2) first 'free' here
+           |
+    <------+
+    |
   'test_2': events 3-4
-      |
-      |   NN |       calls_free_2 (ptr);
-      |      |       ^~~~~~~~~~~~~~~~~~
-      |      |       |
-      |      |       (3) returning to 'test_2' from 'calls_free_2'
-      |......
-      |   NN |       calls_free_2 (ptr);
-      |      |       ~~~~~~~~~~~~~~~~~~
-      |      |       |
-      |      |       (4) passing freed pointer 'ptr' in call to 'calls_free_2' from 'test_2'
-      |
-      +--> 'calls_free_2': event 5
-                  |
-                  |   NN |   free (ptr);
-                  |      |   ^~~~~~~~~~
-                  |      |   |
-                  |      |   (5) second 'free' here; first 'free' was at (2)
-                  |
+    |
+    |   NN |       calls_free_2 (ptr);
+    |      |       ^~~~~~~~~~~~~~~~~~
+    |      |       |
+    |      |       (3) returning to 'test_2' from 'calls_free_2'
+    |......
+    |   NN |       calls_free_2 (ptr);
+    |      |       ~~~~~~~~~~~~~~~~~~
+    |      |       |
+    |      |       (4) passing freed pointer 'ptr' in call to 'calls_free_2' from 'test_2'
+    |
+    +--> 'calls_free_2': event 5
+           |
+           |   NN |   free (ptr);
+           |      |   ^~~~~~~~~~
+           |      |   |
+           |      |   (5) second 'free' here; first 'free' was at (2)
+           |
   { dg-end-multiline-output "" } */
 
 // TODO: range cases
diff --git a/gcc/testsuite/gcc.dg/analyzer/analyzer-verbosity-1.c b/gcc/testsuite/gcc.dg/analyzer/analyzer-verbosity-1.c
index 32f3111..7e437bb 100644
--- a/gcc/testsuite/gcc.dg/analyzer/analyzer-verbosity-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/analyzer-verbosity-1.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fanalyzer-verbosity=1" } */
+/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret -fanalyzer-verbosity=1" } */
 
 #include <stdlib.h>
 
@@ -20,56 +20,58 @@ void test_1 (void *ptr, int a, int b)
 }
 
 /* { dg-begin-multiline-output "" }
+   NN |   free (ptr);
+      |   ^~~~~~~~~~
   'test_1': events 1-2
-      |
-      |   NN | void test_1 (void *ptr, int a, int b)
-      |      |      ^~~~~~
-      |      |      |
-      |      |      (1) entry to 'test_1'
-      |......
-      |   NN |     calls_free_1 (ptr);
-      |      |     ~~~~~~~~~~~~~~~~~~
-      |      |     |
-      |      |     (2) calling 'calls_free_1' from 'test_1'
-      |
-      +--> 'calls_free_1': events 3-4
-                  |
-                  |   NN | void calls_free_1 (void *ptr)
-                  |      |      ^~~~~~~~~~~~
-                  |      |      |
-                  |      |      (3) entry to 'calls_free_1'
-                  |   NN | {
-                  |   NN |   free (ptr);
-                  |      |   ~~~~~~~~~~
-                  |      |   |
-                  |      |   (4) first 'free' here
-                  |
-      <-----------+
-      |
+    |
+    |   NN | void test_1 (void *ptr, int a, int b)
+    |      |      ^~~~~~
+    |      |      |
+    |      |      (1) entry to 'test_1'
+    |......
+    |   NN |     calls_free_1 (ptr);
+    |      |     ~~~~~~~~~~~~~~~~~~
+    |      |     |
+    |      |     (2) calling 'calls_free_1' from 'test_1'
+    |
+    +--> 'calls_free_1': events 3-4
+           |
+           |   NN | void calls_free_1 (void *ptr)
+           |      |      ^~~~~~~~~~~~
+           |      |      |
+           |      |      (3) entry to 'calls_free_1'
+           |   NN | {
+           |   NN |   free (ptr);
+           |      |   ~~~~~~~~~~
+           |      |   |
+           |      |   (4) first 'free' here
+           |
+    <------+
+    |
   'test_1': events 5-6
-      |
-      |   NN |     calls_free_1 (ptr);
-      |      |     ^~~~~~~~~~~~~~~~~~
-      |      |     |
-      |      |     (5) returning to 'test_1' from 'calls_free_1'
-      |......
-      |   NN |     calls_free_1 (ptr);
-      |      |     ~~~~~~~~~~~~~~~~~~
-      |      |     |
-      |      |     (6) passing freed pointer 'ptr' in call to 'calls_free_1' from 'test_1'
-      |
-      +--> 'calls_free_1': events 7-8
-                  |
-                  |   NN | void calls_free_1 (void *ptr)
-                  |      |      ^~~~~~~~~~~~
-                  |      |      |
-                  |      |      (7) entry to 'calls_free_1'
-                  |   NN | {
-                  |   NN |   free (ptr);
-                  |      |   ~~~~~~~~~~
-                  |      |   |
-                  |      |   (8) second 'free' here; first 'free' was at (4)
-                  |
+    |
+    |   NN |     calls_free_1 (ptr);
+    |      |     ^~~~~~~~~~~~~~~~~~
+    |      |     |
+    |      |     (5) returning to 'test_1' from 'calls_free_1'
+    |......
+    |   NN |     calls_free_1 (ptr);
+    |      |     ~~~~~~~~~~~~~~~~~~
+    |      |     |
+    |      |     (6) passing freed pointer 'ptr' in call to 'calls_free_1' from 'test_1'
+    |
+    +--> 'calls_free_1': events 7-8
+           |
+           |   NN | void calls_free_1 (void *ptr)
+           |      |      ^~~~~~~~~~~~
+           |      |      |
+           |      |      (7) entry to 'calls_free_1'
+           |   NN | {
+           |   NN |   free (ptr);
+           |      |   ~~~~~~~~~~
+           |      |   |
+           |      |   (8) second 'free' here; first 'free' was at (4)
+           |
   { dg-end-multiline-output "" } */
 
 void calls_free_2 (void *ptr)
@@ -103,54 +105,56 @@ void test_2 (void *ptr, int a, int b)
 }
 
 /* { dg-begin-multiline-output "" }
+   NN |   free (ptr);
+      |   ^~~~~~~~~~
   'test_2': events 1-2
-      |
-      |   NN | void test_2 (void *ptr, int a, int b)
-      |      |      ^~~~~~
-      |      |      |
-      |      |      (1) entry to 'test_2'
-      |......
-      |   NN |       calls_free_2 (ptr);
-      |      |       ~~~~~~~~~~~~~~~~~~
-      |      |       |
-      |      |       (2) calling 'calls_free_2' from 'test_2'
-      |
-      +--> 'calls_free_2': events 3-4
-                  |
-                  |   NN | void calls_free_2 (void *ptr)
-                  |      |      ^~~~~~~~~~~~
-                  |      |      |
-                  |      |      (3) entry to 'calls_free_2'
-                  |   NN | {
-                  |   NN |   free (ptr);
-                  |      |   ~~~~~~~~~~
-                  |      |   |
-                  |      |   (4) first 'free' here
-                  |
-      <-----------+
-      |
+    |
+    |   NN | void test_2 (void *ptr, int a, int b)
+    |      |      ^~~~~~
+    |      |      |
+    |      |      (1) entry to 'test_2'
+    |......
+    |   NN |       calls_free_2 (ptr);
+    |      |       ~~~~~~~~~~~~~~~~~~
+    |      |       |
+    |      |       (2) calling 'calls_free_2' from 'test_2'
+    |
+    +--> 'calls_free_2': events 3-4
+           |
+           |   NN | void calls_free_2 (void *ptr)
+           |      |      ^~~~~~~~~~~~
+           |      |      |
+           |      |      (3) entry to 'calls_free_2'
+           |   NN | {
+           |   NN |   free (ptr);
+           |      |   ~~~~~~~~~~
+           |      |   |
+           |      |   (4) first 'free' here
+           |
+    <------+
+    |
   'test_2': events 5-6
-      |
-      |   NN |       calls_free_2 (ptr);
-      |      |       ^~~~~~~~~~~~~~~~~~
-      |      |       |
-      |      |       (5) returning to 'test_2' from 'calls_free_2'
-      |......
-      |   NN |       calls_free_2 (ptr);
-      |      |       ~~~~~~~~~~~~~~~~~~
-      |      |       |
-      |      |       (6) passing freed pointer 'ptr' in call to 'calls_free_2' from 'test_2'
-      |
-      +--> 'calls_free_2': events 7-8
-                  |
-                  |   NN | void calls_free_2 (void *ptr)
-                  |      |      ^~~~~~~~~~~~
-                  |      |      |
-                  |      |      (7) entry to 'calls_free_2'
-                  |   NN | {
-                  |   NN |   free (ptr);
-                  |      |   ~~~~~~~~~~
-                  |      |   |
-                  |      |   (8) second 'free' here
-                  |
+    |
+    |   NN |       calls_free_2 (ptr);
+    |      |       ^~~~~~~~~~~~~~~~~~
+    |      |       |
+    |      |       (5) returning to 'test_2' from 'calls_free_2'
+    |......
+    |   NN |       calls_free_2 (ptr);
+    |      |       ~~~~~~~~~~~~~~~~~~
+    |      |       |
+    |      |       (6) passing freed pointer 'ptr' in call to 'calls_free_2' from 'test_2'
+    |
+    +--> 'calls_free_2': events 7-8
+           |
+           |   NN | void calls_free_2 (void *ptr)
+           |      |      ^~~~~~~~~~~~
+           |      |      |
+           |      |      (7) entry to 'calls_free_2'
+           |   NN | {
+           |   NN |   free (ptr);
+           |      |   ~~~~~~~~~~
+           |      |   |
+           |      |   (8) second 'free' here; first 'free' was at (4)
+           |
   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/analyzer-verbosity-2.c b/gcc/testsuite/gcc.dg/analyzer/analyzer-verbosity-2.c
index 99a51fc..2c9e5da 100644
--- a/gcc/testsuite/gcc.dg/analyzer/analyzer-verbosity-2.c
+++ b/gcc/testsuite/gcc.dg/analyzer/analyzer-verbosity-2.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fanalyzer-verbosity=2" } */
+/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret -fanalyzer-verbosity=2" } */
 
 #include <stdlib.h>
 
@@ -20,67 +20,69 @@ void test_1 (void *ptr, int a, int b)
 }
 
 /* { dg-begin-multiline-output "" }
+   NN |   free (ptr);
+      |   ^~~~~~~~~~
   'test_1': events 1-4
-      |
-      |   NN | void test_1 (void *ptr, int a, int b)
-      |      |      ^~~~~~
-      |      |      |
-      |      |      (1) entry to 'test_1'
-      |   NN | {
-      |   NN |   if (a)
-      |      |      ~
-      |      |      |
-      |      |      (2) following 'true' branch (when 'a != 0')...
-      |   NN |     calls_free_1 (ptr);
-      |      |     ~~~~~~~~~~~~~~~~~~
-      |      |     |
-      |      |     (3) ...to here
-      |      |     (4) calling 'calls_free_1' from 'test_1'
-      |
-      +--> 'calls_free_1': events 5-6
-                  |
-                  |   NN | void calls_free_1 (void *ptr)
-                  |      |      ^~~~~~~~~~~~
-                  |      |      |
-                  |      |      (5) entry to 'calls_free_1'
-                  |   NN | {
-                  |   NN |   free (ptr);
-                  |      |   ~~~~~~~~~~
-                  |      |   |
-                  |      |   (6) first 'free' here
-                  |
-      <-----------+
-      |
+    |
+    |   NN | void test_1 (void *ptr, int a, int b)
+    |      |      ^~~~~~
+    |      |      |
+    |      |      (1) entry to 'test_1'
+    |   NN | {
+    |   NN |   if (a)
+    |      |      ~
+    |      |      |
+    |      |      (2) following 'true' branch (when 'a != 0')...
+    |   NN |     calls_free_1 (ptr);
+    |      |     ~~~~~~~~~~~~~~~~~~
+    |      |     |
+    |      |     (3) ...to here
+    |      |     (4) calling 'calls_free_1' from 'test_1'
+    |
+    +--> 'calls_free_1': events 5-6
+           |
+           |   NN | void calls_free_1 (void *ptr)
+           |      |      ^~~~~~~~~~~~
+           |      |      |
+           |      |      (5) entry to 'calls_free_1'
+           |   NN | {
+           |   NN |   free (ptr);
+           |      |   ~~~~~~~~~~
+           |      |   |
+           |      |   (6) first 'free' here
+           |
+    <------+
+    |
   'test_1': events 7-10
-      |
-      |   NN |     calls_free_1 (ptr);
-      |      |     ^~~~~~~~~~~~~~~~~~
-      |      |     |
-      |      |     (7) returning to 'test_1' from 'calls_free_1'
-      |   NN | 
-      |   NN |   if (b)
-      |      |      ~
-      |      |      |
-      |      |      (8) following 'false' branch (when 'b == 0')...
-      |......
-      |   NN |     calls_free_1 (ptr);
-      |      |     ~~~~~~~~~~~~~~~~~~
-      |      |     |
-      |      |     (9) ...to here
-      |      |     (10) passing freed pointer 'ptr' in call to 'calls_free_1' from 'test_1'
-      |
-      +--> 'calls_free_1': events 11-12
-                  |
-                  |   NN | void calls_free_1 (void *ptr)
-                  |      |      ^~~~~~~~~~~~
-                  |      |      |
-                  |      |      (11) entry to 'calls_free_1'
-                  |   NN | {
-                  |   NN |   free (ptr);
-                  |      |   ~~~~~~~~~~
-                  |      |   |
-                  |      |   (12) second 'free' here; first 'free' was at (6)
-                  |
+    |
+    |   NN |     calls_free_1 (ptr);
+    |      |     ^~~~~~~~~~~~~~~~~~
+    |      |     |
+    |      |     (7) returning to 'test_1' from 'calls_free_1'
+    |   NN | 
+    |   NN |   if (b)
+    |      |      ~
+    |      |      |
+    |      |      (8) following 'false' branch (when 'b == 0')...
+    |......
+    |   NN |     calls_free_1 (ptr);
+    |      |     ~~~~~~~~~~~~~~~~~~
+    |      |     |
+    |      |     (9) ...to here
+    |      |     (10) passing freed pointer 'ptr' in call to 'calls_free_1' from 'test_1'
+    |
+    +--> 'calls_free_1': events 11-12
+           |
+           |   NN | void calls_free_1 (void *ptr)
+           |      |      ^~~~~~~~~~~~
+           |      |      |
+           |      |      (11) entry to 'calls_free_1'
+           |   NN | {
+           |   NN |   free (ptr);
+           |      |   ~~~~~~~~~~
+           |      |   |
+           |      |   (12) second 'free' here; first 'free' was at (6)
+           |
   { dg-end-multiline-output "" } */
 
 void calls_free_2 (void *ptr)
@@ -114,74 +116,76 @@ void test_2 (void *ptr, int a, int b)
 }
 
 /* { dg-begin-multiline-output "" }
+   NN |   free (ptr);
+      |   ^~~~~~~~~~
   'test_2': events 1-4
-      |
-      |   NN | void test_2 (void *ptr, int a, int b)
-      |      |      ^~~~~~
-      |      |      |
-      |      |      (1) entry to 'test_2'
-      |   NN | {
-      |   NN |   switch (a)
-      |      |   ~~~~~~
-      |      |   |
-      |      |   (2) following 'case 3:' branch...
-      |......
-      |   NN |     case 3:
-      |      |     ~~~~
-      |      |     |
-      |      |     (3) ...to here
-      |   NN |       calls_free_2 (ptr);
-      |      |       ~~~~~~~~~~~~~~~~~~
-      |      |       |
-      |      |       (4) calling 'calls_free_2' from 'test_2'
-      |
-      +--> 'calls_free_2': events 5-6
-                  |
-                  |   NN | void calls_free_2 (void *ptr)
-                  |      |      ^~~~~~~~~~~~
-                  |      |      |
-                  |      |      (5) entry to 'calls_free_2'
-                  |   NN | {
-                  |   NN |   free (ptr);
-                  |      |   ~~~~~~~~~~
-                  |      |   |
-                  |      |   (6) first 'free' here
-                  |
-      <-----------+
-      |
+    |
+    |   NN | void test_2 (void *ptr, int a, int b)
+    |      |      ^~~~~~
+    |      |      |
+    |      |      (1) entry to 'test_2'
+    |   NN | {
+    |   NN |   switch (a)
+    |      |   ~~~~~~
+    |      |   |
+    |      |   (2) following 'case 3:' branch...
+    |......
+    |   NN |     case 3:
+    |      |     ~~~~
+    |      |     |
+    |      |     (3) ...to here
+    |   NN |       calls_free_2 (ptr);
+    |      |       ~~~~~~~~~~~~~~~~~~
+    |      |       |
+    |      |       (4) calling 'calls_free_2' from 'test_2'
+    |
+    +--> 'calls_free_2': events 5-6
+           |
+           |   NN | void calls_free_2 (void *ptr)
+           |      |      ^~~~~~~~~~~~
+           |      |      |
+           |      |      (5) entry to 'calls_free_2'
+           |   NN | {
+           |   NN |   free (ptr);
+           |      |   ~~~~~~~~~~
+           |      |   |
+           |      |   (6) first 'free' here
+           |
+    <------+
+    |
   'test_2': events 7-10
-      |
-      |   NN |       calls_free_2 (ptr);
-      |      |       ^~~~~~~~~~~~~~~~~~
-      |      |       |
-      |      |       (7) returning to 'test_2' from 'calls_free_2'
-      |......
-      |   NN |   switch (b)
-      |      |   ~~~~~~
-      |      |   |
-      |      |   (8) following 'default:' branch...
-      |   NN |     {
-      |   NN |     default:
-      |      |     ~~~~~~~
-      |      |     |
-      |      |     (9) ...to here
-      |   NN |       calls_free_2 (ptr);
-      |      |       ~~~~~~~~~~~~~~~~~~
-      |      |       |
-      |      |       (10) passing freed pointer 'ptr' in call to 'calls_free_2' from 'test_2'
-      |
-      +--> 'calls_free_2': events 11-12
-                  |
-                  |   NN | void calls_free_2 (void *ptr)
-                  |      |      ^~~~~~~~~~~~
-                  |      |      |
-                  |      |      (11) entry to 'calls_free_2'
-                  |   NN | {
-                  |   NN |   free (ptr);
-                  |      |   ~~~~~~~~~~
-                  |      |   |
-                  |      |   (12) second 'free' here; first 'free' was at (6)
-                  |
+    |
+    |   NN |       calls_free_2 (ptr);
+    |      |       ^~~~~~~~~~~~~~~~~~
+    |      |       |
+    |      |       (7) returning to 'test_2' from 'calls_free_2'
+    |......
+    |   NN |   switch (b)
+    |      |   ~~~~~~
+    |      |   |
+    |      |   (8) following 'default:' branch...
+    |   NN |     {
+    |   NN |     default:
+    |      |     ~~~~~~~
+    |      |     |
+    |      |     (9) ...to here
+    |   NN |       calls_free_2 (ptr);
+    |      |       ~~~~~~~~~~~~~~~~~~
+    |      |       |
+    |      |       (10) passing freed pointer 'ptr' in call to 'calls_free_2' from 'test_2'
+    |
+    +--> 'calls_free_2': events 11-12
+           |
+           |   NN | void calls_free_2 (void *ptr)
+           |      |      ^~~~~~~~~~~~
+           |      |      |
+           |      |      (11) entry to 'calls_free_2'
+           |   NN | {
+           |   NN |   free (ptr);
+           |      |   ~~~~~~~~~~
+           |      |   |
+           |      |   (12) second 'free' here; first 'free' was at (6)
+           |
   { dg-end-multiline-output "" } */
 
 // TODO: range cases
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-11.c b/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-11.c
index e8a6bcc..d02250f 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-11.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-11.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events" } */
+/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
 
 #include <stdlib.h>
 
@@ -28,66 +28,68 @@ void test (void *ptr)
 }
 
 /* { dg-begin-multiline-output "" }
+   NN |   free (victim);
+      |   ^~~~~~~~~~~~~
   'test': events 1-2
-     |
-     |   NN | void test (void *ptr)
-     |      |      ^~~~
-     |      |      |
-     |      |      (1) entry to 'test'
-     |......
-     |   NN |   may_call_free (ptr);
-     |      |   ~~~~~~~~~~~~~~~~~~~
-     |      |   |
-     |      |   (2) calling 'may_call_free' from 'test'
-     |
-     +--> 'may_call_free': events 3-6
-                 |
-                 |   NN | may_call_free (void *victim)
-                 |      | ^~~~~~~~~~~~~
-                 |      | |
-                 |      | (3) entry to 'may_call_free'
-                 |   NN | {
-                 |   NN |   if (some_condition ())
-                 |      |      ~
-                 |      |      |
-                 |      |      (4) following 'false' branch...
-                 |......
-                 |   NN |   free (victim);
-                 |      |   ~~~~~~~~~~~~~
-                 |      |   |
-                 |      |   (5) ...to here
-                 |      |   (6) first 'free' here
-                 |
-     <-----------+
-     |
+    |
+    |   NN | void test (void *ptr)
+    |      |      ^~~~
+    |      |      |
+    |      |      (1) entry to 'test'
+    |......
+    |   NN |   may_call_free (ptr);
+    |      |   ~~~~~~~~~~~~~~~~~~~
+    |      |   |
+    |      |   (2) calling 'may_call_free' from 'test'
+    |
+    +--> 'may_call_free': events 3-6
+           |
+           |   NN | may_call_free (void *victim)
+           |      | ^~~~~~~~~~~~~
+           |      | |
+           |      | (3) entry to 'may_call_free'
+           |   NN | {
+           |   NN |   if (some_condition ())
+           |      |      ~
+           |      |      |
+           |      |      (4) following 'false' branch...
+           |......
+           |   NN |   free (victim);
+           |      |   ~~~~~~~~~~~~~
+           |      |   |
+           |      |   (5) ...to here
+           |      |   (6) first 'free' here
+           |
+    <------+
+    |
   'test': events 7-8
-     |
-     |   NN |   may_call_free (ptr);
-     |      |   ^~~~~~~~~~~~~~~~~~~
-     |      |   |
-     |      |   (7) returning to 'test' from 'may_call_free'
-     |......
-     |   NN |   may_call_free (ptr);
-     |      |   ~~~~~~~~~~~~~~~~~~~
-     |      |   |
-     |      |   (8) passing freed pointer 'ptr' in call to 'may_call_free' from 'test'
-     |
-     +--> 'may_call_free': events 9-12
-                 |
-                 |   NN | may_call_free (void *victim)
-                 |      | ^~~~~~~~~~~~~
-                 |      | |
-                 |      | (9) entry to 'may_call_free'
-                 |   NN | {
-                 |   NN |   if (some_condition ())
-                 |      |      ~
-                 |      |      |
-                 |      |      (10) following 'false' branch...
-                 |......
-                 |   NN |   free (victim);
-                 |      |   ~~~~~~~~~~~~~
-                 |      |   |
-                 |      |   (11) ...to here
-                 |      |   (12) second 'free' here; first 'free' was at (6)
-                 |
+    |
+    |   NN |   may_call_free (ptr);
+    |      |   ^~~~~~~~~~~~~~~~~~~
+    |      |   |
+    |      |   (7) returning to 'test' from 'may_call_free'
+    |......
+    |   NN |   may_call_free (ptr);
+    |      |   ~~~~~~~~~~~~~~~~~~~
+    |      |   |
+    |      |   (8) passing freed pointer 'ptr' in call to 'may_call_free' from 'test'
+    |
+    +--> 'may_call_free': events 9-12
+           |
+           |   NN | may_call_free (void *victim)
+           |      | ^~~~~~~~~~~~~
+           |      | |
+           |      | (9) entry to 'may_call_free'
+           |   NN | {
+           |   NN |   if (some_condition ())
+           |      |      ~
+           |      |      |
+           |      |      (10) following 'false' branch...
+           |......
+           |   NN |   free (victim);
+           |      |   ~~~~~~~~~~~~~
+           |      |   |
+           |      |   (11) ...to here
+           |      |   (12) second 'free' here; first 'free' was at (6)
+           |
   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-double-free.c b/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-double-free.c
index 7bc46ce..a63e7e8 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-double-free.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-double-free.c
@@ -1,9 +1,6 @@
 /* Example of a multilevel wrapper around malloc/free, with a double-'free'.  */
 
-/* { dg-options "--analyzer -fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fanalyzer-checker=malloc -fanalyzer-verbose-state-changes" } */
-
-/* FIXME: we shouldn't need this.  */
-/* { dg-additional-options "-fanalyzer-fine-grained" } */
+/* { dg-options "--analyzer -fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fanalyzer-checker=malloc -fanalyzer-verbose-state-changes -fdiagnostics-show-caret" } */
 
 #include <stdlib.h>
 
@@ -49,124 +46,126 @@ void test (int i)
 
 /* double-'free'.  */
 /* { dg-begin-multiline-output "" }
+   NN |   free (ptr);
+      |   ^~~~~~~~~~
   'test': events 1-2
-     |
-     |   NN | void test (int i)
-     |      |      ^~~~
-     |      |      |
-     |      |      (1) entry to 'test'
-     |   NN | {
-     |   NN |   boxed_int *obj = make_boxed_int (i);
-     |      |                    ~~~~~~~~~~~~~~~~~~
-     |      |                    |
-     |      |                    (2) calling 'make_boxed_int' from 'test'
-     |
-     +--> 'make_boxed_int': events 3-6
-                  |
-                  |   NN | make_boxed_int (int i)
-                  |      | ^~~~~~~~~~~~~~
-                  |      | |
-                  |      | (3) entry to 'make_boxed_int'
-                  |......
-                  |   NN |   if (!result)
-                  |      |      ~
-                  |      |      |
-                  |      |      (4) following 'false' branch (when 'result' is non-NULL)...
-                  |   NN |     abort ();
-                  |   NN |   result->i = i;
-                  |      |   ~~~~~~~~~~~~~
-                  |      |             |
-                  |      |             (5) ...to here
-                  |   NN |   return result;
-                  |      |          ~~~~~~
-                  |      |          |
-                  |      |          (6) state of '<return-value>': 'start' -> 'nonnull' (origin: NULL)
-                  |
-     <------------+
-     |
+    |
+    |   NN | void test (int i)
+    |      |      ^~~~
+    |      |      |
+    |      |      (1) entry to 'test'
+    |   NN | {
+    |   NN |   boxed_int *obj = make_boxed_int (i);
+    |      |                    ~~~~~~~~~~~~~~~~~~
+    |      |                    |
+    |      |                    (2) calling 'make_boxed_int' from 'test'
+    |
+    +--> 'make_boxed_int': events 3-6
+           |
+           |   NN | make_boxed_int (int i)
+           |      | ^~~~~~~~~~~~~~
+           |      | |
+           |      | (3) entry to 'make_boxed_int'
+           |......
+           |   NN |   if (!result)
+           |      |      ~
+           |      |      |
+           |      |      (4) following 'false' branch (when 'result' is non-NULL)...
+           |   NN |     abort ();
+           |   NN |   result->i = i;
+           |      |   ~~~~~~~~~~~~~
+           |      |             |
+           |      |             (5) ...to here
+           |   NN |   return result;
+           |      |          ~~~~~~
+           |      |          |
+           |      |          (6) state of '<return-value>': 'start' -> 'nonnull' (origin: NULL)
+           |
+    <------+
+    |
   'test': events 7-8
-     |
-     |   NN |   boxed_int *obj = make_boxed_int (i);
-     |      |                    ^~~~~~~~~~~~~~~~~~
-     |      |                    |
-     |      |                    (7) returning to 'test' from 'make_boxed_int'
-     |   NN | 
-     |   NN |   free_boxed_int (obj);
-     |      |   ~~~~~~~~~~~~~~~~~~~~
-     |      |   |
-     |      |   (8) calling 'free_boxed_int' from 'test'
-     |
-     +--> 'free_boxed_int': events 9-10
+    |
+    |   NN |   boxed_int *obj = make_boxed_int (i);
+    |      |                    ^~~~~~~~~~~~~~~~~~
+    |      |                    |
+    |      |                    (7) returning to 'test' from 'make_boxed_int'
+    |   NN | 
+    |   NN |   free_boxed_int (obj);
+    |      |   ~~~~~~~~~~~~~~~~~~~~
+    |      |   |
+    |      |   (8) calling 'free_boxed_int' from 'test'
+    |
+    +--> 'free_boxed_int': events 9-10
+           |
+           |   NN | free_boxed_int (boxed_int *bi)
+           |      | ^~~~~~~~~~~~~~
+           |      | |
+           |      | (9) entry to 'free_boxed_int'
+           |   NN | {
+           |   NN |   wrapped_free (bi);
+           |      |   ~~~~~~~~~~~~~~~~~
+           |      |   |
+           |      |   (10) calling 'wrapped_free' from 'free_boxed_int'
+           |
+           +--> 'wrapped_free': events 11-12
                   |
-                  |   NN | free_boxed_int (boxed_int *bi)
-                  |      | ^~~~~~~~~~~~~~
-                  |      | |
-                  |      | (9) entry to 'free_boxed_int'
+                  |   NN | void wrapped_free (void *ptr)
+                  |      |      ^~~~~~~~~~~~
+                  |      |      |
+                  |      |      (11) entry to 'wrapped_free'
                   |   NN | {
-                  |   NN |   wrapped_free (bi);
-                  |      |   ~~~~~~~~~~~~~~~~~
+                  |   NN |   free (ptr);
+                  |      |   ~~~~~~~~~~
                   |      |   |
-                  |      |   (10) calling 'wrapped_free' from 'free_boxed_int'
+                  |      |   (12) first 'free' here (state of 'ptr': 'nonnull' -> 'freed', origin: NULL)
                   |
-                  +--> 'wrapped_free': events 11-12
-                              |
-                              |   NN | void wrapped_free (void *ptr)
-                              |      |      ^~~~~~~~~~~~
-                              |      |      |
-                              |      |      (11) entry to 'wrapped_free'
-                              |   NN | {
-                              |   NN |   free (ptr);
-                              |      |   ~~~~~~~~~~
-                              |      |   |
-                              |      |   (12) first 'free' here (state of 'ptr': 'nonnull' -> 'freed', origin: NULL)
-                              |
-                  <-----------+
-                  |
-          'free_boxed_int': event 13
-                  |
-                  |   NN |   wrapped_free (bi);
-                  |      |   ^~~~~~~~~~~~~~~~~
-                  |      |   |
-                  |      |   (13) returning to 'free_boxed_int' from 'wrapped_free'
-                  |
-     <------------+
-     |
+           <------+
+           |
+         'free_boxed_int': event 13
+           |
+           |   NN |   wrapped_free (bi);
+           |      |   ^~~~~~~~~~~~~~~~~
+           |      |   |
+           |      |   (13) returning to 'free_boxed_int' from 'wrapped_free'
+           |
+    <------+
+    |
   'test': events 14-15
-     |
-     |   NN |   free_boxed_int (obj);
-     |      |   ^~~~~~~~~~~~~~~~~~~~
-     |      |   |
-     |      |   (14) returning to 'test' from 'free_boxed_int'
-     |   NN | 
-     |   NN |   free_boxed_int (obj);
-     |      |   ~~~~~~~~~~~~~~~~~~~~
-     |      |   |
-     |      |   (15) passing freed pointer 'obj' in call to 'free_boxed_int' from 'test'
-     |
-     +--> 'free_boxed_int': events 16-17
+    |
+    |   NN |   free_boxed_int (obj);
+    |      |   ^~~~~~~~~~~~~~~~~~~~
+    |      |   |
+    |      |   (14) returning to 'test' from 'free_boxed_int'
+    |   NN | 
+    |   NN |   free_boxed_int (obj);
+    |      |   ~~~~~~~~~~~~~~~~~~~~
+    |      |   |
+    |      |   (15) passing freed pointer 'obj' in call to 'free_boxed_int' from 'test'
+    |
+    +--> 'free_boxed_int': events 16-17
+           |
+           |   NN | free_boxed_int (boxed_int *bi)
+           |      | ^~~~~~~~~~~~~~
+           |      | |
+           |      | (16) entry to 'free_boxed_int'
+           |   NN | {
+           |   NN |   wrapped_free (bi);
+           |      |   ~~~~~~~~~~~~~~~~~
+           |      |   |
+           |      |   (17) passing freed pointer 'bi' in call to 'wrapped_free' from 'free_boxed_int'
+           |
+           +--> 'wrapped_free': events 18-19
                   |
-                  |   NN | free_boxed_int (boxed_int *bi)
-                  |      | ^~~~~~~~~~~~~~
-                  |      | |
-                  |      | (16) entry to 'free_boxed_int'
+                  |   NN | void wrapped_free (void *ptr)
+                  |      |      ^~~~~~~~~~~~
+                  |      |      |
+                  |      |      (18) entry to 'wrapped_free'
                   |   NN | {
-                  |   NN |   wrapped_free (bi);
-                  |      |   ~~~~~~~~~~~~~~~~~
+                  |   NN |   free (ptr);
+                  |      |   ~~~~~~~~~~
                   |      |   |
-                  |      |   (17) passing freed pointer 'bi' in call to 'wrapped_free' from 'free_boxed_int'
+                  |      |   (19) second 'free' here; first 'free' was at (12) ('ptr' is in state 'freed')
                   |
-                  +--> 'wrapped_free': events 18-19
-                              |
-                              |   NN | void wrapped_free (void *ptr)
-                              |      |      ^~~~~~~~~~~~
-                              |      |      |
-                              |      |      (18) entry to 'wrapped_free'
-                              |   NN | {
-                              |   NN |   free (ptr);
-                              |      |   ~~~~~~~~~~
-                              |      |   |
-                              |      |   (19) second 'free' here; first 'free' was at (12) ('ptr' is in state 'freed')
-                              |
    { dg-end-multiline-output "" } */
 
 /* TODO: the event describing the allocation is uninteresting and probably
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-unchecked.c b/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-unchecked.c
index e981b9a..a3a3909 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-unchecked.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-unchecked.c
@@ -1,6 +1,6 @@
 /* Example of a multilevel wrapper around malloc, with an unchecked write.  */
 
-/* { dg-options "--analyzer -fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fanalyzer-checker=malloc -fanalyzer-verbose-state-changes" } */
+/* { dg-options "--analyzer -fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fanalyzer-checker=malloc -fdiagnostics-show-caret -fanalyzer-verbose-state-changes" } */
 
 #include <stdlib.h>
 
@@ -24,41 +24,43 @@ make_boxed_int (int i)
 
 /* "dereference of possibly-NULL 'result' [CWE-690]".  */
 /* { dg-begin-multiline-output "" }
+   NN |   result->i = i;
+      |   ~~~~~~~~~~^~~
   'make_boxed_int': events 1-2
-          |
-          |   NN | make_boxed_int (int i)
-          |      | ^~~~~~~~~~~~~~
-          |      | |
-          |      | (1) entry to 'make_boxed_int'
-          |   NN | {
-          |   NN |   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
-          |      |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-          |      |                                    |
-          |      |                                    (2) calling 'wrapped_malloc' from 'make_boxed_int'
-          |
-          +--> 'wrapped_malloc': events 3-4
-                       |
-                       |   NN | void *wrapped_malloc (size_t size)
-                       |      |       ^~~~~~~~~~~~~~
-                       |      |       |
-                       |      |       (3) entry to 'wrapped_malloc'
-                       |   NN | {
-                       |   NN |   return malloc (size);
-                       |      |          ~~~~~~~~~~~~~
-                       |      |          |
-                       |      |          (4) this call could return NULL (state of '<return-value>': 'start' -> 'unchecked', origin: NULL)
-                       |
-          <------------+
-          |
+    |
+    |   NN | make_boxed_int (int i)
+    |      | ^~~~~~~~~~~~~~
+    |      | |
+    |      | (1) entry to 'make_boxed_int'
+    |   NN | {
+    |   NN |   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
+    |      |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    |      |                                    |
+    |      |                                    (2) calling 'wrapped_malloc' from 'make_boxed_int'
+    |
+    +--> 'wrapped_malloc': events 3-4
+           |
+           |   NN | void *wrapped_malloc (size_t size)
+           |      |       ^~~~~~~~~~~~~~
+           |      |       |
+           |      |       (3) entry to 'wrapped_malloc'
+           |   NN | {
+           |   NN |   return malloc (size);
+           |      |          ~~~~~~~~~~~~~
+           |      |          |
+           |      |          (4) this call could return NULL (state of '<return-value>': 'start' -> 'unchecked', origin: NULL)
+           |
+    <------+
+    |
   'make_boxed_int': events 5-6
-          |
-          |   NN |   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
-          |      |                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-          |      |                                    |
-          |      |                                    (5) possible return of NULL to 'make_boxed_int' from 'wrapped_malloc'
-          |   NN |   result->i = i;
-          |      |   ~~~~~~~~~~~~~                     
-          |      |             |
-          |      |             (6) 'result' could be NULL: unchecked value from (4) ('result' is in state 'unchecked')
-          |
+    |
+    |   NN |   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
+    |      |                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+    |      |                                    |
+    |      |                                    (5) possible return of NULL to 'make_boxed_int' from 'wrapped_malloc'
+    |   NN |   result->i = i;
+    |      |   ~~~~~~~~~~~~~                     
+    |      |             |
+    |      |             (6) 'result' could be NULL: unchecked value from (4) ('result' is in state 'unchecked')
+    |
   { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-macro-inline-events.c b/gcc/testsuite/gcc.dg/analyzer/malloc-macro-inline-events.c
index 0d5831c..a34b97b 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-macro-inline-events.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-macro-inline-events.c
@@ -22,24 +22,24 @@ int 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);
-     |      |   ^~~~~~~~~~~~
-     |
+    |
+    |
+    |   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);
-     |      |   ^~~~~~~~~~~~
-     |
+    |
+    |
+    |   NN | #define WRAPPED_FREE(PTR) free(PTR)
+    |      |                           ^~~~~~~~~
+    |      |                           |
+    |      |                           (2) second 'free' here; first 'free' was at (1)
+    |   NN |   WRAPPED_FREE (ptr);
+    |      |   ^~~~~~~~~~~~
+    |
      { dg-end-multiline-output "" } */
 }
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c b/gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c
index 50d8765..6bee885 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-paths-9.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events" } */
+/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
 
 #include <stdlib.h>
 
@@ -9,21 +9,23 @@ void test_1 (void)
   free (ptr); /* { dg-warning "double-'free' of 'ptr'"  } */
 }
 /* { dg-begin-multiline-output "" }
+   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)
@@ -37,58 +39,62 @@ void test_2 (int x, int y)
 
 /* "double-'free' of 'ptr'".  */
 /* { dg-begin-multiline-output "" }
+   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'.  */
 /* { dg-begin-multiline-output "" }
+   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)
@@ -111,172 +117,182 @@ int test_3 (int x, int y)
 
 /* "dereference of possibly-NULL 'ptr'".  */
 /* { dg-begin-multiline-output "" }
+   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
-      |
+    |
+    |   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'".  */
 /* { dg-begin-multiline-output "" }
+   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 "" } */
 
-/* "dereference of freed pointer 'ptr'".  */
-/* { dg-begin-multiline-output "" }
-  'test_3': events 1-3
-      |
-      |   NN |   if (x)
-      |      |      ^
-      |      |      |
-      |      |      (1) following 'true' branch (when 'x != 0')...
-      |   NN |     free (ptr);
-      |      |     ~~~~~~~~~~
-      |      |     |
-      |      |     (2) ...to here
-      |   NN | 
-      |   NN |   *ptr = 19;
-      |      |   ~~~~~~~~~
-      |      |        |
-      |      |        (3) use after 'free' of 'ptr' here
-      |
-   { dg-end-multiline-output "" } */
-/* TODO: this is really a duplicate; can we either eliminate it, or
-   improve the path?  */
-
 /* "use after 'free' of 'ptr'".  */
 /* { dg-begin-multiline-output "" }
+   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 |      to dereference it above
-      |   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'".  */
 /* { dg-begin-multiline-output "" }
+   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 "" } */
 
-/* "dereference of freed pointer 'ptr'".  */
+/* "use after 'free' of 'ptr'".  */
+/* { dg-begin-multiline-output "" }
+   NN |   *ptr = 19;
+      |   ~~~~~^~~~
+  'test_3': events 1-3
+    |
+    |   NN |   if (x)
+    |      |      ^
+    |      |      |
+    |      |      (1) following 'true' branch (when 'x != 0')...
+    |   NN |     free (ptr);
+    |      |     ~~~~~~~~~~
+    |      |     |
+    |      |     (2) ...to here
+    |   NN | 
+    |   NN |   *ptr = 19;
+    |      |   ~~~~~~~~~
+    |      |        |
+    |      |        (3) use after 'free' of 'ptr' here
+    |
+   { dg-end-multiline-output "" } */
+
+/* "use after 'free' of 'ptr'".  */
 /* { dg-begin-multiline-output "" }
+   NN |   return *ptr;
+      |          ^~~~
   'test_3': events 1-5
-      |
-      |   NN |   if (x)
-      |      |      ^
-      |      |      |
-      |      |      (1) following 'false' branch (when 'x == 0')...
-      |......
-      |   NN |   *ptr = 19;
-      |      |   ~~~~~~~~~
-      |      |        |
-      |      |        (2) ...to here
-      |......
-      |   NN |   if (y)
-      |      |      ~
-      |      |      |
-      |      |      (3) following 'true' branch (when 'y != 0')...
-      |   NN |     free (ptr);
-      |      |     ~~~~~~~~~~
-      |      |     |
-      |      |     (4) ...to here
-      |   NN |      to dereference it above
-      |   NN |   return *ptr;
-      |      |          ~~~~
-      |      |          |
-      |      |          (5) use after 'free' of 'ptr' here
-      |
+    |
+    |   NN |   if (x)
+    |      |      ^
+    |      |      |
+    |      |      (1) following 'false' branch (when 'x == 0')...
+    |......
+    |   NN |   *ptr = 19;
+    |      |   ~~~~~~~~~
+    |      |        |
+    |      |        (2) ...to here
+    |......
+    |   NN |   if (y)
+    |      |      ~
+    |      |      |
+    |      |      (3) following 'true' branch (when 'y != 0')...
+    |   NN |     free (ptr);
+    |      |     ~~~~~~~~~~
+    |      |     |
+    |      |     (4) ...to here
+    |   NN |      to dereference it above
+    |   NN |   return *ptr;
+    |      |          ~~~~
+    |      |          |
+    |      |          (5) use after 'free' of 'ptr' here
+    |
    { dg-end-multiline-output "" } */
 /* TODO: this is really a duplicate; can we either eliminate it, or
    improve the path?  */
diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-2.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-2.c
index c5fb915..7afe66e 100644
--- a/gcc/testsuite/gcc.dg/analyzer/setjmp-2.c
+++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-2.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events" } */
+/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
 
 #include <setjmp.h>
 #include <stddef.h>
@@ -33,49 +33,51 @@ void test_2 (void)
 }
 
 /* { dg-begin-multiline-output "" }
+   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 "" } */
 
 void test_3 (void)
diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-3.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-3.c
index f40ee7f..6f67ff5 100644
--- a/gcc/testsuite/gcc.dg/analyzer/setjmp-3.c
+++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-3.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events" } */
+/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
 
 #include <setjmp.h>
 #include <stddef.h>
@@ -34,71 +34,73 @@ void outer (void)
 }
 
 /* { dg-begin-multiline-output "" }
+   NN |       __analyzer_dump_path ();
+      |       ^~~~~~~~~~~~~~~~~~~~~~~
   'outer': event 1
-     |
-     |   NN | void outer (void)
-     |      |      ^~~~~
-     |      |      |
-     |      |      (1) entry to 'outer'
-     |
+    |
+    |   NN | void outer (void)
+    |      |      ^~~~~
+    |      |      |
+    |      |      (1) entry to 'outer'
+    |
   'outer': event 2
-     |
-     |   NN |   i = setjmp(env);
-     |      |       ^~~~~~
-     |      |       |
-     |      |       (2) 'setjmp' called here
-     |
+    |
+    |   NN |   i = setjmp(env);
+    |      |       ^~~~~~
+    |      |       |
+    |      |       (2) 'setjmp' called here
+    |
   'outer': events 3-5
-     |
-     |   NN |   if (i != 0)
-     |      |      ^
-     |      |      |
-     |      |      (3) following 'false' branch (when 'i == 0')...
-     |......
-     |   NN |       foo (1);
-     |      |       ~~~~~~~
-     |      |       |
-     |      |       (4) ...to here
-     |   NN |       inner ();
-     |      |       ~~~~~~~~
-     |      |       |
-     |      |       (5) calling 'inner' from 'outer'
-     |
-     +--> 'inner': events 6-7
-             |
-             |   NN | static void inner (void)
-             |      |             ^~~~~
-             |      |             |
-             |      |             (6) entry to 'inner'
-             |   NN | {
-             |   NN |   longjmp (env, 1);
-             |      |   ~~~~~~~~~~~~~~~~
-             |      |   |
-             |      |   (7) rewinding from 'longjmp' in 'inner'...
-             |
-     <-------+
-     |
+    |
+    |   NN |   if (i != 0)
+    |      |      ^
+    |      |      |
+    |      |      (3) following 'false' branch (when 'i == 0')...
+    |......
+    |   NN |       foo (1);
+    |      |       ~~~~~~~
+    |      |       |
+    |      |       (4) ...to here
+    |   NN |       inner ();
+    |      |       ~~~~~~~~
+    |      |       |
+    |      |       (5) calling 'inner' from 'outer'
+    |
+    +--> 'inner': events 6-7
+           |
+           |   NN | static void inner (void)
+           |      |             ^~~~~
+           |      |             |
+           |      |             (6) entry to 'inner'
+           |   NN | {
+           |   NN |   longjmp (env, 1);
+           |      |   ~~~~~~~~~~~~~~~~
+           |      |   |
+           |      |   (7) rewinding from 'longjmp' in 'inner'...
+           |
+    <------+
+    |
   'outer': event 8
-     |
-     |   NN |   i = setjmp(env);
-     |      |       ^~~~~~
-     |      |       |
-     |      |       (8) ...to 'setjmp' in 'outer' (saved at (2))
-     |
+    |
+    |   NN |   i = setjmp(env);
+    |      |       ^~~~~~
+    |      |       |
+    |      |       (8) ...to 'setjmp' in 'outer' (saved at (2))
+    |
   'outer': events 9-11
-     |
-     |   NN |   if (i != 0)
-     |      |      ^
-     |      |      |
-     |      |      (9) following 'true' branch (when 'i != 0')...
-     |   NN |     {
-     |   NN |       foo (2);
-     |      |       ~~~~~~~
-     |      |       |
-     |      |       (10) ...to here
-     |   NN |       __analyzer_dump_path ();
-     |      |       ~~~~~~~~~~~~~~~~~~~~~~~
-     |      |       |
-     |      |       (11) here
-     |
+    |
+    |   NN |   if (i != 0)
+    |      |      ^
+    |      |      |
+    |      |      (9) following 'true' branch (when 'i != 0')...
+    |   NN |     {
+    |   NN |       foo (2);
+    |      |       ~~~~~~~
+    |      |       |
+    |      |       (10) ...to here
+    |   NN |       __analyzer_dump_path ();
+    |      |       ~~~~~~~~~~~~~~~~~~~~~~~
+    |      |       |
+    |      |       (11) here
+    |
     { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-4.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-4.c
index 01f5208..21bb87e 100644
--- a/gcc/testsuite/gcc.dg/analyzer/setjmp-4.c
+++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-4.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events" } */
+/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
 
 #include <setjmp.h>
 
@@ -29,77 +29,79 @@ int main (void)
 }
 
 /* { dg-begin-multiline-output "" }
+   NN |     __analyzer_dump_path ();
+      |     ^~~~~~~~~~~~~~~~~~~~~~~
   'main': event 1
-     |
-     |   NN | int main (void)
-     |      |     ^~~~
-     |      |     |
-     |      |     (1) entry to 'main'
-     |
+    |
+    |   NN | int main (void)
+    |      |     ^~~~
+    |      |     |
+    |      |     (1) entry to 'main'
+    |
   'main': event 2
-     |
-     |   NN |   if (!setjmp(buf))
-     |      |        ^~~~~~
-     |      |        |
-     |      |        (2) 'setjmp' called here
-     |
+    |
+    |   NN |   if (!setjmp(buf))
+    |      |        ^~~~~~
+    |      |        |
+    |      |        (2) 'setjmp' called here
+    |
   'main': events 3-5
-     |
-     |   NN |   if (!setjmp(buf))
-     |      |      ^
-     |      |      |
-     |      |      (3) following 'true' branch...
-     |   NN |     outer (42);
-     |      |     ~~~~~~~~~~
-     |      |     |
-     |      |     (4) ...to here
-     |      |     (5) calling 'outer' from 'main'
-     |
-     +--> 'outer': events 6-7
-             |
-             |   NN | void outer (int y)
-             |      |      ^~~~~
-             |      |      |
-             |      |      (6) entry to 'outer'
-             |......
-             |   NN |   inner (y);
-             |      |   ~~~~~~~~~
-             |      |   |
-             |      |   (7) calling 'inner' from 'outer'
-             |
-             +--> 'inner': events 8-9
-                     |
-                     |   NN | void inner (int x)
-                     |      |      ^~~~~
-                     |      |      |
-                     |      |      (8) entry to 'inner'
-                     |......
-                     |   NN |   longjmp (buf, 1);
-                     |      |   ~~~~~~~~~~~~~~~~
-                     |      |   |
-                     |      |   (9) rewinding from 'longjmp' in 'inner'...
-                     |
-     <---------------+
-     |
+    |
+    |   NN |   if (!setjmp(buf))
+    |      |      ^
+    |      |      |
+    |      |      (3) following 'true' branch...
+    |   NN |     outer (42);
+    |      |     ~~~~~~~~~~
+    |      |     |
+    |      |     (4) ...to here
+    |      |     (5) calling 'outer' from 'main'
+    |
+    +--> 'outer': events 6-7
+           |
+           |   NN | void outer (int y)
+           |      |      ^~~~~
+           |      |      |
+           |      |      (6) entry to 'outer'
+           |......
+           |   NN |   inner (y);
+           |      |   ~~~~~~~~~
+           |      |   |
+           |      |   (7) calling 'inner' from 'outer'
+           |
+           +--> 'inner': events 8-9
+                  |
+                  |   NN | void inner (int x)
+                  |      |      ^~~~~
+                  |      |      |
+                  |      |      (8) entry to 'inner'
+                  |......
+                  |   NN |   longjmp (buf, 1);
+                  |      |   ~~~~~~~~~~~~~~~~
+                  |      |   |
+                  |      |   (9) rewinding from 'longjmp' in 'inner'...
+                  |
+    <-------------+
+    |
   'main': event 10
-     |
-     |   NN |   if (!setjmp(buf))
-     |      |        ^~~~~~
-     |      |        |
-     |      |        (10) ...to 'setjmp' in 'main' (saved at (2))
-     |
+    |
+    |   NN |   if (!setjmp(buf))
+    |      |        ^~~~~~
+    |      |        |
+    |      |        (10) ...to 'setjmp' in 'main' (saved at (2))
+    |
   'main': events 11-13
-     |
-     |   NN |   if (!setjmp(buf))
-     |      |      ^
-     |      |      |
-     |      |      (11) following 'false' branch...
-     |......
-     |   NN |     __analyzer_dump_path ();
-     |      |     ~~~~~~~~~~~~~~~~~~~~~~~
-     |      |     |
-     |      |     (12) ...to here
-     |      |     (13) here
-     |
+    |
+    |   NN |   if (!setjmp(buf))
+    |      |      ^
+    |      |      |
+    |      |      (11) following 'false' branch...
+    |......
+    |   NN |     __analyzer_dump_path ();
+    |      |     ~~~~~~~~~~~~~~~~~~~~~~~
+    |      |     |
+    |      |     (12) ...to here
+    |      |     (13) here
+    |
     { dg-end-multiline-output "" } */
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-5.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-5.c
index 2180f47..faac51c 100644
--- a/gcc/testsuite/gcc.dg/analyzer/setjmp-5.c
+++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-5.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events" } */
+/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
 
 #include <setjmp.h>
 #include <stddef.h>
@@ -20,44 +20,46 @@ void outer (void)
 }
 
 /* { dg-begin-multiline-output "" }
+   NN |   longjmp (env, 42);
+      |   ^~~~~~~~~~~~~~~~~
   'outer': events 1-2
-     |
-     |   NN | void outer (void)
-     |      |      ^~~~~
-     |      |      |
-     |      |      (1) entry to 'outer'
-     |......
-     |   NN |   inner ();
-     |      |   ~~~~~~~~
-     |      |   |
-     |      |   (2) calling 'inner' from 'outer'
-     |
-     +--> 'inner': event 3
-             |
-             |   NN | static void inner (void)
-             |      |             ^~~~~
-             |      |             |
-             |      |             (3) entry to 'inner'
-             |
-          'inner': event 4
-             |
-             |   NN |   setjmp (env);
-             |      |   ^~~~~~
-             |      |   |
-             |      |   (4) 'setjmp' called here
-             |
-     <-------+
-     |
+    |
+    |   NN | void outer (void)
+    |      |      ^~~~~
+    |      |      |
+    |      |      (1) entry to 'outer'
+    |......
+    |   NN |   inner ();
+    |      |   ~~~~~~~~
+    |      |   |
+    |      |   (2) calling 'inner' from 'outer'
+    |
+    +--> 'inner': event 3
+           |
+           |   NN | static void inner (void)
+           |      |             ^~~~~
+           |      |             |
+           |      |             (3) entry to 'inner'
+           |
+         'inner': event 4
+           |
+           |   NN |   setjmp (env);
+           |      |   ^~~~~~
+           |      |   |
+           |      |   (4) 'setjmp' called here
+           |
+    <------+
+    |
   'outer': events 5-6
-     |
-     |   NN |   inner ();
-     |      |   ^~~~~~~~
-     |      |   |
-     |      |   (5) returning to 'outer' from 'inner'
-     |   NN | 
-     |   NN |   longjmp (env, 42);
-     |      |   ~~~~~~~~~~~~~~~~~
-     |      |   |
-     |      |   (6) here
-     |
+    |
+    |   NN |   inner ();
+    |      |   ^~~~~~~~
+    |      |   |
+    |      |   (5) returning to 'outer' from 'inner'
+    |   NN | 
+    |   NN |   longjmp (env, 42);
+    |      |   ~~~~~~~~~~~~~~~~~
+    |      |   |
+    |      |   (6) here
+    |
     { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-8.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-8.c
index 4f378b6..ad3ef8f 100644
--- a/gcc/testsuite/gcc.dg/analyzer/setjmp-8.c
+++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-8.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events" } */
+/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
 
 #include <setjmp.h>
 #include <stddef.h>
@@ -35,71 +35,73 @@ void outer (void)
 }
 
 /* { dg-begin-multiline-output "" }
+   NN |       __analyzer_dump_path ();
+      |       ^~~~~~~~~~~~~~~~~~~~~~~
   'outer': event 1
-     |
-     |   NN | void outer (void)
-     |      |      ^~~~~
-     |      |      |
-     |      |      (1) entry to 'outer'
-     |
+    |
+    |   NN | void outer (void)
+    |      |      ^~~~~
+    |      |      |
+    |      |      (1) entry to 'outer'
+    |
   'outer': event 2
-     |
-     |   NN |   i = setjmp(env);
-     |      |       ^~~~~~
-     |      |       |
-     |      |       (2) 'setjmp' called here
-     |
+    |
+    |   NN |   i = setjmp(env);
+    |      |       ^~~~~~
+    |      |       |
+    |      |       (2) 'setjmp' called here
+    |
   'outer': events 3-5
-     |
-     |   NN |   if (i != 0)
-     |      |      ^
-     |      |      |
-     |      |      (3) following 'false' branch (when 'i == 0')...
-     |......
-     |   NN |       foo (1);
-     |      |       ~~~~~~~
-     |      |       |
-     |      |       (4) ...to here
-     |   NN |       inner ();
-     |      |       ~~~~~~~~
-     |      |       |
-     |      |       (5) calling 'inner' from 'outer'
-     |
-     +--> 'inner': events 6-7
-             |
-             |   NN | static void inner (void)
-             |      |             ^~~~~
-             |      |             |
-             |      |             (6) entry to 'inner'
-             |......
-             |   NN |   longjmp (env, 0);
-             |      |   ~~~~~~~~~~~~~~~~
-             |      |   |
-             |      |   (7) rewinding from 'longjmp' in 'inner'...
-             |
-     <-------+
-     |
+    |
+    |   NN |   if (i != 0)
+    |      |      ^
+    |      |      |
+    |      |      (3) following 'false' branch (when 'i == 0')...
+    |......
+    |   NN |       foo (1);
+    |      |       ~~~~~~~
+    |      |       |
+    |      |       (4) ...to here
+    |   NN |       inner ();
+    |      |       ~~~~~~~~
+    |      |       |
+    |      |       (5) calling 'inner' from 'outer'
+    |
+    +--> 'inner': events 6-7
+           |
+           |   NN | static void inner (void)
+           |      |             ^~~~~
+           |      |             |
+           |      |             (6) entry to 'inner'
+           |......
+           |   NN |   longjmp (env, 0);
+           |      |   ~~~~~~~~~~~~~~~~
+           |      |   |
+           |      |   (7) rewinding from 'longjmp' in 'inner'...
+           |
+    <------+
+    |
   'outer': event 8
-     |
-     |   NN |   i = setjmp(env);
-     |      |       ^~~~~~
-     |      |       |
-     |      |       (8) ...to 'setjmp' in 'outer' (saved at (2))
-     |
+    |
+    |   NN |   i = setjmp(env);
+    |      |       ^~~~~~
+    |      |       |
+    |      |       (8) ...to 'setjmp' in 'outer' (saved at (2))
+    |
   'outer': events 9-11
-     |
-     |   NN |   if (i != 0)
-     |      |      ^
-     |      |      |
-     |      |      (9) following 'true' branch (when 'i != 0')...
-     |   NN |     {
-     |   NN |       foo (2);
-     |      |       ~~~~~~~
-     |      |       |
-     |      |       (10) ...to here
-     |   NN |       __analyzer_dump_path ();
-     |      |       ~~~~~~~~~~~~~~~~~~~~~~~
-     |      |       |
-     |      |       (11) here
-     |
+    |
+    |   NN |   if (i != 0)
+    |      |      ^
+    |      |      |
+    |      |      (9) following 'true' branch (when 'i != 0')...
+    |   NN |     {
+    |   NN |       foo (2);
+    |      |       ~~~~~~~
+    |      |       |
+    |      |       (10) ...to here
+    |   NN |       __analyzer_dump_path ();
+    |      |       ~~~~~~~~~~~~~~~~~~~~~~~
+    |      |       |
+    |      |       (11) here
+    |
     { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/setjmp-9.c b/gcc/testsuite/gcc.dg/analyzer/setjmp-9.c
index acfc3b7..081ae047 100644
--- a/gcc/testsuite/gcc.dg/analyzer/setjmp-9.c
+++ b/gcc/testsuite/gcc.dg/analyzer/setjmp-9.c
@@ -1,4 +1,4 @@
-/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events" } */
+/* { dg-additional-options "-fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
 
 #include <setjmp.h>
 #include <stddef.h>
@@ -37,71 +37,73 @@ void outer (void)
 }
 
 /* { dg-begin-multiline-output "" }
+   NN |       __analyzer_dump_path ();
+      |       ^~~~~~~~~~~~~~~~~~~~~~~
   'outer': event 1
-     |
-     |   NN | void outer (void)
-     |      |      ^~~~~
-     |      |      |
-     |      |      (1) entry to 'outer'
-     |
+    |
+    |   NN | void outer (void)
+    |      |      ^~~~~
+    |      |      |
+    |      |      (1) entry to 'outer'
+    |
   'outer': event 2
-     |
-     |   NN |   i = setjmp(env);
-     |      |       ^~~~~~
-     |      |       |
-     |      |       (2) 'setjmp' called here
-     |
+    |
+    |   NN |   i = setjmp(env);
+    |      |       ^~~~~~
+    |      |       |
+    |      |       (2) 'setjmp' called here
+    |
   'outer': events 3-5
-     |
-     |   NN |   if (i != 0)
-     |      |      ^
-     |      |      |
-     |      |      (3) following 'false' branch (when 'i == 0')...
-     |......
-     |   NN |       foo (1);
-     |      |       ~~~~~~~
-     |      |       |
-     |      |       (4) ...to here
-     |   NN |       inner ();
-     |      |       ~~~~~~~~
-     |      |       |
-     |      |       (5) calling 'inner' from 'outer'
-     |
-     +--> 'inner': events 6-7
-             |
-             |   NN | static void inner (void)
-             |      |             ^~~~~
-             |      |             |
-             |      |             (6) entry to 'inner'
-             |......
-             |   NN |   longjmp (env, unknown_val);
-             |      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~
-             |      |   |
-             |      |   (7) rewinding from 'longjmp' in 'inner'...
-             |
-     <-------+
-     |
+    |
+    |   NN |   if (i != 0)
+    |      |      ^
+    |      |      |
+    |      |      (3) following 'false' branch (when 'i == 0')...
+    |......
+    |   NN |       foo (1);
+    |      |       ~~~~~~~
+    |      |       |
+    |      |       (4) ...to here
+    |   NN |       inner ();
+    |      |       ~~~~~~~~
+    |      |       |
+    |      |       (5) calling 'inner' from 'outer'
+    |
+    +--> 'inner': events 6-7
+           |
+           |   NN | static void inner (void)
+           |      |             ^~~~~
+           |      |             |
+           |      |             (6) entry to 'inner'
+           |......
+           |   NN |   longjmp (env, unknown_val);
+           |      |   ~~~~~~~~~~~~~~~~~~~~~~~~~~
+           |      |   |
+           |      |   (7) rewinding from 'longjmp' in 'inner'...
+           |
+    <------+
+    |
   'outer': event 8
-     |
-     |   NN |   i = setjmp(env);
-     |      |       ^~~~~~
-     |      |       |
-     |      |       (8) ...to 'setjmp' in 'outer' (saved at (2))
-     |
+    |
+    |   NN |   i = setjmp(env);
+    |      |       ^~~~~~
+    |      |       |
+    |      |       (8) ...to 'setjmp' in 'outer' (saved at (2))
+    |
   'outer': events 9-11
-     |
-     |   NN |   if (i != 0)
-     |      |      ^
-     |      |      |
-     |      |      (9) following 'true' branch (when 'i != 0')...
-     |   NN |     {
-     |   NN |       foo (2);
-     |      |       ~~~~~~~
-     |      |       |
-     |      |       (10) ...to here
-     |   NN |       __analyzer_dump_path ();
-     |      |       ~~~~~~~~~~~~~~~~~~~~~~~
-     |      |       |
-     |      |       (11) here
-     |
+    |
+    |   NN |   if (i != 0)
+    |      |      ^
+    |      |      |
+    |      |      (9) following 'true' branch (when 'i != 0')...
+    |   NN |     {
+    |   NN |       foo (2);
+    |      |       ~~~~~~~
+    |      |       |
+    |      |       (10) ...to here
+    |   NN |       __analyzer_dump_path ();
+    |      |       ~~~~~~~~~~~~~~~~~~~~~~~
+    |      |       |
+    |      |       (11) here
+    |
     { dg-end-multiline-output "" } */
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-default.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-default.c
index d68f856..5712dbd 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-default.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-default.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "" } */
+/* { dg-options "-fdiagnostics-show-caret" } */
 
 #include <stdlib.h>
 
@@ -12,101 +12,103 @@ void wrapped_free (void *ptr)
 {
   free (ptr); /* { dg-warning "double-free of 'ptr' \\\[CWE-415\\]" } */
   /* { dg-begin-multiline-output "" }
+   free (ptr);
+   ^~~~~~~~~~
   'test': events 1-2
-     |
-     | {
-     | ^
-     | |
-     | (1) entering 'test'
-     |   boxed_int *obj = make_boxed_int (i);
-     |                    ~~~~~~~~~~~~~~~~~~
-     |                    |
-     |                    (2) calling 'make_boxed_int'
-     |
-     +--> 'make_boxed_int': events 3-4
+    |
+    | {
+    | ^
+    | |
+    | (1) entering 'test'
+    |   boxed_int *obj = make_boxed_int (i);
+    |                    ~~~~~~~~~~~~~~~~~~
+    |                    |
+    |                    (2) calling 'make_boxed_int'
+    |
+    +--> 'make_boxed_int': events 3-4
+           |
+           | {
+           | ^
+           | |
+           | (3) entering 'make_boxed_int'
+           |   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
+           |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+           |                                    |
+           |                                    (4) calling 'wrapped_malloc'
+           |
+           +--> 'wrapped_malloc': events 5-6
                   |
                   | {
                   | ^
                   | |
-                  | (3) entering 'make_boxed_int'
-                  |   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
-                  |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-                  |                                    |
-                  |                                    (4) calling 'wrapped_malloc'
+                  | (5) entering 'wrapped_malloc'
+                  |   return malloc (size);
+                  |          ~~~~~~~~~~~~~
+                  |          |
+                  |          (6) calling 'malloc'
                   |
-                  +--> 'wrapped_malloc': events 5-6
-                               |
-                               | {
-                               | ^
-                               | |
-                               | (5) entering 'wrapped_malloc'
-                               |   return malloc (size);
-                               |          ~~~~~~~~~~~~~
-                               |          |
-                               |          (6) calling 'malloc'
-                               |
-     <-------------------------+
-     |
+    <-------------+
+    |
   'test': event 7
-     |
-     |   free_boxed_int (obj);
-     |   ^~~~~~~~~~~~~~~~~~~~
-     |   |
-     |   (7) calling 'free_boxed_int'
-     |
-     +--> 'free_boxed_int': events 8-9
+    |
+    |   free_boxed_int (obj);
+    |   ^~~~~~~~~~~~~~~~~~~~
+    |   |
+    |   (7) calling 'free_boxed_int'
+    |
+    +--> 'free_boxed_int': events 8-9
+           |
+           | {
+           | ^
+           | |
+           | (8) entering 'free_boxed_int'
+           |   wrapped_free (bi);
+           |   ~~~~~~~~~~~~~~~~~
+           |   |
+           |   (9) calling 'wrapped_free'
+           |
+           +--> 'wrapped_free': events 10-11
                   |
                   | {
                   | ^
                   | |
-                  | (8) entering 'free_boxed_int'
-                  |   wrapped_free (bi);
-                  |   ~~~~~~~~~~~~~~~~~
+                  | (10) entering 'wrapped_free'
+                  |   free (ptr);
+                  |   ~~~~~~~~~~
                   |   |
-                  |   (9) calling 'wrapped_free'
+                  |   (11) calling 'free'
                   |
-                  +--> 'wrapped_free': events 10-11
-                              |
-                              | {
-                              | ^
-                              | |
-                              | (10) entering 'wrapped_free'
-                              |   free (ptr);
-                              |   ~~~~~~~~~~
-                              |   |
-                              |   (11) calling 'free'
-                              |
-     <------------------------+
-     |
+    <-------------+
+    |
   'test': event 12
-     |
-     |   free_boxed_int (obj);
-     |   ^~~~~~~~~~~~~~~~~~~~
-     |   |
-     |   (12) calling 'free_boxed_int'
-     |
-     +--> 'free_boxed_int': events 13-14
+    |
+    |   free_boxed_int (obj);
+    |   ^~~~~~~~~~~~~~~~~~~~
+    |   |
+    |   (12) calling 'free_boxed_int'
+    |
+    +--> 'free_boxed_int': events 13-14
+           |
+           | {
+           | ^
+           | |
+           | (13) entering 'free_boxed_int'
+           |   wrapped_free (bi);
+           |   ~~~~~~~~~~~~~~~~~
+           |   |
+           |   (14) calling 'wrapped_free'
+           |
+           +--> 'wrapped_free': events 15-16
                   |
                   | {
                   | ^
                   | |
-                  | (13) entering 'free_boxed_int'
-                  |   wrapped_free (bi);
-                  |   ~~~~~~~~~~~~~~~~~
+                  | (15) entering 'wrapped_free'
+                  |   free (ptr);
+                  |   ~~~~~~~~~~
                   |   |
-                  |   (14) calling 'wrapped_free'
+                  |   (16) calling 'free'
                   |
-                  +--> 'wrapped_free': events 15-16
-                              |
-                              | {
-                              | ^
-                              | |
-                              | (15) entering 'wrapped_free'
-                              |   free (ptr);
-                              |   ~~~~~~~~~~
-                              |   |
-                              |   (16) calling 'free'
-                              |
      { dg-end-multiline-output "" } */
 }
 
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-inline-events-1.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-inline-events-1.c
index a457283..430d817 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-inline-events-1.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-inline-events-1.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-fdiagnostics-path-format=inline-events" } */
+/* { dg-options "-fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
 
 #include <stdlib.h>
 
@@ -12,101 +12,103 @@ void wrapped_free (void *ptr)
 {
   free (ptr); /* { dg-warning "double-free of 'ptr' \\\[CWE-415\\]" } */
   /* { dg-begin-multiline-output "" }
+   free (ptr);
+   ^~~~~~~~~~
   'test': events 1-2
-     |
-     | {
-     | ^
-     | |
-     | (1) entering 'test'
-     |   boxed_int *obj = make_boxed_int (i);
-     |                    ~~~~~~~~~~~~~~~~~~
-     |                    |
-     |                    (2) calling 'make_boxed_int'
-     |
-     +--> 'make_boxed_int': events 3-4
+    |
+    | {
+    | ^
+    | |
+    | (1) entering 'test'
+    |   boxed_int *obj = make_boxed_int (i);
+    |                    ~~~~~~~~~~~~~~~~~~
+    |                    |
+    |                    (2) calling 'make_boxed_int'
+    |
+    +--> 'make_boxed_int': events 3-4
+           |
+           | {
+           | ^
+           | |
+           | (3) entering 'make_boxed_int'
+           |   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
+           |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+           |                                    |
+           |                                    (4) calling 'wrapped_malloc'
+           |
+           +--> 'wrapped_malloc': events 5-6
                   |
                   | {
                   | ^
                   | |
-                  | (3) entering 'make_boxed_int'
-                  |   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
-                  |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-                  |                                    |
-                  |                                    (4) calling 'wrapped_malloc'
+                  | (5) entering 'wrapped_malloc'
+                  |   return malloc (size);
+                  |          ~~~~~~~~~~~~~
+                  |          |
+                  |          (6) calling 'malloc'
                   |
-                  +--> 'wrapped_malloc': events 5-6
-                               |
-                               | {
-                               | ^
-                               | |
-                               | (5) entering 'wrapped_malloc'
-                               |   return malloc (size);
-                               |          ~~~~~~~~~~~~~
-                               |          |
-                               |          (6) calling 'malloc'
-                               |
-     <-------------------------+
-     |
+    <-------------+
+    |
   'test': event 7
-     |
-     |   free_boxed_int (obj);
-     |   ^~~~~~~~~~~~~~~~~~~~
-     |   |
-     |   (7) calling 'free_boxed_int'
-     |
-     +--> 'free_boxed_int': events 8-9
+    |
+    |   free_boxed_int (obj);
+    |   ^~~~~~~~~~~~~~~~~~~~
+    |   |
+    |   (7) calling 'free_boxed_int'
+    |
+    +--> 'free_boxed_int': events 8-9
+           |
+           | {
+           | ^
+           | |
+           | (8) entering 'free_boxed_int'
+           |   wrapped_free (bi);
+           |   ~~~~~~~~~~~~~~~~~
+           |   |
+           |   (9) calling 'wrapped_free'
+           |
+           +--> 'wrapped_free': events 10-11
                   |
                   | {
                   | ^
                   | |
-                  | (8) entering 'free_boxed_int'
-                  |   wrapped_free (bi);
-                  |   ~~~~~~~~~~~~~~~~~
+                  | (10) entering 'wrapped_free'
+                  |   free (ptr);
+                  |   ~~~~~~~~~~
                   |   |
-                  |   (9) calling 'wrapped_free'
+                  |   (11) calling 'free'
                   |
-                  +--> 'wrapped_free': events 10-11
-                              |
-                              | {
-                              | ^
-                              | |
-                              | (10) entering 'wrapped_free'
-                              |   free (ptr);
-                              |   ~~~~~~~~~~
-                              |   |
-                              |   (11) calling 'free'
-                              |
-     <------------------------+
-     |
+    <-------------+
+    |
   'test': event 12
-     |
-     |   free_boxed_int (obj);
-     |   ^~~~~~~~~~~~~~~~~~~~
-     |   |
-     |   (12) calling 'free_boxed_int'
-     |
-     +--> 'free_boxed_int': events 13-14
+    |
+    |   free_boxed_int (obj);
+    |   ^~~~~~~~~~~~~~~~~~~~
+    |   |
+    |   (12) calling 'free_boxed_int'
+    |
+    +--> 'free_boxed_int': events 13-14
+           |
+           | {
+           | ^
+           | |
+           | (13) entering 'free_boxed_int'
+           |   wrapped_free (bi);
+           |   ~~~~~~~~~~~~~~~~~
+           |   |
+           |   (14) calling 'wrapped_free'
+           |
+           +--> 'wrapped_free': events 15-16
                   |
                   | {
                   | ^
                   | |
-                  | (13) entering 'free_boxed_int'
-                  |   wrapped_free (bi);
-                  |   ~~~~~~~~~~~~~~~~~
+                  | (15) entering 'wrapped_free'
+                  |   free (ptr);
+                  |   ~~~~~~~~~~
                   |   |
-                  |   (14) calling 'wrapped_free'
+                  |   (16) calling 'free'
                   |
-                  +--> 'wrapped_free': events 15-16
-                              |
-                              | {
-                              | ^
-                              | |
-                              | (15) entering 'wrapped_free'
-                              |   free (ptr);
-                              |   ~~~~~~~~~~
-                              |   |
-                              |   (16) calling 'free'
-                              |
      { dg-end-multiline-output "" } */
 }
 
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-inline-events-2.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-inline-events-2.c
index 2c7e401..c2bfabe 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-inline-events-2.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-inline-events-2.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-fdiagnostics-path-format=inline-events" } */
+/* { dg-options "-fdiagnostics-path-format=inline-events -fdiagnostics-show-caret" } */
 
 /* Verify that 'inline-events' copes gracefully with events with an
    unknown location.  */
@@ -17,105 +17,108 @@ void wrapped_free (void *ptr)
 {
   free (ptr); /* { dg-warning "double-free of 'ptr' \\\[CWE-415\\]" } */
   /* { dg-begin-multiline-output "" }
+   free (ptr);
+   ^~~~~~~~~~
   'test': events 1-2
-     |
-     | {
-     | ^
-     | |
-     | (1) entering 'test'
-     |   boxed_int *obj = make_boxed_int (i);
-     |                    ~~~~~~~~~~~~~~~~~~
-     |                    |
-     |                    (2) calling 'make_boxed_int'
-     |
-     +--> 'make_boxed_int': events 3-4
+    |
+    | {
+    | ^
+    | |
+    | (1) entering 'test'
+    |   boxed_int *obj = make_boxed_int (i);
+    |                    ~~~~~~~~~~~~~~~~~~
+    |                    |
+    |                    (2) calling 'make_boxed_int'
+    |
+    +--> 'make_boxed_int': events 3-4
+           |
+           | {
+           | ^
+           | |
+           | (3) entering 'make_boxed_int'
+           |   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
+           |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+           |                                    |
+           |                                    (4) calling 'wrapped_malloc'
+           |
+           +--> 'wrapped_malloc': events 5-6
                   |
                   | {
                   | ^
                   | |
-                  | (3) entering 'make_boxed_int'
-                  |   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
-                  |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-                  |                                    |
-                  |                                    (4) calling 'wrapped_malloc'
+                  | (5) entering 'wrapped_malloc'
+                  |   return malloc (size);
+                  |          ~~~~~~~~~~~~~
+                  |          |
+                  |          (6) calling 'malloc'
                   |
-                  +--> 'wrapped_malloc': events 5-6
-                               |
-                               | {
-                               | ^
-                               | |
-                               | (5) entering 'wrapped_malloc'
-                               |   return malloc (size);
-                               |          ~~~~~~~~~~~~~
-                               |          |
-                               |          (6) calling 'malloc'
-                               |
-     <-------------------------+
-     |
+    <-------------+
+    |
   'test': event 7
-     |
-     |   free_boxed_int (obj);
-     |   ^~~~~~~~~~~~~~~~~~~~
-     |   |
-     |   (7) calling 'free_boxed_int'
-     |
-     +--> 'free_boxed_int': events 8-9
+    |
+    |   free_boxed_int (obj);
+    |   ^~~~~~~~~~~~~~~~~~~~
+    |   |
+    |   (7) calling 'free_boxed_int'
+    |
+    +--> 'free_boxed_int': events 8-9
+           |
+           | {
+           | ^
+           | |
+           | (8) entering 'free_boxed_int'
+           |   wrapped_free (bi);
+           |   ~~~~~~~~~~~~~~~~~
+           |   |
+           |   (9) calling 'wrapped_free'
+           |
+           +--> 'wrapped_free': events 10-11
                   |
                   | {
                   | ^
                   | |
-                  | (8) entering 'free_boxed_int'
-                  |   wrapped_free (bi);
-                  |   ~~~~~~~~~~~~~~~~~
+                  | (10) entering 'wrapped_free'
+                  |   free (ptr);
+                  |   ~~~~~~~~~~
                   |   |
-                  |   (9) calling 'wrapped_free'
+                  |   (11) calling 'free'
                   |
-                  +--> 'wrapped_free': events 10-11
-                              |
-                              | {
-                              | ^
-                              | |
-                              | (10) entering 'wrapped_free'
-                              |   free (ptr);
-                              |   ~~~~~~~~~~
-                              |   |
-                              |   (11) calling 'free'
-                              |
-     <------------------------+
-     |
+    <-------------+
+    |
   'test': event 12
-     |
-     | (12): calling 'missing_location'
-     |
+    |
+    |cc1:
+    | (12): calling 'missing_location'
+    |
   'test': event 13
-     |
-     |   free_boxed_int (obj);
-     |   ^~~~~~~~~~~~~~~~~~~~
-     |   |
-     |   (13) calling 'free_boxed_int'
-     |
-     +--> 'free_boxed_int': events 14-15
+    |
+    |   free_boxed_int (obj);
+    |   ^~~~~~~~~~~~~~~~~~~~
+    |   |
+    |   (13) calling 'free_boxed_int'
+    |
+    +--> 'free_boxed_int': events 14-15
+           |
+           | {
+           | ^
+           | |
+           | (14) entering 'free_boxed_int'
+           |   wrapped_free (bi);
+           |   ~~~~~~~~~~~~~~~~~
+           |   |
+           |   (15) calling 'wrapped_free'
+           |
+           +--> 'wrapped_free': events 16-17
                   |
                   | {
                   | ^
                   | |
-                  | (14) entering 'free_boxed_int'
-                  |   wrapped_free (bi);
-                  |   ~~~~~~~~~~~~~~~~~
+                  | (16) entering 'wrapped_free'
+                  |   free (ptr);
+                  |   ~~~~~~~~~~
                   |   |
-                  |   (15) calling 'wrapped_free'
+                  |   (17) calling 'free'
                   |
-                  +--> 'wrapped_free': events 16-17
-                              |
-                              | {
-                              | ^
-                              | |
-                              | (16) entering 'wrapped_free'
-                              |   free (ptr);
-                              |   ~~~~~~~~~~
-                              |   |
-                              |   (17) calling 'free'
-                              |
      { dg-end-multiline-output "" } */
 }
 
diff --git a/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-inline-events-3.c b/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-inline-events-3.c
index 969a060..5e7b099 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-inline-events-3.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-path-format-inline-events-3.c
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-fdiagnostics-path-format=inline-events -fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers" } */
+/* { dg-options "-fdiagnostics-path-format=inline-events -fdiagnostics-show-line-numbers -fdiagnostics-nn-line-numbers -fdiagnostics-show-caret" } */
 
 /* Verify the interaction of inline-events with line numbers.  */
 
@@ -16,105 +16,108 @@ void wrapped_free (void *ptr)
 {
   free (ptr); /* { dg-warning "double-free of 'ptr' \\\[CWE-415\\]" } */
   /* { dg-begin-multiline-output "" }
+   NN |   free (ptr);
+      |   ^~~~~~~~~~
   'test': events 1-2
-     |
-     |   NN | {
-     |      | ^
-     |      | |
-     |      | (1) entering 'test'
-     |   NN |   boxed_int *obj = make_boxed_int (i);
-     |      |                    ~~~~~~~~~~~~~~~~~~
-     |      |                    |
-     |      |                    (2) calling 'make_boxed_int'
-     |
-     +--> 'make_boxed_int': events 3-4
+    |
+    |   NN | {
+    |      | ^
+    |      | |
+    |      | (1) entering 'test'
+    |   NN |   boxed_int *obj = make_boxed_int (i);
+    |      |                    ~~~~~~~~~~~~~~~~~~
+    |      |                    |
+    |      |                    (2) calling 'make_boxed_int'
+    |
+    +--> 'make_boxed_int': events 3-4
+           |
+           |   NN | {
+           |      | ^
+           |      | |
+           |      | (3) entering 'make_boxed_int'
+           |   NN |   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
+           |      |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+           |      |                                    |
+           |      |                                    (4) calling 'wrapped_malloc'
+           |
+           +--> 'wrapped_malloc': events 5-6
                   |
                   |   NN | {
                   |      | ^
                   |      | |
-                  |      | (3) entering 'make_boxed_int'
-                  |   NN |   boxed_int *result = (boxed_int *)wrapped_malloc (sizeof (boxed_int));
-                  |      |                                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-                  |      |                                    |
-                  |      |                                    (4) calling 'wrapped_malloc'
+                  |      | (5) entering 'wrapped_malloc'
+                  |   NN |   return malloc (size);
+                  |      |          ~~~~~~~~~~~~~
+                  |      |          |
+                  |      |          (6) calling 'malloc'
                   |
-                  +--> 'wrapped_malloc': events 5-6
-                               |
-                               |   NN | {
-                               |      | ^
-                               |      | |
-                               |      | (5) entering 'wrapped_malloc'
-                               |   NN |   return malloc (size);
-                               |      |          ~~~~~~~~~~~~~
-                               |      |          |
-                               |      |          (6) calling 'malloc'
-                               |
-     <-------------------------+
-     |
+    <-------------+
+    |
   'test': event 7
-     |
-     |   NN |   free_boxed_int (obj);
-     |      |   ^~~~~~~~~~~~~~~~~~~~
-     |      |   |
-     |      |   (7) calling 'free_boxed_int'
-     |
-     +--> 'free_boxed_int': events 8-9
+    |
+    |   NN |   free_boxed_int (obj);
+    |      |   ^~~~~~~~~~~~~~~~~~~~
+    |      |   |
+    |      |   (7) calling 'free_boxed_int'
+    |
+    +--> 'free_boxed_int': events 8-9
+           |
+           |   NN | {
+           |      | ^
+           |      | |
+           |      | (8) entering 'free_boxed_int'
+           |   NN |   wrapped_free (bi);
+           |      |   ~~~~~~~~~~~~~~~~~
+           |      |   |
+           |      |   (9) calling 'wrapped_free'
+           |
+           +--> 'wrapped_free': events 10-11
                   |
                   |   NN | {
                   |      | ^
                   |      | |
-                  |      | (8) entering 'free_boxed_int'
-                  |   NN |   wrapped_free (bi);
-                  |      |   ~~~~~~~~~~~~~~~~~
+                  |      | (10) entering 'wrapped_free'
+                  |   NN |   free (ptr);
+                  |      |   ~~~~~~~~~~
                   |      |   |
-                  |      |   (9) calling 'wrapped_free'
+                  |      |   (11) calling 'free'
                   |
-                  +--> 'wrapped_free': events 10-11
-                              |
-                              |   NN | {
-                              |      | ^
-                              |      | |
-                              |      | (10) entering 'wrapped_free'
-                              |   NN |   free (ptr);
-                              |      |   ~~~~~~~~~~
-                              |      |   |
-                              |      |   (11) calling 'free'
-                              |
-     <------------------------+
-     |
+    <-------------+
+    |
   'test': event 12
-     |
-     | (12): calling 'missing_location'
-     |
+    |
+    |cc1:
+    | (12): calling 'missing_location'
+    |
   'test': event 13
-     |
-     |   NN |   free_boxed_int (obj);
-     |      |   ^~~~~~~~~~~~~~~~~~~~
-     |      |   |
-     |      |   (13) calling 'free_boxed_int'
-     |
-     +--> 'free_boxed_int': events 14-15
+    |
+    |   NN |   free_boxed_int (obj);
+    |      |   ^~~~~~~~~~~~~~~~~~~~
+    |      |   |
+    |      |   (13) calling 'free_boxed_int'
+    |
+    +--> 'free_boxed_int': events 14-15
+           |
+           |   NN | {
+           |      | ^
+           |      | |
+           |      | (14) entering 'free_boxed_int'
+           |   NN |   wrapped_free (bi);
+           |      |   ~~~~~~~~~~~~~~~~~
+           |      |   |
+           |      |   (15) calling 'wrapped_free'
+           |
+           +--> 'wrapped_free': events 16-17
                   |
                   |   NN | {
                   |      | ^
                   |      | |
-                  |      | (14) entering 'free_boxed_int'
-                  |   NN |   wrapped_free (bi);
-                  |      |   ~~~~~~~~~~~~~~~~~
+                  |      | (16) entering 'wrapped_free'
+                  |   NN |   free (ptr);
+                  |      |   ~~~~~~~~~~
                   |      |   |
-                  |      |   (15) calling 'wrapped_free'
+                  |      |   (17) calling 'free'
                   |
-                  +--> 'wrapped_free': events 16-17
-                              |
-                              |   NN | {
-                              |      | ^
-                              |      | |
-                              |      | (16) entering 'wrapped_free'
-                              |   NN |   free (ptr);
-                              |      |   ~~~~~~~~~~
-                              |      |   |
-                              |      |   (17) calling 'free'
-                              |
      { 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 9695fcb..391aeb9 100644
--- a/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-2.c
+++ b/gcc/testsuite/gcc.dg/plugin/diagnostic-test-paths-2.c
@@ -35,24 +35,22 @@ make_a_list_of_random_ints_badly(PyObject *self,
   /* { dg-begin-multiline-output "" }
    29 |     PyList_Append(list, item);
       |     ^~~~~~~~~~~~~~~~~~~~~~~~~
-     { dg-end-multiline-output "" } */
-  /* { dg-begin-multiline-output "" }
   '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 09c46f3..d044152 100644
--- a/gcc/tree-diagnostic-path.cc
+++ b/gcc/tree-diagnostic-path.cc
@@ -156,11 +156,14 @@ class path_summary
       /* Emit a span indicating the filename (and line/column) if the
 	 line has changed relative to the last call to
 	 diagnostic_show_locus.  */
-      expanded_location exploc
-	= linemap_client_expand_location_to_spelling_point
+      if (dc->show_caret)
+	{
+	  expanded_location exploc
+	    = linemap_client_expand_location_to_spelling_point
 	    (initial_loc, LOCATION_ASPECT_CARET);
-      if (exploc.file != LOCATION_FILE (dc->last_location))
-	dc->start_span (dc, exploc);
+	  if (exploc.file != LOCATION_FILE (dc->last_location))
+	    dc->start_span (dc, exploc);
+	}
 
       /* If we have an UNKNOWN_LOCATION (or BUILTINS_LOCATION) as the
 	 primary location for an event, diagnostic_show_locus won't print
@@ -300,25 +303,7 @@ path_summary::print (diagnostic_context *dc, bool show_depths) const
 {
   pretty_printer *pp = dc->printer;
 
-  auto_vec<int> name_lengths;
-
-  /* Populate name_lengths.  */
-  {
-    pretty_printer *tmp_pp = pp->clone ();
-    pp_show_color (tmp_pp) = 0;
-    int i;
-    event_range *range;
-    FOR_EACH_VEC_ELT (m_ranges, i, range)
-      {
-	print_fndecl (tmp_pp, range->m_fndecl, false);
-	/* We want the length of the quoted decl in characters, not in bytes.
-	   For now, we get the length of the unquoted decl (in bytes), hope
-	   it's ASCII, and add 2 for the quotes.  */
-	name_lengths.safe_push (strlen (pp_formatted_text (tmp_pp)) + 2);
-	pp_clear_output_area (tmp_pp);
-      }
-    delete tmp_pp;
-  }
+  const int per_frame_indent = 2;
 
   const char *const line_color = "path";
   const char *start_line_color
@@ -365,11 +350,9 @@ path_summary::print (diagnostic_context *dc, bool show_depths) const
 	pp_printf (pp, " (depth %i)", range->m_stack_depth);
       pp_newline (pp);
 
-      int midpoint = name_lengths[i] / 2;
-
       /* Print a run of events.  */
       {
-	write_indent (pp, cur_indent + midpoint);
+	write_indent (pp, cur_indent + per_frame_indent);
 	pp_string (pp, start_line_color);
 	pp_string (pp, "|");
 	pp_string (pp, end_line_color);
@@ -379,7 +362,7 @@ path_summary::print (diagnostic_context *dc, bool show_depths) const
 	char *prefix;
 	{
 	  pretty_printer tmp_pp;
-	  write_indent (&tmp_pp, cur_indent + midpoint);
+	  write_indent (&tmp_pp, cur_indent + per_frame_indent);
 	  pp_string (&tmp_pp, start_line_color);
 	  pp_string (&tmp_pp, "|");
 	  pp_string (&tmp_pp, end_line_color);
@@ -390,7 +373,7 @@ path_summary::print (diagnostic_context *dc, bool show_depths) const
 	range->print (dc);
 	pp_set_prefix (pp, saved_prefix);
 
-	write_indent (pp, cur_indent + midpoint);
+	write_indent (pp, cur_indent + per_frame_indent);
 	pp_string (pp, start_line_color);
 	pp_string (pp, "|");
 	pp_string (pp, end_line_color);
@@ -410,20 +393,19 @@ path_summary::print (diagnostic_context *dc, bool show_depths) const
 		 "     <------------ +\n"
 		 "     |\n".  */
 
-	      int next_midpoint = name_lengths[i + 1] / 2;
-
 	      gcc_assert (vbar_column_for_depth.get
 			  (next_range->m_stack_depth));
 
 	      int vbar_for_next_frame
 		= *vbar_column_for_depth.get (next_range->m_stack_depth);
 
-	      int indent_for_next_frame = vbar_for_next_frame - next_midpoint;
+	      int indent_for_next_frame
+		= vbar_for_next_frame - per_frame_indent;
 	      write_indent (pp, vbar_for_next_frame);
 	      pp_string (pp, start_line_color);
 	      pp_character (pp, '<');
-	      for (int i = indent_for_next_frame + next_midpoint;
-		   i < cur_indent + midpoint - 1; i++)
+	      for (int i = indent_for_next_frame + per_frame_indent;
+		   i < cur_indent + per_frame_indent - 1; i++)
 		pp_character (pp, '-');
 	      pp_character (pp, '+');
 	      pp_string (pp, end_line_color);
@@ -442,8 +424,8 @@ path_summary::print (diagnostic_context *dc, bool show_depths) const
 	      gcc_assert (range->m_stack_depth != EMPTY);
 	      gcc_assert (range->m_stack_depth != DELETED);
 	      vbar_column_for_depth.put (range->m_stack_depth,
-					 cur_indent + midpoint);
-	      cur_indent += midpoint;
+					 cur_indent + per_frame_indent);
+	      cur_indent += per_frame_indent;
 	    }
 
 	}
@@ -651,54 +633,54 @@ test_interprocedural_path_1 (pretty_printer *event_pp)
   summary.print (&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"
+     "    | (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"
-     "                  | (3): entering `make_boxed_int'\n"
-     "                  | (4): calling `wrapped_malloc'\n"
+     "                  | (5): entering `wrapped_malloc'\n"
+     "                  | (6): calling malloc\n"
      "                  |\n"
-     "                  +--> `wrapped_malloc': events 5-6 (depth 2)\n"
-     "                               |\n"
-     "                               | (5): entering `wrapped_malloc'\n"
-     "                               | (6): calling malloc\n"
-     "                               |\n"
-     "     <-------------------------+\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"
+     "    | (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"
-     "                  | (9): entering `free_boxed_int'\n"
-     "                  | (10): calling `wrapped_free'\n"
+     "                  | (11): entering `wrapped_free'\n"
+     "                  | (12): calling free\n"
      "                  |\n"
-     "                  +--> `wrapped_free': events 11-12 (depth 2)\n"
-     "                              |\n"
-     "                              | (11): entering `wrapped_free'\n"
-     "                              | (12): calling free\n"
-     "                              |\n"
-     "     <------------------------+\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"
+     "    | (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"
-     "                  +--> `wrapped_free': events 17-18 (depth 2)\n"
-     "                              |\n"
-     "                              | (17): entering `wrapped_free'\n"
-     "                              | (18): calling free\n"
-     "                              |\n",
+     "                  | (17): entering `wrapped_free'\n"
+     "                  | (18): calling free\n"
+     "                  |\n",
      pp_formatted_text (dc.printer));
 }
 
@@ -785,24 +767,24 @@ test_recursion (pretty_printer *event_pp)
   summary.print (&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",
+     "    |\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));
 }
 
-- 
1.8.5.3

