Define CLANG/GNUC_PREREQ macros to check gcc/clang minimum version
authorIvan Maidanski <ivmai@mail.ru>
Tue, 7 Mar 2017 15:19:29 +0000 (18:19 +0300)
committerIvan Maidanski <ivmai@mail.ru>
Tue, 7 Mar 2017 15:19:29 +0000 (18:19 +0300)
(code refactoring)

* cord/cordxtra.c (CORD_ATTR_UNUSED): Use GC_GNUC_PREREQ() instead of
direct use of __GNUC[_MINOR]__.
* gc_cpp.cc (GC_NEW_DELETE_NEED_THROW): Likewise.
* include/gc_config_macros.h (GC_API, GC_ATTR_MALLOC, GC_ATTR_ALLOC_SIZE,
GC_ATTR_NONNULL, GC_ATTR_DEPRECATED, GC_RETURN_ADDR,
GC_RETURN_ADDR_PARENT, GC_PTHREAD_EXIT_ATTRIBUTE): Likewise.
* include/gc_cpp.h (GC_NO_OPERATOR_NEW_ARRAY): Likewise.
* include/gc_inline.h (GC_EXPECT, GC_PREFETCH_FOR_WRITE): Likewise.
* include/new_gc_alloc.h: Likewise.
* include/private/gc_priv.h (GC_INNER, GC_ATTR_UNUSED, EXPECT, GC_INLINE,
GC_ATTR_NOINLINE, GC_API_OSCALL, GC_ATTR_FORMAT_PRINTF,
NONNULL_ARG_NOT_NULL): Likewise.
* include/private/gc_priv.h [CANCEL_SAFE] (GC_cancel_disable_count):
Likewise.
* include/private/gcconfig.h (HAVE_BUILTIN_UNWIND_INIT, PREFETCH,
GC_PREFETCH_FOR_WRITE): Likewise.
* include/private/gcconfig.h [I386 && LINUX && __ELF__]
(GC_NO_SIGSETJMP): Likewise.
* include/private/gcconfig.h [X86_64 && MSWIN32] (MPROTECT_VDB):
Likewise.
* include/private/thread_local_alloc.h [CYGWIN32] (USE_PTHREAD_SPECIFIC):
Likewise.
* include/private/thread_local_alloc.h [LINUX && !ARM32 && !AVR32
|| PLATFORM_ANDROID && !__clang__] (USE_COMPILER_TLS): Likewise.
* mark.c [MSWIN32 || MSWINCE] (GC_mark_some): Likewise.
* mark_rts.c (GC_approx_sp): Likewise.
* tests/test_cpp.cc (ATTR_UNUSED): Likewise.
* tools/setjmp_t.c (nested_sp): Likewise.
* include/gc_config_macros.h (GC_GNUC_PREREQ): New macro (not for
public use).
* include/private/gc_priv.h (GC_CLANG_PREREQ): New private macro.
* include/private/gcconfig.h (HAVE_BUILTIN_UNWIND_INIT): Refine comment.
* include/private/thread_local_alloc.h [LINUX && !ARM32 && !AVR32
|| PLATFORM_ANDROID && !__clang__] (USE_COMPILER_TLS): Use
GC_CLANG_PREREQ() instead of direct use of __clang_major__ and
__clang_minor__.
* mark.c [MSWIN32 || MSWINCE] (GC_mark_some): Likewise.

13 files changed:
cord/cordxtra.c
gc_cpp.cc
include/gc_config_macros.h
include/gc_cpp.h
include/gc_inline.h
include/new_gc_alloc.h
include/private/gc_priv.h
include/private/gcconfig.h
include/private/thread_local_alloc.h
mark.c
mark_rts.c
tests/test_cpp.cc
tools/setjmp_t.c

index cac407d..61df89b 100644 (file)
@@ -63,7 +63,7 @@ typedef void (* oom_fn)(void);
                          ABORT("Out of memory"); }
 # define ABORT(msg) { fprintf(stderr, "%s\n", msg); abort(); }
 
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#if GC_GNUC_PREREQ(3, 4)
 # define CORD_ATTR_UNUSED __attribute__((__unused__))
 #else
 # define CORD_ATTR_UNUSED /* empty */
