From 6a2cfde29ffb442daa944a4a109991f21d12bfc6 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Wed, 23 Jan 2019 13:07:44 +0000 Subject: [PATCH] gtypes: Define signed integer minimum values in terms of maximum values MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is what limits.h does. It avoids a problem when compiling with MSVC (in C++ mode) on Windows, whereby the 0x80000000 constant is interpreted as unsigned, and *then* the unary minus is applied to it. https://docs.microsoft.com/en-us/cpp/error-messages/compiler-warnings/compiler-warning-level-2-c4146?view=vs-2017 Add a test which should hopefully catch problems with different compilers’ interpretations of this in future. Signed-off-by: Philip Withnall https://gitlab.gnome.org/GNOME/glib/issues/1663 --- glib/gtypes.h | 8 ++++---- glib/tests/utils.c | 31 +++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/glib/gtypes.h b/glib/gtypes.h index 67adb7f1f..f5b369dc5 100644 --- a/glib/gtypes.h +++ b/glib/gtypes.h @@ -58,19 +58,19 @@ typedef float gfloat; typedef double gdouble; /* Define min and max constants for the fixed size numerical types */ -#define G_MININT8 ((gint8) -0x80) +#define G_MININT8 ((gint8) (-G_MAXINT8 - 1)) #define G_MAXINT8 ((gint8) 0x7f) #define G_MAXUINT8 ((guint8) 0xff) -#define G_MININT16 ((gint16) -0x8000) +#define G_MININT16 ((gint16) (-G_MAXINT16 - 1)) #define G_MAXINT16 ((gint16) 0x7fff) #define G_MAXUINT16 ((guint16) 0xffff) -#define G_MININT32 ((gint32) -0x80000000) +#define G_MININT32 ((gint32) (-G_MAXINT32 - 1)) #define G_MAXINT32 ((gint32) 0x7fffffff) #define G_MAXUINT32 ((guint32) 0xffffffff) -#define G_MININT64 ((gint64) G_GINT64_CONSTANT(-0x8000000000000000)) +#define G_MININT64 ((gint64) (-G_MAXINT64 - G_GINT64_CONSTANT(1))) #define G_MAXINT64 G_GINT64_CONSTANT(0x7fffffffffffffff) #define G_MAXUINT64 G_GUINT64_CONSTANT(0xffffffffffffffff) diff --git a/glib/tests/utils.c b/glib/tests/utils.c index 79bc08184..421a70560 100644 --- a/glib/tests/utils.c +++ b/glib/tests/utils.c @@ -655,6 +655,36 @@ test_check_setuid (void) g_assert (!res); } +/* Test the defined integer limits are correct, as some compilers have had + * problems with signed/unsigned conversion in the past. These limits should not + * vary between platforms, compilers or architectures. + * + * Use string comparisons to avoid the same systematic problems with unary minus + * application in C++. See https://gitlab.gnome.org/GNOME/glib/issues/1663. */ +static void +test_int_limits (void) +{ + gchar *str = NULL; + + g_test_bug ("https://gitlab.gnome.org/GNOME/glib/issues/1663"); + + str = g_strdup_printf ("%d %d %u\n" + "%" G_GINT16_FORMAT " %" G_GINT16_FORMAT " %" G_GUINT16_FORMAT "\n" + "%" G_GINT32_FORMAT " %" G_GINT32_FORMAT " %" G_GUINT32_FORMAT "\n" + "%" G_GINT64_FORMAT " %" G_GINT64_FORMAT " %" G_GUINT64_FORMAT "\n", + G_MININT8, G_MAXINT8, G_MAXUINT8, + G_MININT16, G_MAXINT16, G_MAXUINT16, + G_MININT32, G_MAXINT32, G_MAXUINT32, + G_MININT64, G_MAXINT64, G_MAXUINT64); + + g_assert_cmpstr (str, ==, + "-128 127 255\n" + "-32768 32767 65535\n" + "-2147483648 2147483647 4294967295\n" + "-9223372036854775808 9223372036854775807 18446744073709551615\n"); + g_free (str); +} + int main (int argc, char *argv[]) @@ -706,6 +736,7 @@ main (int argc, g_test_add_func ("/utils/nullify", test_nullify); g_test_add_func ("/utils/atexit", test_atexit); g_test_add_func ("/utils/check-setuid", test_check_setuid); + g_test_add_func ("/utils/int-limits", test_int_limits); return g_test_run (); }