Use __GNUC__ instead of SECP256K1_GNUC_PREREQ
What changed, and why it matters
This commit is a routine cleanup of compiler feature checks in the secp256k1 cryptographic library. It replaces a custom version-check macro with a simpler check for whether the compiler is GCC (or claims to be GCC, like Clang). The change does not fix a security bug and does not introduce a clear vulnerability; it removes support for very old GCC versions that are no longer targeted.
No security action required. Review as normal build-system/compiler-compatibility cleanup.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The patch removes all uses of SECP256K1_GNUC_PREREQ and replaces them with defined(GNUC). This affects attribute macros (warn_unused_result, nonnull), inline hints (inline, forceinline-style), __builtin_expect, __restrict, and __builtin_ctz* usage. The commit message states that all reasonably supported GCC versions already have these features, and that the old macro was misleading because Clang advertises itself as GCC 4.2. There is no functional code change for supported compilers; the only behavioral difference is that ancient GCC versions (<3.4, <3.0, <2.7) would no longer get these optimizations/attributes. No security defect is present in the diff.
Changed components
include/secp256k1.hsrc/util.hInspect captured patch +10 / −10
diff --git a/include/secp256k1.h b/include/secp256k1.h
index 2f3383e..0fa4d67 100644
--- a/include/secp256k1.h
+++ b/include/secp256k1.h
@@ -178,12 +178,12 @@ typedef int (*secp256k1_nonce_function)(
/* Warning attributes
* NONNULL is not used if SECP256K1_BUILD is set to avoid the compiler optimizing out
* some paranoid null checks. */
-# if defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4)
+# if defined(__GNUC__)
# define SECP256K1_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
# else
# define SECP256K1_WARN_UNUSED_RESULT
# endif
-# if !defined(SECP256K1_BUILD) && defined(__GNUC__) && SECP256K1_GNUC_PREREQ(3, 4)
+# if !defined(SECP256K1_BUILD) && defined(__GNUC__)
# define SECP256K1_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x)))
# else
# define SECP256K1_ARG_NONNULL(_x)
diff --git a/src/util.h b/src/util.h
index 492a592..163f932 100644
--- a/src/util.h
+++ b/src/util.h
@@ -46,7 +46,7 @@ static void print_buf_plain(const unsigned char *buf, size_t len) {
}
# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
-# if SECP256K1_GNUC_PREREQ(2,7)
+# if defined(__GNUC__)
# define SECP256K1_INLINE __inline__
# elif (defined(_MSC_VER))
# define SECP256K1_INLINE __inline
@@ -58,7 +58,7 @@ static void print_buf_plain(const unsigned char *buf, size_t len) {
# endif
# if !defined(_DEBUG) && !defined(__NO_INLINE__) && !defined(__OPTIMIZE_SIZE__)
-# if defined(__OPTIMIZE__) && (SECP256K1_GNUC_PREREQ(3, 0) || defined(__clang__))
+# if defined(__OPTIMIZE__) && defined(__GNUC__)
# define SECP256K1_FORCE_INLINE SECP256K1_INLINE __attribute__((always_inline))
# elif defined(_MSC_VER)
# define SECP256K1_FORCE_INLINE __forceinline
@@ -143,7 +143,7 @@ static const secp256k1_callback default_error_callback = {
} while(0)
#endif
-#if SECP256K1_GNUC_PREREQ(3, 0)
+#if defined(__GNUC__)
#define EXPECT(x,c) __builtin_expect((x),(c))
#else
#define EXPECT(x,c) (x)
@@ -199,7 +199,7 @@ static SECP256K1_INLINE void *checked_malloc(const secp256k1_callback* cb, size_
# define SECP256K1_RESTRICT
#else
# if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
-# if SECP256K1_GNUC_PREREQ(3,0)
+# if defined(__GNUC__)
# define SECP256K1_RESTRICT __restrict__
# elif (defined(_MSC_VER) && _MSC_VER >= 1400)
# define SECP256K1_RESTRICT __restrict
@@ -392,13 +392,13 @@ static SECP256K1_INLINE int secp256k1_ctz64_var_debruijn(uint64_t x) {
/* Determine the number of trailing zero bits in a (non-zero) 32-bit x. */
static SECP256K1_INLINE int secp256k1_ctz32_var(uint32_t x) {
VERIFY_CHECK(x != 0);
-#if (__has_builtin(__builtin_ctz) || SECP256K1_GNUC_PREREQ(3,4))
+#if (__has_builtin(__builtin_ctz) || defined(__GNUC__))
/* If the unsigned type is sufficient to represent the largest uint32_t, consider __builtin_ctz. */
if (((unsigned)UINT32_MAX) == UINT32_MAX) {
return __builtin_ctz(x);
}
#endif
-#if (__has_builtin(__builtin_ctzl) || SECP256K1_GNUC_PREREQ(3,4))
+#if (__has_builtin(__builtin_ctzl) || defined(__GNUC__))
/* Otherwise consider __builtin_ctzl (the unsigned long type is always at least 32 bits). */
return __builtin_ctzl(x);
#else
@@ -410,13 +410,13 @@ static SECP256K1_INLINE int secp256k1_ctz32_var(uint32_t x) {
/* Determine the number of trailing zero bits in a (non-zero) 64-bit x. */
static SECP256K1_INLINE int secp256k1_ctz64_var(uint64_t x) {
VERIFY_CHECK(x != 0);
-#if (__has_builtin(__builtin_ctzl) || SECP256K1_GNUC_PREREQ(3,4))
+#if (__has_builtin(__builtin_ctzl) || defined(__GNUC__))
/* If the unsigned long type is sufficient to represent the largest uint64_t, consider __builtin_ctzl. */
if (((unsigned long)UINT64_MAX) == UINT64_MAX) {
return __builtin_ctzl(x);
}
#endif
-#if (__has_builtin(__builtin_ctzll) || SECP256K1_GNUC_PREREQ(3,4))
+#if (__has_builtin(__builtin_ctzll) || defined(__GNUC__))
/* Otherwise consider __builtin_ctzll (the unsigned long long type is always at least 64 bits). */
return __builtin_ctzll(x);
#else
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.