index 185ec25..04737dc 100644 (file)
--- a/gc_cpp.cc
+++ b/gc_cpp.cc
@@ -29,8 +29,7 @@ built-in "new" and "delete".
 
 #include "gc_cpp.h"
 
-#if !defined(GC_NEW_DELETE_NEED_THROW) && defined(__GNUC__) \
-    && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
+#if GC_GNUC_PREREQ(4, 2) && !defined(GC_NEW_DELETE_NEED_THROW)
 # define GC_NEW_DELETE_NEED_THROW
 #endif
 
index e8748f5..df63c9c 100644 (file)
 /* We separate it only to make gc.h more suitable as documentation.       */
 #if defined(GC_H)
 
+/* Convenient internal macro to test version of GCC.    */
+#if defined(__GNUC__) && defined(__GNUC_MINOR__)
+# define GC_GNUC_PREREQ(major, minor) \
+            ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((major) << 16) + (minor))
+#else
+# define GC_GNUC_PREREQ(major, minor) 0 /* FALSE */
+#endif
+
 /* Some tests for old macros.  These violate our namespace rules and    */
 /* will disappear shortly.  Use the GC_ names.                          */
 #if defined(SOLARIS_THREADS) || defined(_SOLARIS_THREADS) \
 # elif defined(__GNUC__)
     /* Only matters if used in conjunction with -fvisibility=hidden option. */
 #   if defined(GC_BUILD) && !defined(GC_NO_VISIBILITY) \
-            && (__GNUC__ >= 4 || defined(GC_VISIBILITY_HIDDEN_SET))
+            && (GC_GNUC_PREREQ(4, 0) || defined(GC_VISIBILITY_HIDDEN_SET))
 #     define GC_API extern __attribute__((__visibility__("default")))
 #   endif
 # endif
   /* by using custom GC_oom_func then define GC_OOM_FUNC_RETURNS_ALIAS. */
 # ifdef GC_OOM_FUNC_RETURNS_ALIAS
 #   define GC_ATTR_MALLOC /* empty */
-# elif defined(__GNUC__) && (__GNUC__ > 3 \
-                             || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
+# elif GC_GNUC_PREREQ(3, 1)
 #   define GC_ATTR_MALLOC __attribute__((__malloc__))
 # elif defined(_MSC_VER) && _MSC_VER >= 1400
 #   define GC_ATTR_MALLOC __declspec(noalias) __declspec(restrict)
 #   else
 #     define GC_ATTR_ALLOC_SIZE(argnum) /* empty */
 #   endif
-# elif __GNUC__ > 4 \
-       || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3 && !defined(__ICC))
+# elif GC_GNUC_PREREQ(4, 3) && !defined(__ICC)
 #   define GC_ATTR_ALLOC_SIZE(argnum) __attribute__((__alloc_size__(argnum)))
 # else
 #   define GC_ATTR_ALLOC_SIZE(argnum) /* empty */
 #endif
 
 #ifndef GC_ATTR_NONNULL
-# if defined(__GNUC__) && __GNUC__ >= 4
+# if GC_GNUC_PREREQ(4, 0)
 #   define GC_ATTR_NONNULL(argnum) __attribute__((__nonnull__(argnum)))
 # else
 #   define GC_ATTR_NONNULL(argnum) /* empty */
 # ifdef GC_BUILD
 #   undef GC_ATTR_DEPRECATED
 #   define GC_ATTR_DEPRECATED /* empty */
-# elif defined(__GNUC__) && __GNUC__ >= 4
+# elif GC_GNUC_PREREQ(4, 0)
 #   define GC_ATTR_DEPRECATED __attribute__((__deprecated__))
 # elif defined(_MSC_VER) && _MSC_VER >= 1200
 #   define GC_ATTR_DEPRECATED __declspec(deprecated)
      || defined(PLATFORM_ANDROID) || defined(__ANDROID__)) \
     && !defined(GC_CAN_SAVE_CALL_STACKS)
 # define GC_ADD_CALLER
