Commit 2848923a2f5099b6d105b0b30212134d84377dee

lhchavez 2019-01-08T17:32:23

Let GCC use the add/mul overflow intrinsics This change tweaks the macros for git__{add,multiply}_sizet_overflow so that GCC can use them. It also stops using the uadd,umul versions since the add,mul can handle way more cases.

diff --git a/src/integer.h b/src/integer.h
index 30528db..98d2b73 100644
--- a/src/integer.h
+++ b/src/integer.h
@@ -55,16 +55,36 @@ GIT_INLINE(bool) git__add_uint64_overflow(uint64_t *out, uint64_t one, uint64_t 
 }
 
 /* Use clang/gcc compiler intrinsics whenever possible */
-#if (SIZE_MAX == ULONG_MAX) && __has_builtin(__builtin_uaddl_overflow)
-# define git__add_sizet_overflow(out, one, two) \
-	__builtin_uaddl_overflow(one, two, out)
-# define git__multiply_sizet_overflow(out, one, two) \
-	__builtin_umull_overflow(one, two, out)
-#elif (SIZE_MAX == UINT_MAX) && __has_builtin(__builtin_uadd_overflow)
-# define git__add_sizet_overflow(out, one, two) \
-	__builtin_uadd_overflow(one, two, out)
-# define git__multiply_sizet_overflow(out, one, two) \
-	__builtin_umul_overflow(one, two, out)
+#if (__has_builtin(__builtin_add_overflow) || \
+     (defined(__GNUC__) && (__GNUC__ >= 5)))
+
+/*
+ * Even though __builtin_{add,mul}_overflow should be able to handle all
+ * possible cases (since it can accept any type), under some configurations
+ * clang would need a dependency on compiler-rt. In order to avoid that, we
+ * attempt to choose one of the explicit unsigned long long / unsigned long
+ * versions of the intrinsics if possible. Unfortunately, unsigned long long
+ * and unsigned long are still different types to the compiler, so we need to
+ * still do some additional sniffing to prevent MinGW 64 from choosing the
+ * wrong version and triggering compiler warnings.
+ */
+#	if (SIZE_MAX == ULLONG_MAX) && (ULONG_MAX == ULLONG_MAX) && defined(_WIN64)
+#		define git__add_sizet_overflow(out, one, two) \
+			__builtin_uaddll_overflow(one, two, out)
+#		define git__multiply_sizet_overflow(out, one, two) \
+			__builtin_umulll_overflow(one, two, out)
+#	elif (SIZE_MAX == ULONG_MAX) && (ULONG_MAX == ULLONG_MAX)
+#		define git__add_sizet_overflow(out, one, two) \
+			__builtin_uaddl_overflow(one, two, out)
+#		define git__multiply_sizet_overflow(out, one, two) \
+			__builtin_umull_overflow(one, two, out)
+#	else
+#		define git__add_sizet_overflow(out, one, two) \
+			__builtin_add_overflow(one, two, out)
+#		define git__multiply_sizet_overflow(out, one, two) \
+			__builtin_mul_overflow(one, two, out)
+#	endif
+
 #else
 
 /**