]> pd.if.org Git - pdclib/commitdiff
_PDCLIB_aux.h: Better detection of Clang and GCC features
authorOwen Shepherd <owen.shepherd@e43.eu>
Wed, 26 Dec 2012 18:51:35 +0000 (18:51 +0000)
committerOwen Shepherd <owen.shepherd@e43.eu>
Wed, 26 Dec 2012 18:51:35 +0000 (18:51 +0000)
internals/_PDCLIB_aux.h

index 986807e18b7d818f2e04ae449c731a17b9cd7bc6..bc13897a7d4254383cc3890499c69ba7459f4a09 100644 (file)
    #error Unsupported _ _cplusplus (__cplusplus) (supported: ISO/IEC 14882:1997, ISO/IEC 14882:2011).
 #endif
 
+#ifndef __STDC_HOSTED__
+    #error Compiler does not define _ _STDC_HOSTED_ _ (not standard-compliant)!
+#elif __STDC_HOSTED__ == 0
+    #define _PDCLIB_HOSTED 0
+#elif __STDC_HOSTED__ == 1
+    #define _PDCLIB_HOSTED 1
+#else
+    #error Compiler does not define _ _STDC_HOSTED_ _ to 0 or 1 (not standard-compliant)!
+#endif
+
+#ifdef __cplusplus
+    #define _PDCLIB_BEGIN_EXTERN_C extern "C" {
+    #define _PDCLIB_END_EXTERN_C }
+    typedef bool _PDCLIB_bool;
+#else
+    #define _PDCLIB_BEGIN_EXTERN_C
+    #define _PDCLIB_END_EXTERN_C
+    typedef _Bool _PDCLIB_bool;
+#endif
+
+/* Clang style feature detection macros
+ * Note: It is common to #define __has_feature(0) if undefined so the presence
+ * of this macro does not guarantee it to be working
+ */
+
+#ifdef __has_feature
+   #define _PDCLIB_HAS_FEATURE(x) __has_feature(x)
+#else
+   #define _PDCLIB_HAS_FEATURE(x) (0)
+#endif
+
+#ifdef __has_extension
+   #define _PDCLIB_HAS_EXTENSION(x) __has_extension(x)
+#else
+   // Older versions of Clang use __has_feature instead
+   #define _PDCLIB_HAS_EXTENSION(x) _PDCLIB_HAS_FEATURE(x)
+#endif
+
+#ifdef __has_builtin
+   #define _PDCLIB_HAS_BUILTIN(x) __has_builtin(x)
+#else
+   #define _PDCLIB_HAS_BUILTIN(x) (0)
+#endif
+
+#ifdef __has_attribute
+   #define _PDCLIB_HAS_ATTRIBUTE(x) __has_builtin(x)
+#else
+   #define _PDCLIB_HAS_ATTRIBUTE(x) (0)
+#endif
+
+/* GCC feature detection macros */
+
+#if defined(__GNUC__)
+    #define _PDCLIB_GCC_MIN(maj, min) \
+        ((__GNUC__ > maj) || (__GNUC__ == maj && __GNUC_MINOR__ >= min))
+#else
+    #define _PDCLIB_GCC_MIN(maj, min) (0)
+#endif
+
+/* Hybrid GCC/Clang feature detection macros */
+#define _PDCLIB_GCC_FEATURE(x, gccmaj, gccmin) \
+        (_PDCLIB_HAS_FEATURE(x) || _PDCLIB_GCC_MIN(gccmin, gccmaj))
+
+#define _PDCLIB_GCC_EXTENSION(x, gccmaj, gccmin) \
+        (_PDCLIB_HAS_EXTENSION(x) || _PDCLIB_GCC_MIN(gccmin, gccmaj))
+
+#define _PDCLIB_GCC_BUILTIN(x, gccmaj, gccmin) \
+        (_PDCLIB_HAS_BUILTIN(x) || _PDCLIB_GCC_MIN(gccmin, gccmaj))
+
+#define _PDCLIB_GCC_ATTRIBUTE(x, gccmaj, gccmin) \
+        (_PDCLIB_HAS_ATTRIBUTE(x) || _PDCLIB_GCC_MIN(gccmin, gccmaj))
+
+/* Extension & Language feature detection */
+
 #if _PDCLIB_C_VERSION >= 1999 || defined(__cplusplus)
     #ifndef __cplusplus
         #define _PDCLIB_restrict restrict
   #define _PDCLIB_noexcept
 #endif
 