-# if __GNUC__ >= 3 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
+# if GC_GNUC_PREREQ(2, 95)
     /* gcc knows how to retrieve return address, but we don't know      */
     /* how to generate call stacks.                                     */
 #   define GC_RETURN_ADDR (GC_word)__builtin_return_address(0)
-#   if (__GNUC__ >= 4) && (defined(__i386__) || defined(__amd64__) \
-        || defined(__x86_64__) /* and probably others... */)
+#   if GC_GNUC_PREREQ(4, 0) && (defined(__i386__) || defined(__amd64__) \
+                        || defined(__x86_64__) /* and probably others... */)
 #     define GC_HAVE_RETURN_ADDR_PARENT
 #     define GC_RETURN_ADDR_PARENT \
         (GC_word)__builtin_extract_return_addr(__builtin_return_address(1))
      && (defined(GC_LINUX_THREADS) || defined(GC_SOLARIS_THREADS))
 #   define GC_HAVE_PTHREAD_EXIT
     /* Intercept pthread_exit on Linux and Solaris.     */
-#   if defined(__GNUC__) /* since GCC v2.7 */
+#   if GC_GNUC_PREREQ(2, 7)
 #     define GC_PTHREAD_EXIT_ATTRIBUTE __attribute__((__noreturn__))
 #   elif defined(__NORETURN) /* used in Solaris */
 #     define GC_PTHREAD_EXIT_ATTRIBUTE __NORETURN
index 1ed36be..920b836 100644 (file)
@@ -157,8 +157,7 @@ by UseGC.  GC is an alias for UseGC, unless GC_NAME_CONFLICT is defined.
 #if !defined(GC_NO_OPERATOR_NEW_ARRAY) \
     && !defined(_ENABLE_ARRAYNEW) /* Digimars */ \
     && (defined(__BORLANDC__) && (__BORLANDC__ < 0x450) \
-        || (defined(__GNUC__) && \
-            (__GNUC__ < 2 || __GNUC__ == 2 && __GNUC_MINOR__ < 6)) \
+        || (defined(__GNUC__) && !GC_GNUC_PREREQ(2, 6)) \
         || (defined(_MSC_VER) && _MSC_VER <= 1020) \
         || (defined(__WATCOMC__) && __WATCOMC__ < 1050))
 # define GC_NO_OPERATOR_NEW_ARRAY
index f0d8189..45281c9 100644 (file)
 #include "gc.h"
 #include "gc_tiny_fl.h"
 
-#if __GNUC__ >= 3
+#if GC_GNUC_PREREQ(3, 0)
 # define GC_EXPECT(expr, outcome) __builtin_expect(expr,outcome)
   /* Equivalent to (expr), but predict that usually (expr)==outcome. */
 #else
 # define GC_EXPECT(expr, outcome) (expr)
-#endif /* __GNUC__ */
+#endif
 
 #ifndef GC_ASSERT
 # ifdef NDEBUG
@@ -48,7 +48,7 @@
 #endif
 
 #ifndef GC_PREFETCH_FOR_WRITE
-# if defined(__GNUC__) && __GNUC__ >= 3 && !defined(GC_NO_PREFETCH_FOR_WRITE)
+# if GC_GNUC_PREREQ(3, 0) && !defined(GC_NO_PREFETCH_FOR_WRITE)
 #   define GC_PREFETCH_FOR_WRITE(x) __builtin_prefetch((x), 1)
 # else
 #   define GC_PREFETCH_FOR_WRITE(x) (void)0
index fc79b5b..cd7ee5d 100644 (file)
 
 #include "gc.h"
 
-#if (__GNUC__ < 3)
-# include <stack>  // A more portable way to get stl_alloc.h .
-#else
+#if GC_GNUC_PREREQ(3, 0)
 # include <bits/stl_alloc.h>
 # ifndef __STL_BEGIN_NAMESPACE
-# define __STL_BEGIN_NAMESPACE namespace std {
-# define __STL_END_NAMESPACE };
+#   define __STL_BEGIN_NAMESPACE namespace std {
+#   define __STL_END_NAMESPACE };
 # endif
