From 5aa8137e892d759adaa103fe93dc4344d86927ed Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Sat, 6 Jun 2020 04:48:56 -0400
Subject: [PATCH 213/237] FIXME: add a bunch of WIP loop tests

---
 .../loop-0-up-to-n-by-1-with-iter-obj.c       | 64 +++++++++++++++++++
 .../gcc.dg/analyzer/loop-0-up-to-n-by-1.c     | 38 +++++++++++
 .../gcc.dg/analyzer/loop-n-down-to-1-by-1.c   | 37 +++++++++++
 .../analyzer/loop-start-down-to-end-by-1.c    | 33 ++++++++++
 .../analyzer/loop-start-down-to-end-by-step.c | 33 ++++++++++
 .../analyzer/loop-start-to-end-by-step.c      | 35 ++++++++++
 .../analyzer/loop-start-up-to-end-by-1.c      | 32 ++++++++++
 7 files changed, 272 insertions(+)
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/loop-0-up-to-n-by-1-with-iter-obj.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/loop-0-up-to-n-by-1.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/loop-n-down-to-1-by-1.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/loop-start-down-to-end-by-1.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/loop-start-down-to-end-by-step.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/loop-start-to-end-by-step.c
 create mode 100644 gcc/testsuite/gcc.dg/analyzer/loop-start-up-to-end-by-1.c

