From f3173ba8c8b94cc1c246f715cde6303764a4184c Mon Sep 17 00:00:00 2001
From: David Malcolm <dmalcolm@redhat.com>
Date: Wed, 10 Jun 2015 06:08:20 -0400
Subject: [PATCH 16/16] wide-int.cc: add selftests

Jeff approved an early version of this:
https://gcc.gnu.org/ml/gcc-patches/2015-10/msg03309.html
> OK if/when prereqs are approved. Minor twiddling if we end up
> moving it elsewhere or standardizing/reducing header files is
> pre-approved.

This version moves it to wide-int.cc and converts it to the new
style.  It's the only example so far of a type-parametrized test.

gcc/ChangeLog:
	* selftest-run-tests.c (selftest::run_tests): Add call
	to wide_int_cc_tests.
	* selftest.h (wide_int_cc_tests): New declaration.
	* wide-int.cc: Include selftest.h and wide-int-print.h.
	(from_int <wide_int>): New function.
	(from_int <offset_int>): New function.
	(from_int <widest_int>): New function.
	(assert_deceq): New function.
	(assert_hexeq): New function.
	(test_printing <VALUE_TYPE>): New function template.
	(test_ops <VALUE_TYPE>): New function template.
	(test_comparisons <VALUE_TYPE>): New function template.
	(run_all_wide_int_tests <VALUE_TYPE>): New function template.
	(selftest::wide_int_cc_tests): New function.
---
 gcc/selftest-run-tests.c |   1 +
 gcc/selftest.h           |   1 +
 gcc/wide-int.cc          | 152 +++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 154 insertions(+)

diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c
index 4233351..ab334aa 100644
--- a/gcc/selftest-run-tests.c
+++ b/gcc/selftest-run-tests.c
@@ -46,6 +46,7 @@ selftest::run_tests ()
   hash_map_tests_c_tests ();
   hash_set_tests_c_tests ();
   vec_c_tests ();
+  wide_int_cc_tests ();
 
   /* Mid-level data structures.  */
   input_c_tests ();
diff --git a/gcc/selftest.h b/gcc/selftest.h
index 2062a8b..a1d3074 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -55,6 +55,7 @@ extern void spellcheck_c_tests ();
 extern void tree_c_tests ();
 extern void tree_cfg_c_tests ();
 extern void vec_c_tests ();
+extern void wide_int_cc_tests ();
 
 extern int num_passes;
 
diff --git a/gcc/wide-int.cc b/gcc/wide-int.cc
index 8648e7d..634dfb8 100644
--- a/gcc/wide-int.cc
+++ b/gcc/wide-int.cc
@@ -23,6 +23,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "tree.h"
+#include "selftest.h"
+#include "wide-int-print.h"
 
 
 #define HOST_BITS_PER_HALF_WIDE_INT 32
@@ -2144,3 +2146,153 @@ template void generic_wide_int <wide_int_ref_storage <false> >::dump () const;
 template void generic_wide_int <wide_int_ref_storage <true> >::dump () const;
 template void offset_int::dump () const;
 template void widest_int::dump () const;