-#ifndef __STL_USE_STD_ALLOCATORS
-#define __STL_USE_STD_ALLOCATORS
-#endif
+# ifndef __STL_USE_STD_ALLOCATORS
+#   define __STL_USE_STD_ALLOCATORS
+# endif
+#else
+# include <stack>   // A more portable way to get stl_alloc.h file.
 #endif
 
 /* A hack to deal with gcc 3.1.  If you are using gcc3.1 and later,     */
 /* you should probably really use gc_allocator.h instead.               */
-#if defined (__GNUC__) && \
-    (__GNUC__ > 3 || (__GNUC__ == 3 && (__GNUC_MINOR__ >= 1)))
+#if GC_GNUC_PREREQ(3, 1)
 # define simple_alloc __simple_alloc
 #endif
 
index cbaeb37..0201447 100644 (file)
 # endif
 #endif
 
+/* Convenient internal macro to test version of Clang.  */
+#if defined(__clang__) && defined(__clang_major__)
+# define GC_CLANG_PREREQ(major, minor) \
+    ((__clang_major__ << 16) + __clang_minor__ >= ((major) << 16) + (minor))
+#else
+# define GC_CLANG_PREREQ(major, minor) 0 /* FALSE */
+#endif
+
 #ifndef GC_TINY_FL_H
 # include "../gc_tiny_fl.h"
 #endif
@@ -123,7 +131,7 @@ typedef char * ptr_t;   /* A generic pointer to which we can add        */
   /* located in the "extra" folder).                                    */
 # if defined(GC_DLL) && defined(__GNUC__) && !defined(MSWIN32) \
         && !defined(MSWINCE) && !defined(CYGWIN32)
-#   if (__GNUC__ >= 4) && !defined(GC_NO_VISIBILITY)
+#   if GC_GNUC_PREREQ(4, 0) && !defined(GC_NO_VISIBILITY)
       /* See the corresponding GC_API definition. */
 #     define GC_INNER __attribute__((__visibility__("hidden")))
 #   else
@@ -165,14 +173,14 @@ typedef char * ptr_t;   /* A generic pointer to which we can add        */
 #endif /* !GC_ATTR_NO_SANITIZE_MEMORY */
 
 #ifndef GC_ATTR_UNUSED
-# if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+# if GC_GNUC_PREREQ(3, 4)
 #   define GC_ATTR_UNUSED __attribute__((__unused__))
 # else
 #   define GC_ATTR_UNUSED /* empty */
 # endif
 #endif /* !GC_ATTR_UNUSED */
 
-#if __GNUC__ >= 3 && !defined(LINT2)
+#if GC_GNUC_PREREQ(3, 0) && !defined(LINT2)
 # define EXPECT(expr, outcome) __builtin_expect(expr,outcome)
   /* Equivalent to (expr), but predict that usually (expr)==outcome. */
 #else
@@ -183,17 +191,17 @@ typedef char * ptr_t;   /* A generic pointer to which we can add        */
   /* The "inline" keyword is determined by Autoconf AC_C_INLINE.    */
 # define GC_INLINE static inline
 #elif defined(_MSC_VER) || defined(__INTEL_COMPILER) || defined(__DMC__) \
-        || ((__GNUC__ >= 3) && defined(__STRICT_ANSI__)) \
+        || (GC_GNUC_PREREQ(3, 0) && defined(__STRICT_ANSI__)) \
         || defined(__WATCOMC__)
 # define GC_INLINE static __inline
-#elif (__GNUC__ >= 3) || defined(__sun)
+#elif GC_GNUC_PREREQ(3, 0) || defined(__sun)
 # define GC_INLINE static inline
 #else
 # define GC_INLINE static
 #endif
 
 #ifndef GC_ATTR_NOINLINE
-# if __GNUC__ >= 4
+# if GC_GNUC_PREREQ(4, 0)
 #   define GC_ATTR_NOINLINE __attribute__((__noinline__))
 # elif _MSC_VER >= 1400
 #   define GC_ATTR_NOINLINE __declspec(noinline)
@@ -205,7 +213,7 @@ typedef char * ptr_t;   /* A generic pointer to which we can add        */
 #ifndef GC_API_OSCALL
   /* This is used to identify GC routines called by name from OS.       */
 # if defined(__GNUC__)
