From 6a53abcb32ab4ebd928220d66f411c60ba5318d9 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Mon, 29 Jul 2019 11:20:18 -0400
Subject: [PATCH 37/96] FIXME: precision-of-wording for null warnings

---
 gcc/analyzer/sm-malloc.cc                          | 26 +++++++++++++++++-----
 gcc/testsuite/gcc.dg/analyzer/attribute-nonnull.c  |  8 +++----
 gcc/testsuite/gcc.dg/analyzer/malloc-2.c           | 23 +++++++++++++++++++
 .../gcc.dg/analyzer/malloc-ipa-8-unchecked.c       |  2 +-
 4 files changed, 49 insertions(+), 10 deletions(-)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/malloc-2.c

diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc
index a3f0736..7eab9f9 100644
--- a/gcc/analyzer/sm-malloc.cc
+++ b/gcc/analyzer/sm-malloc.cc
@@ -220,7 +220,10 @@ public:
   {
     if (change.m_old_state == m_sm.m_start
 	&& change.m_new_state == m_sm.m_unchecked)
-      return label_text::borrow ("this call could return NULL");
+      {
+	m_origin_of_unchecked_event = change.m_event_id;
+	return label_text::borrow ("this call could return NULL");
+      }
     return malloc_diagnostic::describe_state_change (change);
   }
 
@@ -232,6 +235,9 @@ public:
 			      info.m_caller_fndecl, info.m_callee_fndecl);
     return label_text ();
   }
+
+protected:
+  event_id_t m_origin_of_unchecked_event;
 };
 
 /* Concrete subclass for describing dereference of a possible NULL
@@ -258,7 +264,11 @@ public:
   /* FIXME.  */
   label_text describe_final_event (const evdesc::final_event &ev) FINAL OVERRIDE
   {
-    return formatted_print ("%qE could be NULL", ev.m_expr);
+    if (m_origin_of_unchecked_event.known_p ())
+      return formatted_print ("%qE could be NULL: unchecked value from (%i)",
+			      ev.m_expr, m_origin_of_unchecked_event.one_based ());
+    else
+      return formatted_print ("%qE could be NULL", ev.m_expr);
   }
 
 };
@@ -318,9 +328,15 @@ public:
   /* FIXME.  */
   label_text describe_final_event (const evdesc::final_event &ev) FINAL OVERRIDE
   {
-    return formatted_print ("argument %u (%qE) could be NULL"
-			    " where non-null expected",
-			    m_arg_idx + 1, ev.m_expr);
+    if (m_origin_of_unchecked_event.known_p ())
+      return formatted_print ("argument %u (%qE) from (%i) could be NULL"
+			      " where non-null expected",
+			      m_arg_idx + 1, ev.m_expr,
+			      m_origin_of_unchecked_event.one_based ());
+    else
+      return formatted_print ("argument %u (%qE) could be NULL"
+			      " where non-null expected",
+			      m_arg_idx + 1, ev.m_expr);
   }
 
   // TODO
diff --git a/gcc/testsuite/gcc.dg/analyzer/attribute-nonnull.c b/gcc/testsuite/gcc.dg/analyzer/attribute-nonnull.c
index ab44d07..b3673fb 100644
--- a/gcc/testsuite/gcc.dg/analyzer/attribute-nonnull.c
+++ b/gcc/testsuite/gcc.dg/analyzer/attribute-nonnull.c
@@ -34,10 +34,10 @@ void test_2 (void *p, void *q, void *r)
 
 void test_3 (void *q, void *r)
 {
-  void *p = malloc(1024); /* { dg-message "this call could return NULL" } */
+  void *p = malloc(1024); /* { dg-message "\\(1\\) this call could return NULL" } */
 
   foo(p, q, r); /* { dg-warning "use of possibly-NULL 'p' where non-null expected" } */
-  /* { dg-message "argument 1 \\('p'\\) could be NULL where non-null expected" "" { target *-*-* } .-1 } */
+  /* { dg-message "argument 1 \\('p'\\) from \\(1\\) could be NULL where non-null expected" "" { target *-*-* } .-1 } */
 
   foo(p, q, r);
 
@@ -46,10 +46,10 @@ void test_3 (void *q, void *r)
 
 void test_4 (void *q, void *r)
 {
-  void *p = malloc(1024); /* { dg-message "this call could return NULL" } */
+  void *p = malloc(1024); /* { dg-message "\\(1\\) this call could return NULL" } */
 
   bar(p, q, r); /* { dg-warning "use of possibly-NULL 'p' where non-null expected" } */
-  /* { dg-message "argument 1 \\('p'\\) could be NULL where non-null expected" "" { target *-*-* } .-1 } */
+  /* { dg-message "argument 1 \\('p'\\) from \\(1\\) could be NULL where non-null expected" "" { target *-*-* } .-1 } */
 
   bar(p, q, r);
 
diff --git a/gcc/testsuite/gcc.dg/analyzer/malloc-2.c b/gcc/testsuite/gcc.dg/analyzer/malloc-2.c
new file mode 100644
index 0000000..b197aeb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-2.c
@@ -0,0 +1,23 @@
+/* Tests for precision-of-wording within malloc warnings.  */
+
+typedef __SIZE_TYPE__ size_t;
+extern void *malloc(size_t);
+extern void free(void *);
+extern char *strcpy(char *__restrict __dest, const char *__restrict __src)
+    __attribute__((__nothrow__, __leaf__)) __attribute__((__nonnull__(1, 2)));
+
+void test_1 (void)
+{
+  void *p = malloc (1024); /* { dg-message "\\(1\\) this call could return NULL" } */
+  strcpy ((char *)p, "hello world"); /* { dg-warning "use of possibly-NULL 'p' where non-null expected" } */
+  /* { dg-message "\\(2\\) argument 1 \\('p'\\) from \\(1\\) could be NULL where non-null expected" "" { target *-*-* } .-1 } */
+  free (p);
+}
+
+int *test_2 (void)
+{
+  int *i = malloc (sizeof (int)); /* { dg-message "\\(1\\) this call could return NULL" } */
+  *i = 42; /* { dg-warning "use of possibly-NULL 'i'" } */
+  /* { dg-message "\\(2\\) 'i' could be NULL: unchecked value from \\(1\\)" "" { target *-*-* } .-1 } */
+  return i; 
+}
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 282a577..5a6d82f 100644
--- a/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-unchecked.c
+++ b/gcc/testsuite/gcc.dg/analyzer/malloc-ipa-8-unchecked.c
@@ -59,6 +59,6 @@ make_boxed_int (int i)
           |   NN |   result->i = i;
           |      |   ~~~~~~~~~~~~~                     
           |      |             |
-          |      |             (6) 'result' could be NULL ('result' is in state 'unchecked')
+          |      |             (6) 'result' could be NULL: unchecked value from (4) ('result' is in state 'unchecked')
           |
   { dg-end-multiline-output "" } */
-- 
1.8.5.3