diff --git a/gcc/testsuite/gcc.dg/analyzer/loop-0-up-to-n-by-1-with-iter-obj.c b/gcc/testsuite/gcc.dg/analyzer/loop-0-up-to-n-by-1-with-iter-obj.c
new file mode 100644
index 00000000000..7871a8462ec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/loop-0-up-to-n-by-1-with-iter-obj.c
@@ -0,0 +1,64 @@
+/* { dg-additional-options "-fno-analyzer-state-purge" } */
+
+#include "analyzer-decls.h"
+
+struct iter
+{
+  int start;
+  int end;
+  int val;
+};
+
+struct iter *  __attribute__((noinline))
+iter_new (int start, int end)
+{
+  struct iter *it = (struct iter *)malloc (sizeof (struct iter));
+  it->start = start;
+  it->end = end;
+  it->val = start;
+  return it;
+}
+
+int __attribute__((noinline))
+iter_done_p (struct iter *it)
+{
+  return it->val >= it->end;
+}
+
+// FIXME: WIP example of an iterator object, to see how well we cope
+
+void test(int n)
+{
+  int i;
+
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
+
+  struct iter *it = iter_new (0, n);
+  while (!iter_done_p (it))
+    {
+      __analyzer_eval (i < n); /* { dg-warning "TRUE" } */
+      /* (should report TRUE twice). */
+
+      __analyzer_eval (i == 0); /* { dg-warning "TRUE" "1st" } */
+      /* { dg-warning "FALSE" "2nd" { xfail *-*-* } .-1 } */
+      /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */
+      /* TODO(xfail^^^): ideally we ought to figure out i > 0 after 1st iteration.  */
+
+      __analyzer_eval (i >= 0); /* { dg-warning "TRUE" "1st" } */
+      /* { dg-warning "TRUE" "2nd" { xfail *-*-* } } */
+      /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */
+      /* TODO(xfail^^^): ideally we ought to figure out i >= 0 for all iterations.  */
+
+      __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
+    }
+
+  __analyzer_eval (i >= n); /* { dg-warning "TRUE" } */
+
+  __analyzer_eval (i == n); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */
+  /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */
+  /* TODO(xfail^^^): it only figures out i >= 256, rather than i == 256.  */
+
+  free (it);
+
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/loop-0-up-to-n-by-1.c b/gcc/testsuite/gcc.dg/analyzer/loop-0-up-to-n-by-1.c
new file mode 100644
index 00000000000..8295502dd05
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/loop-0-up-to-n-by-1.c
@@ -0,0 +1,38 @@
+/* { dg-additional-options "-fno-analyzer-state-purge" } */
+// FIXME: ^^^ review all of these
+
+#include "analyzer-decls.h"
+
+// FIXME
+
+void test(int n)
+{
+  int i;
+
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
+
+  for (i = 0; i < n; i++) {
+      __analyzer_eval (i < n); /* { dg-warning "TRUE" } */
+      /* (should report TRUE twice). */
+
+      __analyzer_eval (i == 0); /* { dg-warning "TRUE" "1st" } */
+      /* { dg-warning "FALSE" "2nd" { xfail *-*-* } .-1 } */
+      /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */
+      /* TODO(xfail^^^): ideally we ought to figure out i > 0 after 1st iteration.  */
+
+      __analyzer_eval (i >= 0); /* { dg-warning "TRUE" "1st" } */
+      /* { dg-warning "TRUE" "2nd" { xfail *-*-* } } */
+      /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */
+      /* TODO(xfail^^^): ideally we ought to figure out i >= 0 for all iterations.  */
+
+      __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
+  }
+
+  __analyzer_eval (i >= n); /* { dg-warning "TRUE" } */
+
+  __analyzer_eval (i == n); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */
+  /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */
+  /* TODO(xfail^^^): it only figures out i >= 256, rather than i == 256.  */
+
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/loop-n-down-to-1-by-1.c b/gcc/testsuite/gcc.dg/analyzer/loop-n-down-to-1-by-1.c
new file mode 100644
index 00000000000..d0634c36b1e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/loop-n-down-to-1-by-1.c
@@ -0,0 +1,37 @@
+/* { dg-additional-options "-fno-analyzer-state-purge" } */
+
+#include "analyzer-decls.h"
+
+// FIXME
+
+void test(int n)
+{
+  int i;
+
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
+
+  for (i = n; i > 0; i--) {
+      __analyzer_eval (i > 0); /* { dg-warning "TRUE" } */
+      /* (should report TRUE twice). */
+
+      __analyzer_eval (i == n); /* { dg-warning "TRUE" "1st" } */
+      /* { dg-warning "FALSE" "2nd" { xfail *-*-* } .-1 } */
+      /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */
+      /* TODO(xfail^^^): ideally we ought to figure out i > 0 after 1st iteration.  */
+
+      __analyzer_eval (i <= n); /* { dg-warning "TRUE" "1st" } */
+      /* { dg-warning "TRUE" "2nd" { xfail *-*-* } } */
+      /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */
+      /* TODO(xfail^^^): ideally we ought to figure out i >= 0 for all iterations.  */
+
+      __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
+  }
+
+  __analyzer_eval (i <= 0); /* { dg-warning "TRUE" } */
+
+  __analyzer_eval (i == 0); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */
+  /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */
+  /* TODO(xfail^^^): it only figures out i >= 256, rather than i == 256.  */
+
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/loop-start-down-to-end-by-1.c b/gcc/testsuite/gcc.dg/analyzer/loop-start-down-to-end-by-1.c
new file mode 100644
index 00000000000..45c5188a2db
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/loop-start-down-to-end-by-1.c
@@ -0,0 +1,33 @@
+#include "analyzer-decls.h"
+
+// TODO: not sure what the __analyzer_eval should do
+
+void test(int start, int end, int step)
+{
+  int i;
+
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
+
+  for (i = start; i > end; i --) {
+      __analyzer_eval (i > end); /* { dg-warning "TRUE" } */
+      /* (should report TRUE twice). */
+
+      __analyzer_eval (i == start); /* { dg-warning "TRUE" "1st" } */
+      /* { dg-warning "FALSE" "2nd" { xfail *-*-* } .-1 } */
+      /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */
+      /* TODO(xfail^^^): ideally we ought to figure out i > 0 after 1st iteration.  */
+
+      __analyzer_eval (i <= start); /* { dg-warning "UNKNOWN" } */
+
+      __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
+  }
+
+  __analyzer_eval (i >= end); /* { dg-warning "TRUE" } */
+
+  // FIXME: do we know this?  What if we overshoot?
+  __analyzer_eval (i == end); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */
+  /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */
+  /* TODO(xfail^^^): it only figures out i >= 256, rather than i == 256.  */
+
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/loop-start-down-to-end-by-step.c b/gcc/testsuite/gcc.dg/analyzer/loop-start-down-to-end-by-step.c
new file mode 100644
index 00000000000..c06cc4fa8b2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/loop-start-down-to-end-by-step.c
@@ -0,0 +1,33 @@
+#include "analyzer-decls.h"
+
+// TODO: not sure what the __analyzer_eval should do
+
+void test(int start, int end, int step)
+{
+  int i;
+
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
+
+  for (i = start; i > end; i -= step) {
+      __analyzer_eval (i > end); /* { dg-warning "TRUE" } */
+      /* (should report TRUE twice). */
+
+      __analyzer_eval (i == start); /* { dg-warning "TRUE" "1st" } */
+      /* { dg-warning "FALSE" "2nd" { xfail *-*-* } .-1 } */
+      /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */
+      /* TODO(xfail^^^): ideally we ought to figure out i > 0 after 1st iteration.  */
+
+      __analyzer_eval (i <= start); /* { dg-warning "UNKNOWN" } */
+
+      __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
+  }
+
+  __analyzer_eval (i >= end); /* { dg-warning "TRUE" } */
+
+  // FIXME: do we know this?  What if we overshoot?
+  __analyzer_eval (i == end); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */
+  /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */
+  /* TODO(xfail^^^): it only figures out i >= 256, rather than i == 256.  */
+
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/loop-start-to-end-by-step.c b/gcc/testsuite/gcc.dg/analyzer/loop-start-to-end-by-step.c
new file mode 100644
index 00000000000..ba578291298
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/loop-start-to-end-by-step.c
@@ -0,0 +1,35 @@
+#include "analyzer-decls.h"
+
+// TODO: not sure what the __analyzer_eval should do
+
+void test(int start, int end, int step)
+{
+  int i;
+
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
+
+  for (i = start; i < end; i += step) {
+      __analyzer_eval (i < end); /* { dg-warning "TRUE" } */
+      /* (should report TRUE twice). */
+
+      __analyzer_eval (i == start); /* { dg-warning "TRUE" "1st" } */
+      /* { dg-warning "FALSE" "2nd" { xfail *-*-* } .-1 } */
+      /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */
+      /* TODO(xfail^^^): ideally we ought to figure out i > 0 after 1st iteration.  */
+
+      /* We don't know the direction of step.  */
+      __analyzer_eval (i >= start); /* { dg-warning "UNKNOWN" } */
+
+      __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
+  }
+
+  // FIXME: do we know this?  What about direction of step?
+  __analyzer_eval (i >= 256); /* { dg-warning "TRUE" } */
+
+  // FIXME: do we know this?  What if we overshoot?
+  __analyzer_eval (i == end); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */
+  /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */
+  /* TODO(xfail^^^): it only figures out i >= 256, rather than i == 256.  */
+
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/loop-start-up-to-end-by-1.c b/gcc/testsuite/gcc.dg/analyzer/loop-start-up-to-end-by-1.c
new file mode 100644
index 00000000000..da9de0ab039
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/loop-start-up-to-end-by-1.c
@@ -0,0 +1,32 @@
+#include "analyzer-decls.h"
+
+// TODO: not sure what the __analyzer_eval should do
+
+void test(int start, int end)
+{
+  int i;
+
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
+
+  for (i = start; i < end; i++) {
+      __analyzer_eval (i < end); /* { dg-warning "TRUE" } */
+      /* (should report TRUE twice). */
+
+      __analyzer_eval (i == start); /* { dg-warning "TRUE" "1st" } */
+      /* { dg-warning "FALSE" "2nd" { xfail *-*-* } .-1 } */
+      /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-2 } */
+      /* TODO(xfail^^^): ideally we ought to figure out i > 0 after 1st iteration.  */
+
+      __analyzer_eval (i >= start); /* { dg-warning "TRUE" } */
+
+      __analyzer_dump_exploded_nodes (0); /* { dg-warning "2 processed enodes" } */
+  }
+
+  __analyzer_eval (i >= end); /* { dg-warning "TRUE" } */
+
+  __analyzer_eval (i == end); /* { dg-warning "TRUE" "desired" { xfail *-*-* } } */
+  /* { dg-warning "UNKNOWN" "status quo" { target *-*-* } .-1 } */
+  /* TODO(xfail^^^): it only figures out i >= 256, rather than i == 256.  */
+
+  __analyzer_dump_exploded_nodes (0); /* { dg-warning "1 processed enode" } */
+}
-- 
2.26.2