-#   if (__GNUC__ >= 4) && !defined(GC_NO_VISIBILITY)
+#   if GC_GNUC_PREREQ(4, 0) && !defined(GC_NO_VISIBILITY)
       /* Same as GC_API if GC_DLL.      */
 #     define GC_API_OSCALL extern __attribute__((__visibility__("default")))
 #   else
@@ -2173,7 +2181,7 @@ void GC_noop6(word, word, word, word, word, word);
 GC_API void GC_CALL GC_noop1(word);
 
 #ifndef GC_ATTR_FORMAT_PRINTF
-# if defined(__GNUC__) && __GNUC__ >= 3
+# if GC_GNUC_PREREQ(3, 0)
 #   define GC_ATTR_FORMAT_PRINTF(spec_argnum, first_checked) \
         __attribute__((__format__(__printf__, spec_argnum, first_checked)))
 # else
@@ -2431,7 +2439,7 @@ GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str,
 #endif
 
 /* Runtime check for an argument declared as non-null is actually not null. */
-#if defined(__GNUC__) && __GNUC__ >= 4
+#if GC_GNUC_PREREQ(4, 0)
   /* Workaround tautological-pointer-compare Clang warning.     */
 # define NONNULL_ARG_NOT_NULL(arg) (*(volatile void **)&(arg) != NULL)
 #else
@@ -2603,8 +2611,7 @@ GC_INNER ptr_t GC_store_debug_info(ptr_t p, word sz, const char *str,
 /* Some convenience macros for cancellation support. */
 #if defined(CANCEL_SAFE)
 # if defined(GC_ASSERTIONS) && (defined(USE_COMPILER_TLS) \
-     || (defined(LINUX) && !defined(ARM32) \
-              && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) \
+     || (defined(LINUX) && !defined(ARM32) && GC_GNUC_PREREQ(3, 3)) \
      || defined(HPUX) /* and probably others ... */))
     extern __thread unsigned char GC_cancel_disable_count;
 #   define NEED_CANCEL_DISABLE_COUNT
index 6016b47..3364acf 100644 (file)
  * allocation.
  */
 
-/* If we are using a recent version of gcc, we can use                    */
-/* __builtin_unwind_init() to push the relevant registers onto the stack. */
-# if defined(__GNUC__) && ((__GNUC__ >= 3) \
-                           || (__GNUC__ == 2 && __GNUC_MINOR__ >= 8)) \
+/* If available, we can use __builtin_unwind_init() to push the     */
+/* relevant registers onto the stack.                               */
+# if GC_GNUC_PREREQ(2, 8) \
      && !defined(__INTEL_COMPILER) && !defined(__PATHCC__) \
      && !defined(__FUJITSU) /* for FX10 system */ \
      && !(defined(POWERPC) && defined(DARWIN)) /* for MacOS X 10.3.9 */ \
              extern int _end[];
 #            define DATAEND ((ptr_t)(_end))
 #            if defined(PLATFORM_ANDROID) && !defined(GC_NO_SIGSETJMP) \
-                && !(__ANDROID_API__ >= 18 || __GNUC__ > 4 \
-                     || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) \
-                     || __clang_major__ > 3 \
-                     || (__clang_major__ == 3 && __clang_minor__ >= 2))
+                && !(GC_GNUC_PREREQ(4, 8) || GC_CLANG_PREREQ(3, 2) \
+                     || __ANDROID_API__ >= 18)
                /* Older Android NDK releases lack sigsetjmp in x86 libc */
                /* (setjmp is used instead to find data_start).  The bug */
                /* is fixed in Android NDK r8e (so, ok to use sigsetjmp  */
                 /* STACKBOTTOM and DATASTART are handled specially in   */
                 /* os_dep.c.                                            */
 #       if !defined(__GNUC__) || defined(__INTEL_COMPILER) \
-           || __GNUC__ >= 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)
+           || GC_GNUC_PREREQ(4, 7)
           /* Older GCC has not supported SetUnhandledExceptionFilter    */
           /* properly on x64 (e.g. SEH unwinding information missed).   */
 #         define MPROTECT_VDB
 #endif
 
 #ifndef PREFETCH
