From 9ced7c0484a5df0abf719b033e4218eb95edc1c9 Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Thu, 28 Feb 2019 14:23:09 -0500
Subject: [PATCH 015/161] FIXME: add gcc/testsuite/DEADCODE-analyzer.dg (not
 used)

---
 gcc/testsuite/DEADCODE-analyzer.dg/analyzer.exp    |  49 ++++++++++
 .../DEADCODE-analyzer.dg/constraints/path-count.c  |  16 ++++
 gcc/testsuite/DEADCODE-analyzer.dg/demo-2.c        | 100 +++++++++++++++++++++
 gcc/testsuite/DEADCODE-analyzer.dg/demo-3.c        |  31 +++++++
 gcc/testsuite/DEADCODE-analyzer.dg/demo-4.c        |  61 +++++++++++++
 gcc/testsuite/DEADCODE-analyzer.dg/demo.c          |  30 +++++++
 gcc/testsuite/DEADCODE-analyzer.dg/dg.exp          |  53 +++++++++++
 .../DEADCODE-analyzer.dg/ipa-double-free/api.c     |  15 ++++
 .../DEADCODE-analyzer.dg/ipa-double-free/api.h     |   9 ++
 .../DEADCODE-analyzer.dg/ipa-double-free/client.c  |   8 ++
 .../DEADCODE-analyzer.dg/malloc/bad-size.c         |  20 +++++
 gcc/testsuite/DEADCODE-analyzer.dg/malloc/leak.c   |   6 ++
 .../DEADCODE-analyzer.dg/malloc/unchecked.c        |  14 +++
 .../DEADCODE-analyzer.dg/memory/example.c          |  16 ++++
 .../DEADCODE-analyzer.dg/memory/stack-address.c    |   8 ++
 15 files changed, 436 insertions(+)
 create mode 100644 gcc/testsuite/DEADCODE-analyzer.dg/analyzer.exp
 create mode 100644 gcc/testsuite/DEADCODE-analyzer.dg/constraints/path-count.c
 create mode 100644 gcc/testsuite/DEADCODE-analyzer.dg/demo-2.c
 create mode 100644 gcc/testsuite/DEADCODE-analyzer.dg/demo-3.c
 create mode 100644 gcc/testsuite/DEADCODE-analyzer.dg/demo-4.c
 create mode 100644 gcc/testsuite/DEADCODE-analyzer.dg/demo.c
 create mode 100644 gcc/testsuite/DEADCODE-analyzer.dg/dg.exp
 create mode 100644 gcc/testsuite/DEADCODE-analyzer.dg/ipa-double-free/api.c
 create mode 100644 gcc/testsuite/DEADCODE-analyzer.dg/ipa-double-free/api.h
 create mode 100644 gcc/testsuite/DEADCODE-analyzer.dg/ipa-double-free/client.c
 create mode 100644 gcc/testsuite/DEADCODE-analyzer.dg/malloc/bad-size.c
 create mode 100644 gcc/testsuite/DEADCODE-analyzer.dg/malloc/leak.c
 create mode 100644 gcc/testsuite/DEADCODE-analyzer.dg/malloc/unchecked.c
 create mode 100644 gcc/testsuite/DEADCODE-analyzer.dg/memory/example.c
 create mode 100644 gcc/testsuite/DEADCODE-analyzer.dg/memory/stack-address.c