+
+
+#if CHECKING_P
+
+/* Selftests for wide ints.  We run these multiple times, once per type.  */
+
+/* Helper function for building a test value.  */
+
+template <class VALUE_TYPE>
+static VALUE_TYPE
+from_int (int i);
+
+/* Specializations of the fixture for each wide-int type.  */
+
+template <>
+wide_int
+from_int (int i)
+{
+  return wi::shwi (i, 32);
+}
+
+template <>
+offset_int
+from_int (int i)
+{
+  return offset_int (i);
+}
+
+template <>
+widest_int
+from_int (int i)
+{
+  return widest_int (i);
+}
+
+/* Verify that print_dec (WI, ..., SGN) gives the expected string
+   representation (using base 10).  */
+
+static void
+assert_deceq (const char *expected, const wide_int_ref &wi, signop sgn)
+{
+  char buf[WIDE_INT_PRINT_BUFFER_SIZE];
+  print_dec (wi, buf, sgn);
+  ASSERT_STREQ (expected, buf);
+}
+
+/* Likewise for base 16.  */
+
+static void
+assert_hexeq (const char *expected, const wide_int_ref &wi)
+{
+  char buf[WIDE_INT_PRINT_BUFFER_SIZE];
+  print_hex (wi, buf);
+  ASSERT_STREQ (expected, buf);
+}
+
+/* Test cases.  */
+
+template <class VALUE_TYPE>
+static void
+test_printing ()
+{
+  VALUE_TYPE a = from_int<VALUE_TYPE> (42);
+  assert_deceq ("42", a, SIGNED);
+  assert_hexeq ("0x2a", a);
+}
+
+template <class VALUE_TYPE>
+static void
+test_ops ()
+{
+  VALUE_TYPE a = from_int<VALUE_TYPE> (7);
+  VALUE_TYPE b = from_int<VALUE_TYPE> (3);
+
+  /* Using functions.  */
+  assert_deceq ("-7", wi::neg (a), SIGNED);
+  assert_deceq ("10", wi::add (a, b), SIGNED);
+  assert_deceq ("4", wi::sub (a, b), SIGNED);
+  assert_deceq ("-4", wi::sub (b, a), SIGNED);
+  assert_deceq ("21", wi::mul (a, b), SIGNED);
+
+  /* Using operators.  */
+  assert_deceq ("-7", -a, SIGNED);
+  assert_deceq ("10", a + b, SIGNED);
+  assert_deceq ("4", a - b, SIGNED);
+  assert_deceq ("-4", b - a, SIGNED);
+  assert_deceq ("21", a * b, SIGNED);
+}
+
+template <class VALUE_TYPE>
+static void
+test_comparisons ()
+{
+  VALUE_TYPE a = from_int<VALUE_TYPE> (7);
+  VALUE_TYPE b = from_int<VALUE_TYPE> (3);
+
+  /* == */
+  ASSERT_TRUE (wi::eq_p (a, a));
+  ASSERT_FALSE (wi::eq_p (a, b));
+
+  /* != */
+  ASSERT_TRUE (wi::ne_p (a, b));
+  ASSERT_FALSE (wi::ne_p (a, a));
+
+  /* < */
+  ASSERT_FALSE (wi::lts_p (a, a));
+  ASSERT_FALSE (wi::lts_p (a, b));
+  ASSERT_TRUE (wi::lts_p (b, a));
+
+  /* <= */
+  ASSERT_TRUE (wi::les_p (a, a));
+  ASSERT_FALSE (wi::les_p (a, b));
+  ASSERT_TRUE (wi::les_p (b, a));
+
+  /* > */
+  ASSERT_FALSE (wi::gts_p (a, a));
+  ASSERT_TRUE (wi::gts_p (a, b));
+  ASSERT_FALSE (wi::gts_p (b, a));
+
+  /* >= */
+  ASSERT_TRUE (wi::ges_p (a, a));
+  ASSERT_TRUE (wi::ges_p (a, b));
+  ASSERT_FALSE (wi::ges_p (b, a));
+
+  /* comparison */
+  ASSERT_EQ (-1, wi::cmps (b, a));
+  ASSERT_EQ (0, wi::cmps (a, a));
+  ASSERT_EQ (1, wi::cmps (a, b));
+}
+
+template <class VALUE_TYPE>
+static void run_all_wide_int_tests ()
+{
+  test_printing <VALUE_TYPE> ();
+  test_ops <VALUE_TYPE> ();
+  test_comparisons <VALUE_TYPE> ();
+}
+
+namespace selftest {
+
+void
+wide_int_cc_tests ()
+{
+ run_all_wide_int_tests <wide_int> ();
+ run_all_wide_int_tests <offset_int> ();
+ run_all_wide_int_tests <widest_int> ();
+}
+
+} // namespace selftest
+#endif /* CHECKING_P */
-- 
1.8.5.3

