From f24bb8dc190accee16032d53622f470462b3a000 Mon Sep 17 00:00:00 2001 From: Philip Withnall Date: Fri, 28 Jun 2024 16:58:34 +0100 Subject: [PATCH] gutilsprivate: Factor out g_isnan() helper MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are a couple of places in the code which use `isnan()` and have platform-specific workarounds for it. Unify those, and extend the workaround to work for msys2-mingw32. It seems that msys2-mingw32 can’t automatically use `isnan()` in a wider mode than `float`: ``` In file included from ../glib/gdatetime.c:60: ../glib/gdatetime.c: In function 'g_date_time_new': ../glib/gdatetime.c:1648:14: error: conversion from 'gdouble' {aka 'double'} to 'float' may change value [-Werror=float-conversion] 1648 | isnan (seconds) || | ^~~~~~~ cc1.exe: all warnings being treated as errors ``` See: https://gitlab.gnome.org/pwithnall/glib/-/jobs/4022715 Using it in float mode on all platforms should not change behaviour, as a conversion from `(double) NAN` to `float` should still give `NAN`. Signed-off-by: Philip Withnall Helps: #3405 --- glib/gdatetime.c | 8 ++------ glib/gutilsprivate.h | 18 ++++++++++++++++++ glib/tests/strfuncs.c | 8 ++++---- 3 files changed, 24 insertions(+), 10 deletions(-) diff --git a/glib/gdatetime.c b/glib/gdatetime.c index 3ffb7b8e4..0f3500ca2 100644 --- a/glib/gdatetime.c +++ b/glib/gdatetime.c @@ -82,15 +82,11 @@ #include "gtestutils.h" #include "gthread.h" #include "gtimezone.h" +#include "gutilsprivate.h" #ifndef G_OS_WIN32 #include #include -#else -#if defined (_MSC_VER) && (_MSC_VER < 1800) -/* fallback implementation for isnan() on VS2012 and earlier */ -#define isnan _isnan -#endif #endif /* !G_OS_WIN32 */ struct _GDateTime @@ -1645,7 +1641,7 @@ g_date_time_new (GTimeZone *tz, day < 1 || day > days_in_months[GREGORIAN_LEAP (year)][month] || hour < 0 || hour > 23 || minute < 0 || minute > 59 || - isnan (seconds) || + g_isnan (seconds) || seconds < 0.0 || seconds >= 60.0) return NULL; diff --git a/glib/gutilsprivate.h b/glib/gutilsprivate.h index 7bbde7143..57177350d 100644 --- a/glib/gutilsprivate.h +++ b/glib/gutilsprivate.h @@ -26,6 +26,7 @@ #include "gtypes.h" #include "gtestutils.h" +#include #include G_BEGIN_DECLS @@ -61,6 +62,23 @@ gboolean _g_localtime (time_t timet, struct tm *tm); gboolean g_set_prgname_once (const gchar *prgname); +/* Although isnan() is defined as a type-independent macro in C99, mingw32 + * doesn’t seem to support that (it defines `isnan (float d)` only). Older + * MSVC toolchains don’t support C99 either. So we provide an internal + * abstraction macro. + * + * This should not be made public; toolchains will soon enough catch up with + * C99, so third party code should just use isnan(). */ +static inline int +g_isnan (double d) +{ +#if (defined (_MSC_VER) && (_MSC_VER < 1800)) || defined(__MINGW32__) + return _isnan (d); +#else + return isnan (d); +#endif +} + G_END_DECLS #endif /* __G_UTILS_PRIVATE_H__ */ diff --git a/glib/tests/strfuncs.c b/glib/tests/strfuncs.c index 544cee936..5d4dfa3aa 100644 --- a/glib/tests/strfuncs.c +++ b/glib/tests/strfuncs.c @@ -34,11 +34,11 @@ #include #include #include + #include "glib.h" +#include "gutilsprivate.h" #if defined (_MSC_VER) && (_MSC_VER <= 1800) -#define isnan(x) _isnan(x) - #ifndef NAN static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff}; #define NAN (*(const float *) __nan) @@ -1625,7 +1625,7 @@ check_strtod_string (gchar *number, setlocale (LC_NUMERIC, locales[l]); d = g_ascii_strtod (number, &end); - g_assert_true (isnan (res) ? isnan (d) : (d == res)); + g_assert_true (g_isnan (res) ? g_isnan (d) : (d == res)); g_assert_true ((gsize) (end - number) == (check_end ? correct_len : strlen (number))); } @@ -1660,7 +1660,7 @@ test_ascii_strtod (void) /* Do this before any call to setlocale. */ our_nan = atof ("NaN"); #endif - g_assert_true (isnan (our_nan)); + g_assert_true (g_isnan (our_nan)); #ifdef INFINITY our_inf = INFINITY;