diff --git a/gcc/testsuite/DEADCODE-analyzer.dg/analyzer.exp b/gcc/testsuite/DEADCODE-analyzer.dg/analyzer.exp
new file mode 100644
index 0000000..515a676
--- /dev/null
+++ b/gcc/testsuite/DEADCODE-analyzer.dg/analyzer.exp
@@ -0,0 +1,49 @@
+# Test code for analyzer_plugin.so
+load_lib dg.exp
+load_lib prune.exp
+load_lib target-supports.exp
+load_lib gcc-defs.exp
+load_lib timeout.exp
+load_lib target-libpath.exp
+load_lib gcc.exp
+load_lib dejagnu.exp
+
+proc analyzer_target_compile { source dest type options } {
+    gcc_target_compile $source $dest $type $options
+}
+
+load_lib gcc-dg.exp
+
+proc analyzer-dg-test { prog do_what extra_tool_flags } {
+    verbose "within analyzer-dg-test..."
+    verbose "  prog: $prog"
+    verbose "  do_what: $do_what"
+    verbose "  extra_tool_flags: $extra_tool_flags"
+
+    set result \
+	[gcc-dg-test-1 analyzer_target_compile $prog $do_what $extra_tool_flags]
+
+    set comp_output [lindex $result 0]
+    set output_file [lindex $result 1]
+
+    return [list $comp_output $output_file]
+}
+
+# Initialize dg.
+dg-init
+
+# Gather a list of all tests.
+
+set tests [find $srcdir/$subdir *.c]
+
+set tests [lsort $tests]
+
+verbose "tests: $tests"
+
+set DEFAULT_CFLAGS "--analyzer"
+
+# Main loop.  This will invoke analyzer-dg-test on each test-*.c file.
+dg-runtest $tests "" $DEFAULT_CFLAGS
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/DEADCODE-analyzer.dg/constraints/path-count.c b/gcc/testsuite/DEADCODE-analyzer.dg/constraints/path-count.c
new file mode 100644
index 0000000..f6f9bd8
--- /dev/null
+++ b/gcc/testsuite/DEADCODE-analyzer.dg/constraints/path-count.c
@@ -0,0 +1,16 @@
+extern void foo (void);
+extern void bar (void);
+extern void baz (void);
+
+void test (int flag)
+{
+  if (flag)
+    foo ();
+  
+  bar ();
+
+  if (flag)
+    baz ();
+}
+
+/* { dg-final { scan-dump "analysis" "num paths: 2" "analyzer.txt" } } */
diff --git a/gcc/testsuite/DEADCODE-analyzer.dg/demo-2.c b/gcc/testsuite/DEADCODE-analyzer.dg/demo-2.c
new file mode 100644
index 0000000..254a9b3
--- /dev/null
+++ b/gcc/testsuite/DEADCODE-analyzer.dg/demo-2.c
@@ -0,0 +1,100 @@
+/* Control flow tests.  */
+
+#include <stdlib.h>
+
+/* Ensure that we don't need to laboriously walk every path to get
+   to the end of the function.  */
+
+int test_1 (int n)
+{
+  int i, j, k;
+  k = 0;
+  for (int i = 0; i < n; i++)
+    for (int j = 0; j < 1000; j++)
+      k++;
+  return k;
+}
+
+/* Ensure that we don't get an exponential growth in paths due to
+   repeated diamonds in the CFG.  */
+
+typedef struct obj {
+  int ob_refcnt;
+} PyObject;
+
+extern void Py_Dealloc (PyObject *op);
+
+#define Py_DECREF(op)                                   \
+    do {                                                \
+      if (--((PyObject*)(op))->ob_refcnt == 0)		\
+	Py_Dealloc((PyObject *)(op));			\
+    } while (0)
+
+int test_2 (PyObject *obj_01, PyObject *obj_02, PyObject *obj_03,
+	    PyObject *obj_04, PyObject *obj_05, PyObject *obj_06,
+	    PyObject *obj_07, PyObject *obj_08, PyObject *obj_09,
+	    PyObject *obj_10, PyObject *obj_11, PyObject *obj_12,
+	    PyObject *obj_13, PyObject *obj_14, PyObject *obj_15)
+{
+    Py_DECREF (obj_01); Py_DECREF (obj_02); Py_DECREF (obj_03);
+    Py_DECREF (obj_04); Py_DECREF (obj_05); Py_DECREF (obj_06);
+    Py_DECREF (obj_07); Py_DECREF (obj_08); Py_DECREF (obj_09);
+    Py_DECREF (obj_10); Py_DECREF (obj_11); Py_DECREF (obj_12);
+    Py_DECREF (obj_13); Py_DECREF (obj_14); Py_DECREF (obj_15);
+}
+
+int test_3 (int i)
+{
+  switch (i)
+    {
+    case 0:
+      return 43;
+    case 1:
+    case 2:
+      return 72;
+    default:
+      return i * 5;
+    }
+}
+
+void __attribute__((noinline)) do_something (int *ptr)
+{
+  *ptr = 42; /* BUG: can be NULL if malloc fails */
+}
+
+int test_4 (int i, int flag)
+{
+  /* Double diamond CFG; either use &i, or a malloc-ed buffer.  */
+  int *ptr = &i;
+  if (flag)
+    ptr = (int *)malloc (sizeof (int));
+  do_something (ptr);
+  if (flag)
+    free (ptr);
+  return i;
+}
+
+/* What about:  */
+
+int test_5 (int flag)
+{
+  int i;
+
+  if (flag)
+    do_something (&i);
+
+  do_something (&i);
+
+  if (!flag)
+    {
+      /* need to ensure we reach here in the traversal, even though
+	 no states have changed, and we already reached the join-point
+	 earlier with flag == true before trying this.
+	 Does the depth-firstness help?
+	 Also, we've called do_something twice; do we need function
+	 summaries here?  */
+      void *ptr = malloc (16);
+      free (ptr);
+      free (ptr);
+    }
+}
diff --git a/gcc/testsuite/DEADCODE-analyzer.dg/demo-3.c b/gcc/testsuite/DEADCODE-analyzer.dg/demo-3.c
new file mode 100644
index 0000000..cab0f09
--- /dev/null
+++ b/gcc/testsuite/DEADCODE-analyzer.dg/demo-3.c
@@ -0,0 +1,31 @@
+#include <stdlib.h>
+
+extern void __dump_malloc_state ();
+
+typedef struct boxed_int
+{
+  int val;
+} boxed_int;
+
+extern boxed_int *make_boxed_int (int i);
+
+/* Can we use magic fnnames to capture internal state, and thus write
+   DejaGnu tests for this?  */
+
+boxed_int *
+make_boxed_int (int val)
+{
+  boxed_int *new_ptr;
+
+  __dump_malloc_state (); /* { dg-message "malloc state: <start, {}> } */
+
+  new_ptr = (boxed_int *)malloc (sizeof (boxed_int));
+
+  __dump_malloc_state (); /* { dg-message "malloc state: <start, {'new_ptr': 'unchecked'}> } */
+
+  new_ptr->val = val;
+
+  __dump_malloc_state ();
+
+  return new_ptr;
+}
diff --git a/gcc/testsuite/DEADCODE-analyzer.dg/demo-4.c b/gcc/testsuite/DEADCODE-analyzer.dg/demo-4.c
new file mode 100644
index 0000000..2ab0f5c
--- /dev/null
+++ b/gcc/testsuite/DEADCODE-analyzer.dg/demo-4.c
@@ -0,0 +1,61 @@
+/* Control flow constraint tests.  */
+
+extern void __dump_truthiness (int);
+
+static void only_called_when_flag_a_true (int val)
+{
+  __dump_truthiness (i == 42); /* { dg-message "true" } */
+}
+
+static void only_called_when_flag_b_true (int val)
+{
+  __dump_truthiness (i == 17); /* { dg-message "true" } */
+}
+
+int test_1 (int flag_a, int flag_b)
+{
+  int i = 17;
+
+  __dump_truthiness (flag_a); /* { dg-message "unknown" } */
+  __dump_truthiness (flag_b); /* { dg-message "unknown" } */
+
+  if (flag_a)
+    {
+      __dump_truthiness (flag_a); /* { dg-message "true" } */
+      __dump_truthiness (flag_b); /* { dg-message "unknown" } */
+      i = 42;
+    }
+
+  __dump_truthiness (flag_b); /* { dg-message "unknown" } */
+
+  if (flag_a)
+    {
+      __dump_truthiness (flag_a); /* { dg-message "true" } */
+      __dump_truthiness (flag_b); /* { dg-message "unknown" } */
+      __dump_truthiness (i == 42); /* { dg-message "true" } */
+      __dump_truthiness (i == 17); /* { dg-message "false" } */
+      only_called_when_flag_a_true (i);
+    }  
+  else
+    {
+      __dump_truthiness (flag_a); /* { dg-message "false" } */
+      __dump_truthiness (flag_b); /* { dg-message "unknown" } */
+      __dump_truthiness (i == 42); /* { dg-message "false" } */
+      __dump_truthiness (i == 17); /* { dg-message "true" } */
+      only_called_when_flag_b_true (i);
+    }
+}
+
+int test_3 (int i)
+{
+  switch (i)
+    {
+    case 0:
+      return 43;
+    case 1:
+    case 2:
+      return 72;
+    default:
+      return i * 5;
+    }
+}
diff --git a/gcc/testsuite/DEADCODE-analyzer.dg/demo.c b/gcc/testsuite/DEADCODE-analyzer.dg/demo.c
new file mode 100644
index 0000000..7e17781
--- /dev/null
+++ b/gcc/testsuite/DEADCODE-analyzer.dg/demo.c
@@ -0,0 +1,30 @@
+#include <stdlib.h>
+
+typedef struct boxed_int
+{
+  int val;
+} boxed_int;
+
+extern boxed_int *make_boxed_int (int i);
+extern void free_boxed_int (boxed_int *victim);
+
+boxed_int *
+make_boxed_int (int val)
+{
+  boxed_int *new_ptr = (boxed_int *)malloc (sizeof (boxed_int));
+  new_ptr->val = val;
+  return new_ptr;
+}
+
+void
+free_boxed_int (boxed_int *victim)
+{
+  free (victim);
+}
+
+void test (int x)
+{
+  boxed_int *bi = make_boxed_int (x);
+  free_boxed_int (bi);
+  free_boxed_int (bi); /* BUG: double-free.  */
+}
diff --git a/gcc/testsuite/DEADCODE-analyzer.dg/dg.exp b/gcc/testsuite/DEADCODE-analyzer.dg/dg.exp
new file mode 100644
index 0000000..7fda22c
--- /dev/null
+++ b/gcc/testsuite/DEADCODE-analyzer.dg/dg.exp
@@ -0,0 +1,53 @@
+# Test code for analyzer_plugin.so
+
+#global tool
+#set tool "gcc"
+load_lib gcc-dg.exp
+
+#load_lib dg.exp
+#load_lib prune.exp
+#load_lib target-supports.exp
+#load_lib gcc-defs.exp
+#load_lib timeout.exp
+#load_lib target-libpath.exp
+#load_lib gcc.exp
+#load_lib dejagnu.exp
+
+proc analyzer_target_compile { source dest type options } {
+    gcc_target_compile $source $dest $type $options
+}
+
+
+proc analyzer-dg-test { prog do_what extra_tool_flags } {
+    verbose "within analyzer-dg-test..."
+    verbose "  prog: $prog"
+    verbose "  do_what: $do_what"
+    verbose "  extra_tool_flags: $extra_tool_flags"
+
+    set result \
+	[gcc-dg-test-1 analyzer_target_compile $prog $do_what $extra_tool_flags]
+
+    set comp_output [lindex $result 0]
+    set output_file [lindex $result 1]
+
+    return [list $comp_output $output_file]
+}
+
+# Initialize dg.
+dg-init
+
+# Gather a list of all tests.
+
+set tests [find $srcdir/$subdir *.c]
+
+set tests [lsort $tests]
+
+verbose "tests: $tests"
+
+set DEFAULT_CFLAGS "--analyzer"
+
+# Main loop.  This will invoke analyzer-dg-test on each test-*.c file.
+dg-runtest $tests "" $DEFAULT_CFLAGS
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/DEADCODE-analyzer.dg/ipa-double-free/api.c b/gcc/testsuite/DEADCODE-analyzer.dg/ipa-double-free/api.c
new file mode 100644
index 0000000..a418ee4
--- /dev/null
+++ b/gcc/testsuite/DEADCODE-analyzer.dg/ipa-double-free/api.c
@@ -0,0 +1,15 @@
+#include "api.h"
+
+boxed_int *
+make_boxed_int (int i)
+{
+  boxed_int *bi = (boxed_int *)malloc (sizeof (boxed_int));
+  bi->i = i;
+  return bi;
+}
+
+void
+free_boxed_int (boxed_int *bi)
+{
+  free (bi);
+}
diff --git a/gcc/testsuite/DEADCODE-analyzer.dg/ipa-double-free/api.h b/gcc/testsuite/DEADCODE-analyzer.dg/ipa-double-free/api.h
new file mode 100644
index 0000000..ebdfa89
--- /dev/null
+++ b/gcc/testsuite/DEADCODE-analyzer.dg/ipa-double-free/api.h
@@ -0,0 +1,9 @@
+#include <stdlib.h>
+
+typedef struct boxed_int
+{
+  int i;
+} boxed_int;
+
+extern boxed_int *make_boxed_int (int i);
+extern void free_boxed_int (boxed_int *bi);
diff --git a/gcc/testsuite/DEADCODE-analyzer.dg/ipa-double-free/client.c b/gcc/testsuite/DEADCODE-analyzer.dg/ipa-double-free/client.c
new file mode 100644
index 0000000..4c7e642
--- /dev/null
+++ b/gcc/testsuite/DEADCODE-analyzer.dg/ipa-double-free/client.c
@@ -0,0 +1,8 @@
+#include "api.h"
+
+void test (int i)
+{
+  boxed_int *bi = make_boxed_int (i);
+  free_boxed_int (bi);
+  free_boxed_int (bi); /* BUG: double-free.  */
+}
diff --git a/gcc/testsuite/DEADCODE-analyzer.dg/malloc/bad-size.c b/gcc/testsuite/DEADCODE-analyzer.dg/malloc/bad-size.c
new file mode 100644
index 0000000..1456c90
--- /dev/null
+++ b/gcc/testsuite/DEADCODE-analyzer.dg/malloc/bad-size.c
@@ -0,0 +1,20 @@
+#include <stdlib.h>
+
+struct foo
+{
+  int i;
+};
+
+struct bar
+{
+  struct foo f;
+  int j;
+};
+
+struct bar *test (void)
+{
+  struct bar *p;
+  p = (struct bar *)malloc (sizeof (struct foo)); /* should warn here */
+  p->j = 42;
+  return p;
+}
diff --git a/gcc/testsuite/DEADCODE-analyzer.dg/malloc/leak.c b/gcc/testsuite/DEADCODE-analyzer.dg/malloc/leak.c
new file mode 100644
index 0000000..957f554
--- /dev/null
+++ b/gcc/testsuite/DEADCODE-analyzer.dg/malloc/leak.c
@@ -0,0 +1,6 @@
+#include <stdlib.h>
+
+void test (void)
+{
+  void *p = malloc (256); /* { dg-error "leak" } */
+}
diff --git a/gcc/testsuite/DEADCODE-analyzer.dg/malloc/unchecked.c b/gcc/testsuite/DEADCODE-analyzer.dg/malloc/unchecked.c
new file mode 100644
index 0000000..a30ff08
--- /dev/null
+++ b/gcc/testsuite/DEADCODE-analyzer.dg/malloc/unchecked.c
@@ -0,0 +1,14 @@
+#include <stdlib.h>
+
+struct foo
+{
+  int i;
+};
+
+struct foo *test (void)
+{
+  struct foo *p;
+  p = (struct foo *)malloc (sizeof (struct foo));
+  p->i = 42; /* unchecked deref */
+  return p;
+}
diff --git a/gcc/testsuite/DEADCODE-analyzer.dg/memory/example.c b/gcc/testsuite/DEADCODE-analyzer.dg/memory/example.c
new file mode 100644
index 0000000..d9af197
--- /dev/null
+++ b/gcc/testsuite/DEADCODE-analyzer.dg/memory/example.c
@@ -0,0 +1,16 @@
+struct s {
+  struct s *next;
+  int f;
+};
+
+void foo (struct s *in)
+{
+  struct s a;
+  struct s b;
+  struct s c;
+  a.next = &b;
+  b.next = &c;
+  in->next = &a;
+  c.f = 42;
+  __analyzer_eval (in->next->next->next->f == 42);  /* { dg-warning "TRUE" } */
+}
diff --git a/gcc/testsuite/DEADCODE-analyzer.dg/memory/stack-address.c b/gcc/testsuite/DEADCODE-analyzer.dg/memory/stack-address.c
new file mode 100644
index 0000000..602b26a
--- /dev/null
+++ b/gcc/testsuite/DEADCODE-analyzer.dg/memory/stack-address.c
@@ -0,0 +1,8 @@
+int *test(void)
+{
+  /* Enough logic to prevent -Wreturn-local-addr from seeing it.  */
+  int i;
+  int *p;
+  p = &i;
+  return p; /* { dg-error "return of pointer to stack" } */
+}
-- 
1.8.5.3