-#if _PDCLIB_CXX_VERSION >= 2011
-  // Hold off on C++ attribute syntax for now
-  // #define _PDCLIB_noreturn [[noreturn]]
-#elif _PDCLIB_C_VERSION >= 2011
+#if _PDCLIB_CXX_VERSION >= 2011 && _PDCLIB_GCC_FEATURE(cxx_attributes, 4, 8)
+    #define _PDCLIB_noreturn [[noreturn]]
+#elif _PDCLIB_C_VERSION >= 2011 && _PDCLIB_GCC_FEATURE(c_noreturn, 4, 7)
     #define _PDCLIB_noreturn _Noreturn
 #endif
 
    #define _PDCLIB_IMPORT __declspec(dllimport)
 #endif
 
-#ifdef __GNUC__
-    #ifndef _PDCLIB_EXPORT
-        #define _PDCLIB_EXPORT __attribute__((__visibility__("protected")))
-    #endif
-
-    #ifndef _PDCLIB_IMPORT
-        #define _PDCLIB_IMPORT
-    #endif
+#if !defined(_PDCLIB_EXPORT) && _PDCLIB_GCC_ATTRIBUTE(__visibility__, 4, 0)
+    #define _PDCLIB_EXPORT __attribute__((__visibility__("protected")))
+#endif
 
-    #ifndef _PDCLIB_HIDDEN
-        #define _PDCLIB_HIDDEN __attribute__((__visibility__("hidden")))
-    #endif
+#if !defined(_PDCLIB_HIDDEN) && _PDCLIB_GCC_ATTRIBUTE(__visibility__, 4, 0)
+    #define _PDCLIB_HIDDEN __attribute__((__visibility__("hidden")))
+#endif
 
-    #ifndef _PDCLIB_nothrow
-      #define _PDCLIB_nothrow __attribute__((__nothrow__))
-      #define _PDCLIB_noexcept
-    #endif
+#if !defined(_PDCLIB_nothrow) && _PDCLIB_GCC_ATTRIBUTE(__nothrow__, 4, 0)
+    #define _PDCLIB_nothrow __attribute__((__nothrow__))
+    #define _PDCLIB_noexcept
+#endif
 
-    #ifndef _PDCLIB_restrict
-        #define _PDCLIB_restrict __restrict
-    #endif
+#if !defined(_PDCLIB_restrict) && _PDCLIB_GCC_MIN(3, 0)
+    #define _PDCLIB_restrict __restrict
+#endif
 
-    #ifndef _PDCLIB_inline
-        #define _PDCLIB_inline __inline
-    #endif
+#if !defined(_PDCLIB_inline) && _PDCLIB_GCC_MIN(3, 0)
+    #define _PDCLIB_inline __inline
+#endif
 
-    #ifndef _PDCLIB_noreturn
+#if !defined(_PDCLIB_noreturn) && _PDCLIB_GCC_ATTRIBUTE(__noreturn__, 3, 0)
     /* If you don't use __noreturn__, then stdnoreturn.h will break things! */
-        #define _PDCLIB_noreturn __attribute__((__noreturn__))
-    #endif
+    #define _PDCLIB_noreturn __attribute__((__noreturn__))
+#endif
 
-    #ifndef _PDCLIB_DEPRECATED
-        #define _PDCLIB_DEPRECATED __attribute__ ((deprecated))
-    #endif
+#if !defined(_PDCLIB_DEPRECATED) && _PDCLIB_GCC_ATTRIBUTE(__deprecated__, 3, 0)
+    #define _PDCLIB_DEPRECATED __attribute__ ((__deprecated__))
 #endif
 
+/* No-op fallbacks */
+
 #ifndef _PDCLIB_nothrow
   #define _PDCLIB_nothrow
   #define _PDCLIB_noexcept
     #define _PDCLIB_DEPRECATED
 #endif
 
-#ifndef __STDC_HOSTED__
-#error Compiler does not define _ _STDC_HOSTED_ _ (not standard-compliant)!
-#elif __STDC_HOSTED__ == 0
-#define _PDCLIB_HOSTED 0
-#elif __STDC_HOSTED__ == 1
-#define _PDCLIB_HOSTED 1
-#else
-#error Compiler does not define _ _STDC_HOSTED_ _ to 0 or 1 (not standard-compliant)!
-#endif
-
-#ifdef __cplusplus
-    #define _PDCLIB_BEGIN_EXTERN_C extern "C" {
-    #define _PDCLIB_END_EXTERN_C }
-  typedef bool _PDCLIB_bool;
-#else
-  #define _PDCLIB_BEGIN_EXTERN_C
-  #define _PDCLIB_END_EXTERN_C
-  typedef _Bool _PDCLIB_bool;
-#endif
-
 /*#if _PDCLIB_C_VERSION != 1999
 #error PDCLib might not be fully conforming to either C89 or C95 prior to v2.x.
 #endif*/