This patch adds a new ana::integer class to the analyzer for
handling arbitrary-precision integers. It is a wrapper around libgmp's
mpz_t, with integration with GCC components such as pretty_printer, our
json classes, and integer_cst.
Nothing uses this yet, but it is fundamental to my upcoming rewrite
of the analyzer's state-tracking.
gcc/ChangeLog:
* Makefile.in (ANALYZER_OBJS): Add analyzer/integer.o.
gcc/analyzer/ChangeLog:
* analyzer-selftests.cc (run_analyzer_selftests): Call
analyzer_integer_cc_tests.
* analyzer-selftests.h (analyzer_integer_cc_tests): New decl.
* integer.cc: New file.
* integer.h: New file.
Signed-off-by: David Malcolm <[email protected]>
---
gcc/Makefile.in | 1 +
gcc/analyzer/analyzer-selftests.cc | 1 +
gcc/analyzer/analyzer-selftests.h | 1 +
gcc/analyzer/integer.cc | 493 +++++++++++++++++++++++++++++
gcc/analyzer/integer.h | 297 +++++++++++++++++
5 files changed, 793 insertions(+)
create mode 100644 gcc/analyzer/integer.cc
create mode 100644 gcc/analyzer/integer.h
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 7d9536d8da4..5bb019c2343 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1370,6 +1370,7 @@ ANALYZER_OBJS = \
analyzer/function-set.o \
analyzer/infinite-loop.o \
analyzer/infinite-recursion.o \
+ analyzer/integer.o \
analyzer/kf.o \
analyzer/kf-analyzer.o \
analyzer/kf-lang-cp.o \
diff --git a/gcc/analyzer/analyzer-selftests.cc
b/gcc/analyzer/analyzer-selftests.cc
index 9ad8f0a0db4..cf5af41c8d7 100644
--- a/gcc/analyzer/analyzer-selftests.cc
+++ b/gcc/analyzer/analyzer-selftests.cc
@@ -51,6 +51,7 @@ run_analyzer_selftests ()
analyzer_access_diagram_cc_tests ();
analyzer_constraint_manager_cc_tests ();
analyzer_function_set_cc_tests ();
+ analyzer_integer_cc_tests ();
analyzer_program_point_cc_tests ();
analyzer_program_state_cc_tests ();
analyzer_ranges_cc_tests ();
diff --git a/gcc/analyzer/analyzer-selftests.h
b/gcc/analyzer/analyzer-selftests.h
index e350e9243ed..f3af1115f07 100644
--- a/gcc/analyzer/analyzer-selftests.h
+++ b/gcc/analyzer/analyzer-selftests.h
@@ -36,6 +36,7 @@ extern void run_analyzer_selftests ();
extern void analyzer_access_diagram_cc_tests ();
extern void analyzer_constraint_manager_cc_tests ();
extern void analyzer_function_set_cc_tests ();
+extern void analyzer_integer_cc_tests ();
extern void analyzer_program_point_cc_tests ();
extern void analyzer_program_state_cc_tests ();
extern void analyzer_ranges_cc_tests ();
diff --git a/gcc/analyzer/integer.cc b/gcc/analyzer/integer.cc
new file mode 100644
index 00000000000..dee79c97372
--- /dev/null
+++ b/gcc/analyzer/integer.cc
@@ -0,0 +1,493 @@
+/* Arbitrary precision integers.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ Contributed by David Malcolm <[email protected]>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "analyzer/common.h"
+
+#include "diagnostics/markup.h"
+
+#include "selftest.h"
+#include "selftest-json.h"
+
+#include "analyzer/integer.h"
+
+#if ENABLE_ANALYZER
+
+namespace ana {
+
+void
+integer::dump_to_pp (pretty_printer *pp) const
+{
+ char *str = nullptr;
+ gmp_asprintf (&str, "%Zd", m_mpz);
+ gcc_assert (str);
+
+ pp_string (pp, str);
+
+ void (*free_func_ptr) (void *, size_t) = nullptr;
+ mp_get_memory_functions (nullptr, nullptr, &free_func_ptr);
+ gcc_assert (free_func_ptr);
+ free_func_ptr (str, 0);
+}
+
+DEBUG_FUNCTION void
+integer::dump () const
+{
+ pretty_printer pp;
+ pp.set_output_stream (stderr);
+ dump_to_pp (&pp);
+ pp_newline (&pp);
+ pp_flush (&pp);
+}
+
+std::unique_ptr<json::value>
+integer::to_json () const
+{
+ pretty_printer pp;
+ dump_to_pp (&pp);
+ return std::make_unique<json::string> (pp_formatted_text (&pp));
+}
+
+std::unique_ptr<diagnostics::markup::node>
+integer::make_markup_node () const
+{
+ pretty_printer pp;
+ dump_to_pp (&pp);
+ return diagnostics::markup::make_text_node (pp_formatted_text (&pp));
+}
+
+integer
+convert_from_integer_cst (const_tree int_cst)
+{
+ gcc_assert (int_cst);
+ gcc_assert (TREE_CODE (int_cst) == INTEGER_CST);
+
+ integer result;
+ wi::to_mpz (wi::to_wide (int_cst),
+ result.access_mpz (),
+ TYPE_SIGN (TREE_TYPE (int_cst)));
+ return result;
+}
+
+tree
+make_integer_cst_from_integer (tree type, const integer &value, bool wrap)
+{
+ gcc_assert (type);
+
+ /* Need to make a copy, as wi::from_mpz modifies its argument. */
+ integer mutable_copy (value);
+ wide_int w = wi::from_mpz (type, mutable_copy.access_mpz (), wrap);
+ return wide_int_to_tree (type, w);
+}
+
+#if CHECKING_P
+
+namespace selftest {
+
+static void
+test_rule_of_5 ()
+{
+ integer a;
+ ASSERT_EQ (a, 0);
+
+ integer b (42);
+ ASSERT_EQ (b, 42);
+
+ integer c (b);
+ ASSERT_EQ (c, 42);
+ // Check that writes to b don't affect c after the copy:
+ b = 43;
+ ASSERT_EQ (b, 43);
+ ASSERT_EQ (c, 42);
+
+ integer d (std::move (c));
+ ASSERT_EQ (d, 42);
+ ASSERT_EQ (c, 0);
+
+ c = integer (1066);
+ ASSERT_EQ (c, 1066);
+
+ a = std::move (d);
+ ASSERT_EQ (a, 42);
+}
+
+static void
+test_comparisons ()
+{
+ /* Equality. */
+ ASSERT_TRUE (integer (0) == integer (0));
+ ASSERT_FALSE (integer (0) == integer (1));
+ ASSERT_TRUE (integer (0) == 0);
+ ASSERT_FALSE (integer (0) == 42);
+
+ /* Inequality. */
+ ASSERT_TRUE (integer (0) != integer (1));
+ ASSERT_FALSE (integer (0) != integer (0));
+ ASSERT_TRUE (integer (0) != 1);
+ ASSERT_FALSE (integer (0) != 0);
+
+ // operator<
+ ASSERT_TRUE (integer (-1) < integer (0));
+ ASSERT_FALSE (integer (0) < integer (0));
+ ASSERT_TRUE (integer (2) < integer (3));
+ ASSERT_FALSE (integer (3) < integer (2));
+
+ // Default ctor should give zero:
+ ASSERT_TRUE (integer () == integer (0));
+}
+
+static void
+test_addition ()
+{
+ ASSERT_EQ (integer (1) + integer (2),
+ integer (3));
+
+ // Reflexivity
+ ASSERT_EQ (integer (1) + integer (2),
+ integer (2) + integer (1));
+
+ // Commutativity
+ ASSERT_EQ ((integer (1) + integer (2)) + integer (3),
+ integer (6));
+ ASSERT_EQ (integer (1) + (integer (2) + integer (3)),
+ integer (6));
+}
+
+static void
+test_subtraction ()
+{
+ // Identity
+ ASSERT_EQ (integer (2) - integer (0),
+ integer (2));
+
+ // Positive result
+ ASSERT_EQ (integer (11) - integer (7),
+ integer (4));
+
+ // Negative reult
+ ASSERT_EQ (integer (5) - integer (10),
+ integer (-5));
+
+ // Negative operands
+ ASSERT_EQ (integer (-2) - integer (2),
+ integer (-4));
+ ASSERT_EQ (integer (2) - integer (-2),
+ integer (4));
+}
+
+static void
+test_multiplication ()
+{
+ // Zero:
+ ASSERT_EQ (integer (2) * integer (0),
+ integer (0));
+ ASSERT_EQ (integer (0) * integer (2),
+ integer (0));
+
+ // Identity
+ ASSERT_EQ (integer (3) * integer (1),
+ integer (3));
+ ASSERT_EQ (integer (1) * integer (3),
+ integer (3));
+
+ // Combinations of positive and negative
+ ASSERT_EQ (integer (2) * integer (3),
+ integer (6));
+ ASSERT_EQ (integer (4) * integer (-5),
+ integer (-20));
+ ASSERT_EQ (integer (-4) * integer (5),
+ integer (-20));
+ ASSERT_EQ (integer (-4) * integer (-5),
+ integer (20));
+}
+
+static void
+test_division ()
+{
+ ASSERT_EQ (integer (0).floor_div (10),
+ integer (0));
+ ASSERT_EQ (integer (24).floor_div (10),
+ integer (2));
+ ASSERT_EQ (integer (3).floor_div (1),
+ integer (3));
+
+ ASSERT_EQ (integer (-8).floor_div (10),
+ integer (-1));
+}
+
+static void
+test_modulus ()
+{
+ ASSERT_EQ (integer (0).floor_mod (10),
+ integer (0));
+ ASSERT_EQ (integer (24).floor_mod (10),
+ integer (4));
+ ASSERT_EQ (integer (3).floor_mod (1),
+ integer (0));
+
+ ASSERT_EQ (integer (-8).floor_mod (10),
+ integer (2));
+}
+
+static void
+test_dumping ()
+{
+ // Positive
+ {
+ pretty_printer pp;
+ integer (42).dump_to_pp (&pp);
+ ASSERT_STREQ (pp_formatted_text (&pp), "42");
+ }
+
+ // Negative
+ {
+ pretty_printer pp;
+ integer (-100).dump_to_pp (&pp);
+ ASSERT_STREQ (pp_formatted_text (&pp), "-100");
+ }
+}
+
+static void
+test_very_large ()
+{
+ /* Large power of two. */
+ {
+ const integer two_to_the_12 (1 << 12);
+ const integer two_to_the_24 = two_to_the_12 * two_to_the_12;
+ const integer two_to_the_48 = two_to_the_24 * two_to_the_24;
+ const integer two_to_the_96 = two_to_the_48 * two_to_the_48;
+ const integer two_to_the_192 = two_to_the_96 * two_to_the_96;
+ {
+ pretty_printer pp;
+ two_to_the_192.dump_to_pp (&pp);
+ ASSERT_STREQ
+ (pp_formatted_text (&pp),
+ "6277101735386680763835789423207666416102355444464034512896");
+ }
+ // Negation
+ {
+ pretty_printer pp;
+ (-two_to_the_192).dump_to_pp (&pp);
+ ASSERT_STREQ
+ (pp_formatted_text (&pp),
+ "-6277101735386680763835789423207666416102355444464034512896");
+ }
+ }
+
+ /* Large power of ten. */
+ {
+ const integer million (1000 * 1000);
+ const integer ten_to_the_12 = million * million;
+ const integer ten_to_the_24 = ten_to_the_12 * ten_to_the_12;
+ const integer ten_to_the_48 = ten_to_the_24 * ten_to_the_24;
+ const integer ten_to_the_96 = ten_to_the_48 * ten_to_the_48;
+ const integer ten_to_the_192 = ten_to_the_96 * ten_to_the_96;
+ {
+ pretty_printer pp;
+ ten_to_the_192.dump_to_pp (&pp);
+ ASSERT_STREQ
+ (pp_formatted_text (&pp),
+ ("1"
+ "000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000"));
+ }
+
+ // Negation
+ {
+ pretty_printer pp;
+ (-ten_to_the_192).dump_to_pp (&pp);
+ ASSERT_STREQ
+ (pp_formatted_text (&pp),
+ ("-1"
+ "000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000"));
+ }
+
+ // Addition
+ {
+ pretty_printer pp;
+ (ten_to_the_192 + ten_to_the_192).dump_to_pp (&pp);
+ ASSERT_STREQ
+ (pp_formatted_text (&pp),
+ ("2"
+ "000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000"
+ "000000000000000000000000000000000000000000000000"));
+ }
+ }
+}
+
+static void
+test_pp_element ()
+{
+ pretty_printer pp;
+ pp_element_integer e1 (integer (42));
+ pp_element_integer e2 (integer (-100));
+ pp_printf (&pp, "positive: %e negative: %e", &e1, &e2);
+ ASSERT_STREQ (pp_formatted_text (&pp), "positive: 42 negative: -100");
+}
+
+static integer
+get_min_value (tree integral_type)
+{
+ gcc_assert (integral_type);
+ return convert_from_integer_cst (TYPE_MIN_VALUE (integral_type));
+}
+
+static integer
+get_max_value (tree integral_type)
+{
+ gcc_assert (integral_type);
+ return convert_from_integer_cst (TYPE_MAX_VALUE (integral_type));
+}
+
+static void
+test_convert_from_integer_cst ()
+{
+ ASSERT_TRUE (get_min_value (signed_char_type_node) < 0);
+ ASSERT_TRUE (get_max_value (signed_char_type_node) > 0);
+
+ ASSERT_TRUE (get_min_value (unsigned_char_type_node) == 0);
+ ASSERT_TRUE (get_max_value (unsigned_char_type_node) > 0);
+
+ ASSERT_TRUE (get_min_value (integer_type_node) < 0);
+ ASSERT_TRUE (get_max_value (integer_type_node) > 0);
+ ASSERT_EQ (convert_from_integer_cst (integer_zero_node), 0);
+ ASSERT_EQ (convert_from_integer_cst (integer_one_node), 1);
+ ASSERT_EQ (convert_from_integer_cst (integer_minus_one_node), -1);
+
+ ASSERT_TRUE (get_min_value (unsigned_type_node) == 0);
+ ASSERT_TRUE (get_max_value (unsigned_type_node) > 0);
+
+ ASSERT_TRUE (get_min_value (long_integer_type_node) < 0);
+ ASSERT_TRUE (get_max_value (long_integer_type_node) > 0);
+
+ ASSERT_TRUE (get_min_value (long_unsigned_type_node) == 0);
+ ASSERT_TRUE (get_max_value (long_unsigned_type_node) > 0);
+
+ ASSERT_TRUE (get_min_value (long_long_integer_type_node) < 0);
+ ASSERT_TRUE (get_max_value (long_long_integer_type_node) > 0);
+
+ ASSERT_TRUE (get_min_value (long_long_unsigned_type_node) == 0);
+ ASSERT_TRUE (get_max_value (long_long_unsigned_type_node) > 0);
+
+ ASSERT_TRUE (get_min_value (size_type_node) == 0);
+ ASSERT_TRUE (get_max_value (size_type_node) > 0);
+ ASSERT_EQ (convert_from_integer_cst (size_zero_node), 0);
+ ASSERT_EQ (convert_from_integer_cst (size_one_node), 1);
+
+ ASSERT_TRUE (get_min_value (ptrdiff_type_node) < 0);
+ ASSERT_TRUE (get_max_value (ptrdiff_type_node) > 0);
+}
+
+// Verify that INT_CST round-trips through integer.
+
+static void
+assert_round_trip (const ::selftest::location &loc, tree int_cst)
+{
+ integer as_integer = convert_from_integer_cst (int_cst);
+ tree round_tripped_cst = make_integer_cst_from_integer (TREE_TYPE (int_cst),
+ as_integer, false);
+ ASSERT_EQ_AT (loc, TREE_TYPE (int_cst), TREE_TYPE (round_tripped_cst));
+ ASSERT_TRUE_AT (loc, tree_int_cst_equal (int_cst, round_tripped_cst));
+}
+
+#define ASSERT_ROUND_TRIP(INT_CST) \
+ SELFTEST_BEGIN_STMT \
+ assert_round_trip ((SELFTEST_LOCATION), (INT_CST)); \
+ SELFTEST_END_STMT
+
+static void
+test_round_trip_of_integer_cst ()
+{
+ ASSERT_ROUND_TRIP (TYPE_MIN_VALUE (signed_char_type_node));
+ ASSERT_ROUND_TRIP (TYPE_MAX_VALUE (signed_char_type_node));
+
+ ASSERT_ROUND_TRIP (TYPE_MIN_VALUE (unsigned_char_type_node));
+ ASSERT_ROUND_TRIP (TYPE_MAX_VALUE (unsigned_char_type_node));
+
+ ASSERT_ROUND_TRIP (TYPE_MIN_VALUE (integer_type_node));
+ ASSERT_ROUND_TRIP (TYPE_MAX_VALUE (integer_type_node));
+ ASSERT_ROUND_TRIP (integer_zero_node);
+ ASSERT_ROUND_TRIP (integer_one_node);
+ ASSERT_ROUND_TRIP (integer_minus_one_node);
+
+ ASSERT_ROUND_TRIP (TYPE_MIN_VALUE (unsigned_type_node));
+ ASSERT_ROUND_TRIP (TYPE_MAX_VALUE (unsigned_type_node));
+
+ ASSERT_ROUND_TRIP (TYPE_MIN_VALUE (long_integer_type_node));
+ ASSERT_ROUND_TRIP (TYPE_MAX_VALUE (long_integer_type_node));
+
+ ASSERT_ROUND_TRIP (TYPE_MIN_VALUE (long_unsigned_type_node));
+ ASSERT_ROUND_TRIP (TYPE_MAX_VALUE (long_unsigned_type_node));
+
+ ASSERT_ROUND_TRIP (TYPE_MIN_VALUE (long_long_integer_type_node));
+ ASSERT_ROUND_TRIP (TYPE_MAX_VALUE (long_long_integer_type_node));
+
+ ASSERT_ROUND_TRIP (TYPE_MIN_VALUE (long_long_unsigned_type_node));
+ ASSERT_ROUND_TRIP (TYPE_MAX_VALUE (long_long_unsigned_type_node));
+
+ ASSERT_ROUND_TRIP (TYPE_MIN_VALUE (size_type_node));
+ ASSERT_ROUND_TRIP (TYPE_MAX_VALUE (size_type_node));
+ ASSERT_ROUND_TRIP (size_zero_node);
+ ASSERT_ROUND_TRIP (size_one_node);
+
+ ASSERT_ROUND_TRIP (TYPE_MIN_VALUE (ptrdiff_type_node));
+ ASSERT_ROUND_TRIP (TYPE_MAX_VALUE (ptrdiff_type_node));
+}
+
+static void
+test_to_json ()
+{
+ ASSERT_JSON_STRING_EQ (integer (42).to_json ().get (),
+ "42");
+}
+
+/* Run all of the selftests within this file. */
+
+void
+analyzer_integer_cc_tests ()
+{
+ test_rule_of_5 ();
+ test_comparisons ();
+ test_addition ();
+ test_subtraction ();
+ test_multiplication ();
+ test_division ();
+ test_modulus ();
+ test_dumping ();
+ test_very_large ();
+ test_pp_element ();
+ test_convert_from_integer_cst ();
+ test_round_trip_of_integer_cst ();
+ test_to_json ();
+}
+
+} // namespace selftest
+
+#endif /* CHECKING_P */
+
+} // namespace ana
+
+#endif /* #if ENABLE_ANALYZER */
diff --git a/gcc/analyzer/integer.h b/gcc/analyzer/integer.h
new file mode 100644
index 00000000000..7e91f51668e
--- /dev/null
+++ b/gcc/analyzer/integer.h
@@ -0,0 +1,297 @@
+/* Arbitrary precision integers.
+ Copyright (C) 2026 Free Software Foundation, Inc.
+ Contributed by David Malcolm <[email protected]>.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_ANALYZER_INTEGER_H
+#define GCC_ANALYZER_INTEGER_H
+
+#include "pretty-print-markup.h"
+
+namespace ana {
+
+/* A class for arbitrary precision integers.
+
+ This is a C++ wrapper around gmp's mpz_t, with integration with
+ pretty_printer.
+
+ We don't use gmp's gmpxx.h: it uses exceptions, which we can't use. */
+
+class integer
+{
+public:
+ static constexpr const char *dump_type_name = "integer";
+
+ integer ()
+ {
+ mpz_init (m_mpz);
+ }
+
+ integer (int i)
+ {
+ mpz_init_set_si (m_mpz, i);
+ }
+
+ ~integer ()
+ {
+ mpz_clear (m_mpz);
+ }
+
+ integer (const integer &other)
+ {
+ mpz_init_set (m_mpz, other.m_mpz);
+ }
+
+ integer (integer &&other)
+ {
+ mpz_init (m_mpz);
+ std::swap (m_mpz, other.m_mpz);
+ }
+
+ /* Make it easier to use either integer or integer_with_unit
+ in a single template. */
+ const integer &
+ get_integer () const { return *this; }
+
+ bool
+ is_zero_p () const
+ {
+ return mpz_cmp_si (m_mpz, 0) == 0;
+ }
+
+ bool
+ is_one_p () const
+ {
+ return mpz_cmp_si (m_mpz, 1) == 0;
+ }
+
+ integer &
+ operator= (const integer &other)
+ {
+ mpz_set (m_mpz, other.m_mpz);
+ return *this;
+ }
+
+ integer &
+ operator= (integer &&other)
+ {
+ std::swap (m_mpz, other.m_mpz);
+ return *this;
+ }
+
+ static int
+ cmp (const integer &lhs, const integer &rhs)
+ {
+ return mpz_cmp (lhs.m_mpz, rhs.m_mpz);
+ }
+
+ void
+ dump_to_pp (pretty_printer *pp) const;
+
+ void
+ dump () const;
+
+ std::unique_ptr<json::value>
+ to_json () const;
+
+ std::unique_ptr<diagnostics::markup::node>
+ make_markup_node () const;
+
+ /* Overloaded operators. */
+
+ /* Comparison. */
+
+ bool
+ operator== (const integer &other) const
+ {
+ return mpz_cmp (m_mpz, other.m_mpz) == 0;
+ }
+
+ bool
+ operator== (int i) const
+ {
+ return mpz_cmp_si (m_mpz, i) == 0;
+ }
+
+ bool
+ operator!= (const integer &other) const
+ {
+ return mpz_cmp (m_mpz, other.m_mpz) != 0;
+ }
+
+ bool
+ operator!= (int i) const
+ {
+ return mpz_cmp_si (m_mpz, i) != 0;
+ }
+
+ bool
+ operator< (const integer &other) const
+ {
+ return mpz_cmp (m_mpz, other.m_mpz) < 0;
+ }
+
+ bool
+ operator< (int i) const
+ {
+ return mpz_cmp_si (m_mpz, i) < 0;
+ }
+
+ bool
+ operator<= (const integer &other) const
+ {
+ return mpz_cmp (m_mpz, other.m_mpz) <= 0;
+ }
+
+ bool
+ operator> (const integer &other) const
+ {
+ return mpz_cmp (m_mpz, other.m_mpz) > 0;
+ }
+
+ bool
+ operator>= (const integer &other) const
+ {
+ return mpz_cmp (m_mpz, other.m_mpz) >= 0;
+ }
+
+ /* Addition. */
+
+ integer
+ operator+ (const integer &other) const
+ {
+ integer result;
+ mpz_add (result.m_mpz, m_mpz, other.m_mpz);
+ return result;
+ }
+
+ integer &
+ operator+= (const integer &other)
+ {
+ integer tmp = *this + other;
+ *this = std::move (tmp);
+ return *this;
+ }
+
+ /* Subtraction. */
+
+ integer
+ operator- (const integer &other) const
+ {
+ integer result;
+ mpz_sub (result.m_mpz, m_mpz, other.m_mpz);
+ return result;
+ }
+
+ integer
+ operator- () const
+ {
+ integer result;
+ mpz_neg (result.m_mpz, m_mpz);
+ return result;
+ }
+
+ integer &
+ operator-= (const integer &other)
+ {
+ integer tmp = *this - other;
+ *this = std::move (tmp);
+ return *this;
+ }
+
+ /* Multiplication. */
+
+ integer
+ operator* (const integer &other) const
+ {
+ integer result;
+ mpz_mul (result.m_mpz, m_mpz, other.m_mpz);
+ return result;
+ }
+
+ /* Division. */
+
+ integer
+ floor_div (const integer &other) const
+ {
+ gcc_assert (other != 0);
+
+ integer result;
+ mpz_fdiv_q (result.m_mpz, m_mpz, other.m_mpz);
+ return result;
+ }
+
+ /* Modulus. */
+
+ integer
+ floor_mod (const integer &other) const
+ {
+ gcc_assert (other != 0);
+
+ integer result;
+ mpz_fdiv_r (result.m_mpz, m_mpz, other.m_mpz);
+ return result;
+ }
+
+ long
+ as_long () const
+ {
+ return mpz_get_si (m_mpz);
+ }
+
+ unsigned long
+ as_unsigned_long () const
+ {
+ return mpz_get_ui (m_mpz);
+ }
+
+ mpz_t &
+ access_mpz () { return m_mpz; }
+
+private:
+ mpz_t m_mpz;
+};
+
+integer
+convert_from_integer_cst (const_tree int_cst);
+
+tree
+make_integer_cst_from_integer (tree type, const integer &value, bool wrap);
+
+using concrete_integer = integer;
+
+class pp_element_integer : public pp_element
+{
+public:
+ pp_element_integer (integer val)
+ : m_val (std::move (val))
+ {
+ }
+
+ void add_to_phase_2 (pp_markup::context &ctxt) final override
+ {
+ m_val.dump_to_pp (&ctxt.m_pp);
+ }
+
+private:
+ integer m_val;
+};
+
+} // namespace ana
+
+#endif /* GCC_ANALYZER_INTEGER_H */
--
2.56.0