From c50d891fa7ef3dfbad38d9215365455c297a86b5 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Fri, 26 Jul 2019 20:12:24 -0400
Subject: [PATCH 033/124] FIXME: put state change messages before cfg edge
 events

---
 gcc/analyzer/impl-4.cc                         | 42 ++++++++++++++++++--------
 gcc/testsuite/gcc.dg/analyzer/file-1.c         |  2 +-
 gcc/testsuite/gcc.dg/analyzer/malloc-paths-4.c |  6 ++--
 gcc/testsuite/gcc.dg/analyzer/malloc-paths-5.c |  6 ++--
 4 files changed, 36 insertions(+), 20 deletions(-)

diff --git a/gcc/analyzer/impl-4.cc b/gcc/analyzer/impl-4.cc
index e23efc2..956f4cf 100644
--- a/gcc/analyzer/impl-4.cc
+++ b/gcc/analyzer/impl-4.cc
@@ -5067,6 +5067,35 @@ diagnostic_manager::add_events_for_eedge (const exploded_edge &eedge,
   const int dst_stack_depth = dst_point.get_stack_depth ();
   const program_state &src_state = src_node->get_state ();
   const program_state &dst_state = dst_node->get_state ();
+
+  /* Add state change events for the states that have changed.
+     We add these before events for superedges, so that if we have a
+     state_change_event due to following an edge, we'll get this sequence
+     of events:
+
+      | if (!ptr)
+      |    ~
+      |    |
+      |    (1) assuming 'ptr’ is non-NULL  (state_change_event)
+      |    (2) following ‘false’ branch... (start_cfg_edge_event)
+     ...
+      | do_something (ptr);
+      | ~~~~~~~~~~~~~^~~~~
+      |              |
+      |              (3) ...to here        (end_cfg_edge_event).  */
+  gcc_assert (src_state.m_checker_states.length ()
+	      == ext_state.m_checkers.length ());
+  gcc_assert (dst_state.m_checker_states.length ()
+	      == ext_state.m_checkers.length ());
+  for (unsigned i = 0; i < ext_state.m_checkers.length (); i++)
+    {
+      const state_machine &sm = ext_state.get_sm (i);
+      const sm_state_map &src_smap = *src_state.m_checker_states[i];
+      const sm_state_map &dst_smap = *dst_state.m_checker_states[i];
+      add_state_change_events (eedge, sm, src_smap, dst_smap, emission_path);
+    }
+
+  /* Add events for superedges, function entries, and for statements.  */
   switch (dst_point.m_kind)
     {
     default:
@@ -5094,19 +5123,6 @@ diagnostic_manager::add_events_for_eedge (const exploded_edge &eedge,
 			      dst_stack_depth, dst_state));
       break;
     }
-
-  /* Add state change events for the states that have changed.  */
-  gcc_assert (src_state.m_checker_states.length ()
-	      == ext_state.m_checkers.length ());
-  gcc_assert (dst_state.m_checker_states.length ()
-	      == ext_state.m_checkers.length ());
-  for (unsigned i = 0; i < ext_state.m_checkers.length (); i++)
-    {
-      const state_machine &sm = ext_state.get_sm (i);
-      const sm_state_map &src_smap = *src_state.m_checker_states[i];
-      const sm_state_map &dst_smap = *dst_state.m_checker_states[i];
-      add_state_change_events (eedge, sm, src_smap, dst_smap, emission_path);
-    }
 }
 
 /* Subroutine of diagnostic_manager::add_events_for_eedge
diff --git a/gcc/testsuite/gcc.dg/analyzer/file-1.c b/gcc/testsuite/gcc.dg/analyzer/file-1.c
index 722e36e..91d9685 100644
--- a/gcc/testsuite/gcc.dg/analyzer/file-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/file-1.c
@@ -7,7 +7,7 @@ test_1 (const char *path)
   if (!f)
     return;
 
-  fclose (f); /* { dg-message "\\(3\\) \\.\\.\\.to here" } */
+  fclose (f); /* { dg-message "\\(4\\) \\.\\.\\.to here" } */
   /* { dg-message "\\(5\\) first 'fclose' here" "" { target *-*-* } .-1 } */
   fclose (f); /* { dg-warning "double 'fclose' of FILE 'f'" } */ 
   /* { dg-message "second 'fclose' here; first 'fclose' was at \\(5\\)" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-paths-4.c b/gcc/testsuite/gcc.dg/analyzer/malloc-paths-4.c
index bf7d0d4..3b698a6 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-paths-4.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-paths-4.c
@@ -13,8 +13,8 @@ int *test_4 (void)
 
   /* { dg-warning "use of NULL 'ptr'" "" { target *-*-* } on_null_ptr } */
   /* { dg-message "\\(1\\) allocated here" "" { target *-*-* } malloc } */
-  /* { dg-message "\\(2\\) following 'false' branch\\.\\.\\." "" { target *-*-* } cond } */
-  /* { dg-message "\\(3\\) \\.\\.\\.to here" "" { target *-*-* } on_null_ptr } */
-  /* { dg-message "\\(4\\) assuming 'ptr' is NULL" "" { target *-*-* } cond } */
+  /* { dg-message "\\(2\\) assuming 'ptr' is NULL" "" { target *-*-* } cond } */
+  /* { dg-message "\\(3\\) following 'false' branch\\.\\.\\." "" { target *-*-* } cond } */
+  /* { dg-message "\\(4\\) \\.\\.\\.to here" "" { target *-*-* } on_null_ptr } */
   /* { dg-message "\\(5\\) here \\('ptr' is in state 'null'\\)" "" { target *-*-* } on_null_ptr } */
 }
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-paths-5.c b/gcc/testsuite/gcc.dg/analyzer/malloc-paths-5.c
index 58f88f2..71dd0a22 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-paths-5.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-paths-5.c
@@ -31,9 +31,9 @@ int test (const char *filename, int flag)
 
   /* { dg-warning "double-free of 'p'" "" { target *-*-* } second_free_of_p } */
   /* { dg-message "\\(1\\) allocated here" "" { target *-*-* } malloc_of_p } */
-  /* { dg-message "\\(2\\) following 'false' branch\\.\\.\\." "" { target *-*-* } test_of_p } */
-  /* { dg-message "\\(3\\) \\.\\.\\.to here" "" { target *-*-* } malloc_of_q } */
-  /* { dg-message "\\(4\\) assuming 'p' is non-NULL" "" { target *-*-* } test_of_p } */
+  /* { dg-message "\\(2\\) assuming 'p' is non-NULL" "" { target *-*-* } test_of_p } */
+  /* { dg-message "\\(3\\) following 'false' branch\\.\\.\\." "" { target *-*-* } test_of_p } */
+  /* { dg-message "\\(4\\) \\.\\.\\.to here" "" { target *-*-* } malloc_of_q } */
   /* { dg-message "\\(5\\) following 'true' branch\\.\\.\\." "" { target *-*-* } test_of_q } */
   /* { dg-message "\\(6\\) \\.\\.\\.to here" "" { target *-*-* } first_free_of_p } */
   /* { dg-message "\\(7\\) first 'free' here" "" { target *-*-* } first_free_of_p } */
-- 
1.8.5.3