-# if defined(__GNUC__) && __GNUC__ >= 3 && !defined(NO_PREFETCH)
+# if GC_GNUC_PREREQ(3, 0) && !defined(NO_PREFETCH)
 #   define PREFETCH(x) __builtin_prefetch((x), 0, 0)
 # else
 #   define PREFETCH(x) (void)0
 #endif
 
 #ifndef GC_PREFETCH_FOR_WRITE
-# if defined(__GNUC__) && __GNUC__ >= 3 && !defined(GC_NO_PREFETCH_FOR_WRITE)
+# if GC_GNUC_PREREQ(3, 0) && !defined(GC_NO_PREFETCH_FOR_WRITE)
 #   define GC_PREFETCH_FOR_WRITE(x) __builtin_prefetch((x), 1)
 # else
 #   define GC_PREFETCH_FOR_WRITE(x) (void)0
index 3b44a1e..5b9bec3 100644 (file)
@@ -36,7 +36,7 @@
     && !defined(USE_WIN32_COMPILER_TLS) && !defined(USE_COMPILER_TLS) \
     && !defined(USE_CUSTOM_SPECIFIC)
 # if defined(MSWIN32) || defined(MSWINCE) || defined(CYGWIN32)
-#   if defined(CYGWIN32) && (__GNUC__ >= 4)
+#   if defined(CYGWIN32) && GC_GNUC_PREREQ(4, 0)
 #     if defined(__clang__)
         /* As of Cygwin clang3.5.2, thread-local storage is unsupported.    */
 #       define USE_PTHREAD_SPECIFIC
 #     define USE_WIN32_COMPILER_TLS
 #   endif /* !GNU */
 # elif (defined(LINUX) && !defined(ARM32) && !defined(AVR32) \
-         && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)) \
+         && GC_GNUC_PREREQ(3, 3) \
          && !(defined(__clang__) && defined(PLATFORM_ANDROID))) \
        || (defined(PLATFORM_ANDROID) && !defined(__clang__) \
-            && defined(ARM32) \
-            && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)))
+            && defined(ARM32) && GC_GNUC_PREREQ(4, 6))
           /* As of Android NDK r10e, Clang cannot find __tls_get_addr.  */
 #   define USE_COMPILER_TLS
 # elif defined(GC_DGUX386_THREADS) || defined(GC_OSF1_THREADS) \
diff --git a/mark.c b/mark.c
index 9b1d0fe..d568213 100644 (file)
--- a/mark.c
+++ b/mark.c
@@ -531,9 +531,7 @@ static void alloc_mark_stack(size_t);
 
       ext_ex_regn er;
 
-#     if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) \
-         || __clang_major__ > 3 \
-         || (__clang_major__ == 3 && __clang_minor__ >= 3)
+#     if GC_GNUC_PREREQ(4, 7) || GC_CLANG_PREREQ(3, 3)
 #       pragma GCC diagnostic push
         /* Suppress "taking the address of label is non-standard" warning. */
 #       if defined(__clang__)
index a06ce89..eb2e0e9 100644 (file)
@@ -391,7 +391,7 @@ STATIC void GC_remove_tmp_roots(void)
 GC_INNER ptr_t GC_approx_sp(void)
 {
     volatile word sp;
-#   if defined(__GNUC__) && (__GNUC__ >= 4)
+#   if GC_GNUC_PREREQ(4, 0)
         sp = (word)__builtin_frame_address(0);
 #   else
         sp = (word)&sp;
index 1a6c5b6..3d6be9a 100644 (file)
@@ -70,7 +70,7 @@ extern "C" {
                     __LINE__ ); \
         exit( 1 ); }
 
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)
+#if GC_GNUC_PREREQ(3, 4)
 # define ATTR_UNUSED __attribute__((__unused__))
 #else
 # define ATTR_UNUSED /* empty */
index 99f1f7d..987599e 100644 (file)
@@ -62,7 +62,7 @@ struct {
 
 word nested_sp(void)
 {
-# if defined(__GNUC__) && (__GNUC__ >= 4)
+# if GC_GNUC_PREREQ(4, 0)
     return (word)__builtin_frame_address(0);
 # else
     volatile word sp;