+/* Overflow-checked unsigned integer arithmetic
+ */
+#ifndef _GLIB_TEST_OVERFLOW_FALLBACK
+/* https://bugzilla.gnome.org/show_bug.cgi?id=769104 */
+#if __GNUC__ >= 5 && !defined(__INTEL_COMPILER)
+#define _GLIB_HAVE_BUILTIN_OVERFLOW_CHECKS
+#elif g_macro__has_builtin(__builtin_add_overflow)
+#define _GLIB_HAVE_BUILTIN_OVERFLOW_CHECKS
+#endif
+#endif
+
+#ifdef _GLIB_HAVE_BUILTIN_OVERFLOW_CHECKS
+
+#define g_uint_checked_add(dest, a, b) \
+ (!__builtin_add_overflow(a, b, dest))
+#define g_uint_checked_mul(dest, a, b) \
+ (!__builtin_mul_overflow(a, b, dest))
+
+#define g_uint64_checked_add(dest, a, b) \
+ (!__builtin_add_overflow(a, b, dest))
+#define g_uint64_checked_mul(dest, a, b) \
+ (!__builtin_mul_overflow(a, b, dest))
+
+#define g_size_checked_add(dest, a, b) \
+ (!__builtin_add_overflow(a, b, dest))
+#define g_size_checked_mul(dest, a, b) \
+ (!__builtin_mul_overflow(a, b, dest))
+
+#else /* !_GLIB_HAVE_BUILTIN_OVERFLOW_CHECKS */
+
+/* The names of the following inlines are private. Use the macro
+ * definitions above.
+ */
+static inline gboolean _GLIB_CHECKED_ADD_UINT (guint *dest, guint a, guint b) {
+ *dest = a + b; return *dest >= a; }
+static inline gboolean _GLIB_CHECKED_MUL_UINT (guint *dest, guint a, guint b) {
+ *dest = a * b; return !a || *dest / a == b; }
+static inline gboolean _GLIB_CHECKED_ADD_UINT64 (guint64 *dest, guint64 a, guint64 b) {
+ *dest = a + b; return *dest >= a; }
+static inline gboolean _GLIB_CHECKED_MUL_UINT64 (guint64 *dest, guint64 a, guint64 b) {
+ *dest = a * b; return !a || *dest / a == b; }
+static inline gboolean _GLIB_CHECKED_ADD_SIZE (gsize *dest, gsize a, gsize b) {
+ *dest = a + b; return *dest >= a; }
+static inline gboolean _GLIB_CHECKED_MUL_SIZE (gsize *dest, gsize a, gsize b) {
+ *dest = a * b; return !a || *dest / a == b; }
+
+#define g_uint_checked_add(dest, a, b) \
+ _GLIB_CHECKED_ADD_UINT(dest, a, b)
+#define g_uint_checked_mul(dest, a, b) \
+ _GLIB_CHECKED_MUL_UINT(dest, a, b)
+
+#define g_uint64_checked_add(dest, a, b) \
+ _GLIB_CHECKED_ADD_UINT64(dest, a, b)
+#define g_uint64_checked_mul(dest, a, b) \
+ _GLIB_CHECKED_MUL_UINT64(dest, a, b)
+
+#define g_size_checked_add(dest, a, b) \
+ _GLIB_CHECKED_ADD_SIZE(dest, a, b)
+#define g_size_checked_mul(dest, a, b) \
+ _GLIB_CHECKED_MUL_SIZE(dest, a, b)
+
+#endif /* !_GLIB_HAVE_BUILTIN_OVERFLOW_CHECKS */
+