blob: 0e6a4f949c9b0cad239d30231e0be627eaf31060 [file] [log] [blame]
Make GMP compile in a noexcept environment
GMP throws exceptions to indicate errors like failed allocation or negative
factorials. Change these to print a terse error message and SIGABRT.
Ideally, these would `LOG(FATAL)`. However, giving GMP an Abseil dependency
breaks Haskell binaries. (The problematic dependency chain appears to be
Haskell -> GMP -> Abseil -> libunwind.) Instead, just log using `std::cerr` and
call `std::abort`; the abnormal termination will trigger a stack trace in
google3 binaries anyway.
This is an updated version of cl/50915228.
--- a/gmpxx.h
+++ b/gmpxx.h
@@ -39,7 +39,12 @@ see https://www.gnu.org/licenses/. */
#include <utility>
#include <algorithm> /* swap */
#include <string>
+#ifdef __EXCEPTIONS
#include <stdexcept>
+#else
+#include <cstdlib>
+#include <iostream>
+#endif
#include <cfloat>
#include <gmp.h>
@@ -1240,7 +1245,14 @@ struct __gmp_fac_function
static void eval(mpz_ptr z, signed long l)
{
if (l < 0)
+#ifdef __EXCEPTIONS
throw std::domain_error ("factorial(negative)");
+#else
+ {
+ std::cerr << "std::domain_error: factorial(negative)\n";
+ std::abort();
+ }
+#endif
eval(z, static_cast<unsigned long>(l));
}
static void eval(mpz_ptr z, mpz_srcptr w)
@@ -1248,9 +1260,23 @@ struct __gmp_fac_function
if (!mpz_fits_ulong_p(w))
{
if (mpz_sgn(w) < 0)
+#ifdef __EXCEPTIONS
throw std::domain_error ("factorial(negative)");
+#else
+ {
+ std::cerr << "std::domain_error: factorial(negative)\n";
+ std::abort();
+ }
+#endif
else
+#ifdef __EXCEPTIONS
throw std::bad_alloc(); // or std::overflow_error ("factorial")?
+#else
+ {
+ std::cerr << "std::bad_alloc\n";
+ std::abort();
+ }
+#endif
}
eval(z, mpz_get_ui(w));
}
@@ -1264,7 +1290,14 @@ struct __gmp_primorial_function
static void eval(mpz_ptr z, signed long l)
{
if (l < 0)
+#ifdef __EXCEPTIONS
throw std::domain_error ("primorial(negative)");
+#else
+ {
+ std::cerr << "std::domain_error: primorial(negative)\n";
+ std::abort();
+ }
+#endif
eval(z, static_cast<unsigned long>(l));
}
static void eval(mpz_ptr z, mpz_srcptr w)
@@ -1272,9 +1305,23 @@ struct __gmp_primorial_function
if (!mpz_fits_ulong_p(w))
{
if (mpz_sgn(w) < 0)
+#ifdef __EXCEPTIONS
throw std::domain_error ("primorial(negative)");
+#else
+ {
+ std::cerr << "std::domain_error: primorial(negative)\n";
+ std::abort();
+ }
+#endif
else
+#ifdef __EXCEPTIONS
throw std::bad_alloc(); // or std::overflow_error ("primorial")?
+#else
+ {
+ std::cerr << "std::bad_alloc\n";
+ std::abort();
+ }
+#endif
}
eval(z, mpz_get_ui(w));
}
@@ -1299,7 +1346,14 @@ struct __gmp_fib_function
static void eval(mpz_ptr z, mpz_srcptr w)
{
if (!mpz_fits_slong_p(w))
+#ifdef __EXCEPTIONS
throw std::bad_alloc(); // or std::overflow_error ("fibonacci")?
+#else
+ {
+ std::cerr << "std::bad_alloc\n";
+ std::abort();
+ }
+#endif
eval(z, mpz_get_si(w));
}
static void eval(mpz_ptr z, double d)
@@ -1650,7 +1704,14 @@ public:
if (mpz_init_set_str (mp, s, base) != 0)
{
mpz_clear (mp);
+#ifdef __EXCEPTIONS
throw std::invalid_argument ("mpz_set_str");
+#else
+ {
+ std::cerr << "std::invalid_argument: mpz_set_str\n";
+ std::abort();
+ }
+#endif
}
}
explicit __gmp_expr(const std::string &s, int base = 0)
@@ -1658,7 +1719,14 @@ public:
if (mpz_init_set_str(mp, s.c_str(), base) != 0)
{
mpz_clear (mp);
+#ifdef __EXCEPTIONS
throw std::invalid_argument ("mpz_set_str");
+#else
+ {
+ std::cerr << "std::invalid_argument: mpz_set_str\n";
+ std::abort();
+ }
+#endif
}
}
@@ -1685,13 +1753,27 @@ public:
__gmp_expr & operator=(const char *s)
{
if (mpz_set_str (mp, s, 0) != 0)
+#ifdef __EXCEPTIONS
throw std::invalid_argument ("mpz_set_str");
+#else
+ {
+ std::cerr << "std::invalid_argument: mpz_set_str\n";
+ std::abort();
+ }
+#endif
return *this;
}
__gmp_expr & operator=(const std::string &s)
{
if (mpz_set_str(mp, s.c_str(), 0) != 0)
+#ifdef __EXCEPTIONS
throw std::invalid_argument ("mpz_set_str");
+#else
+ {
+ std::cerr << "std::invalid_argument: mpz_set_str\n";
+ std::abort();
+ }
+#endif
return *this;
}
@@ -1828,7 +1910,14 @@ public:
else if (mpq_set_str(mp, s, base) != 0)
{
mpq_clear (mp);
+#ifdef __EXCEPTIONS
throw std::invalid_argument ("mpq_set_str");
+#else
+ {
+ std::cerr << "std::invalid_argument: mpq_set_str\n";
+ std::abort();
+ }
+#endif
}
}
explicit __gmp_expr(const std::string &s, int base = 0)
@@ -1837,7 +1926,14 @@ public:
if (mpq_set_str (mp, s.c_str(), base) != 0)
{
mpq_clear (mp);
+#ifdef __EXCEPTIONS
throw std::invalid_argument ("mpq_set_str");
+#else
+ {
+ std::cerr << "std::invalid_argument: mpq_set_str\n";
+ std::abort();
+ }
+#endif
}
}
explicit __gmp_expr(mpq_srcptr q)
@@ -1874,13 +1970,27 @@ public:
__gmp_expr & operator=(const char *s)
{
if (mpq_set_str (mp, s, 0) != 0)
+#ifdef __EXCEPTIONS
throw std::invalid_argument ("mpq_set_str");
+#else
+ {
+ std::cerr << "std::invalid_argument: mpq_set_str\n";
+ std::abort();
+ }
+#endif
return *this;
}
__gmp_expr & operator=(const std::string &s)
{
if (mpq_set_str(mp, s.c_str(), 0) != 0)
+#ifdef __EXCEPTIONS
throw std::invalid_argument ("mpq_set_str");
+#else
+ {
+ std::cerr << "std::invalid_argument: mpq_set_str\n";
+ std::abort();
+ }
+#endif
return *this;
}
@@ -2038,7 +2148,14 @@ public:
if (mpf_init_set_str (mp, s, 0) != 0)
{
mpf_clear (mp);
+#ifdef __EXCEPTIONS
throw std::invalid_argument ("mpf_set_str");
+#else
+ {
+ std::cerr << "std::invalid_argument: mpf_set_str\n";
+ std::abort();
+ }
+#endif
}
}
__gmp_expr(const char *s, mp_bitcnt_t prec, int base = 0)
@@ -2047,7 +2164,14 @@ public:
if (mpf_set_str(mp, s, base) != 0)
{
mpf_clear (mp);
+#ifdef __EXCEPTIONS
throw std::invalid_argument ("mpf_set_str");
+#else
+ {
+ std::cerr << "std::invalid_argument: mpf_set_str\n";
+ std::abort();
+ }
+#endif
}
}
explicit __gmp_expr(const std::string &s)
@@ -2055,7 +2179,14 @@ public:
if (mpf_init_set_str(mp, s.c_str(), 0) != 0)
{
mpf_clear (mp);
+#ifdef __EXCEPTIONS
throw std::invalid_argument ("mpf_set_str");
+#else
+ {
+ std::cerr << "std::invalid_argument: mpf_set_str\n";
+ std::abort();
+ }
+#endif
}
}
__gmp_expr(const std::string &s, mp_bitcnt_t prec, int base = 0)
@@ -2064,7 +2195,14 @@ public:
if (mpf_set_str(mp, s.c_str(), base) != 0)
{
mpf_clear (mp);
+#ifdef __EXCEPTIONS
throw std::invalid_argument ("mpf_set_str");
+#else
+ {
+ std::cerr << "std::invalid_argument: mpf_set_str\n";
+ std::abort();
+ }
+#endif
}
}
@@ -2093,13 +2231,27 @@ public:
__gmp_expr & operator=(const char *s)
{
if (mpf_set_str (mp, s, 0) != 0)
+#ifdef __EXCEPTIONS
throw std::invalid_argument ("mpf_set_str");
+#else
+ {
+ std::cerr << "std::invalid_argument: mpf_set_str\n";
+ std::abort();
+ }
+#endif
return *this;
}
__gmp_expr & operator=(const std::string &s)
{
if (mpf_set_str(mp, s.c_str(), 0) != 0)
+#ifdef __EXCEPTIONS
throw std::invalid_argument ("mpf_set_str");
+#else
+ {
+ std::cerr << "std::invalid_argument: mpf_set_str\n";
+ std::abort();
+ }
+#endif
return *this;
}
@@ -3505,7 +3657,14 @@ public:
mp_bitcnt_t size)
{
if (f (state, size) == 0)
+#ifdef __EXCEPTIONS
throw std::length_error ("gmp_randinit_lc_2exp_size");
+#else
+ {
+ std::cerr << "std::length_error: gmp_randinit_lc_2exp_size\n";
+ std::abort();
+ }
+#endif
}
~gmp_randclass() { gmp_randclear(state); }